summaryrefslogtreecommitdiff
path: root/kernel_drivers
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2013-01-17 09:59:58 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2013-01-17 11:00:24 +0100
commit3ee6002f301a2e03b411d79c0e67981161dd2726 (patch)
tree38b4c26918007502e62a0f29d8b8bcf2587df3b9 /kernel_drivers
parente30de2e6886cbecc72b6364d78a0415936e05409 (diff)
add dove gc600 driver
Diffstat (limited to 'kernel_drivers')
-rw-r--r--kernel_drivers/Kconfig17
-rw-r--r--kernel_drivers/Makefile2
-rw-r--r--kernel_drivers/README.md7
-rw-r--r--kernel_drivers/gc600_driver_dove/Makefile2
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/Android.mk.def92
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile187
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile.linux35
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.c3695
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.h94
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/makefile.linux55
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/common.node45
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/common.target116
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/config27
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/Kbuild134
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal.h2071
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_base.h2828
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_compiler.h1841
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_driver.h640
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_dump.h90
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_engine.h1673
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_enum.h565
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_mem.h472
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_options.h532
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_profiler.h221
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_raster.h807
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_types.h601
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.c1288
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.h427
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_command.c2370
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_event.c1746
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_heap.c1079
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_mmu.c962
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_precomp.h32
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_video_memory.c1783
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/makefile.linux61
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/makefile.linux46
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_debug.c453
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.c1251
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.h225
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_driver.c1262
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.c418
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.h93
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.c7383
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.h122
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/init_ko.sh23
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/linux1
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile35
-rw-r--r--kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile.linux.def358
-rw-r--r--kernel_drivers/gc600_driver_dove/readme79
49 files changed, 38327 insertions, 19 deletions
diff --git a/kernel_drivers/Kconfig b/kernel_drivers/Kconfig
deleted file mode 100644
index 2f7b88a..0000000
--- a/kernel_drivers/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-choice
- prompt "Vivante GPUs"
- depends on ARCH_DMW
- default GPU_VIVANTE_V4
- optional
-
-config GPU_VIVANTE_V2
- boolean "Version 2.x"
-
-config GPU_VIVANTE_V4
- boolean "Version 4.x"
-
-endchoice
-
-source "drivers/gpu/vivante/v2/Kconfig"
-source "drivers/gpu/vivante/v4/Kconfig"
-
diff --git a/kernel_drivers/Makefile b/kernel_drivers/Makefile
deleted file mode 100644
index dbafd97..0000000
--- a/kernel_drivers/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_GPU_VIVANTE_V2) += v2/
-obj-$(CONFIG_GPU_VIVANTE_V4) += v4/
diff --git a/kernel_drivers/README.md b/kernel_drivers/README.md
new file mode 100644
index 0000000..8a157ca
--- /dev/null
+++ b/kernel_drivers/README.md
@@ -0,0 +1,7 @@
+This collection of kernel drivers is provided for information only. I have not tried building them.
+
+It is likely that this is possible, but it may require some serious work porting either of them to your version of Linux.
+
+If you have a device with Linux or Android with a Vivante GPU, your best bet is to find (or ask for) the GPL drivers for your specific device.
+These may be older (or newer) than the ones provided here but at least you're sure they work with your device.
+
diff --git a/kernel_drivers/gc600_driver_dove/Makefile b/kernel_drivers/gc600_driver_dove/Makefile
new file mode 100644
index 0000000..f2c82a6
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/Makefile
@@ -0,0 +1,2 @@
+obj-y += galcore_ko_src/
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/Android.mk.def b/kernel_drivers/gc600_driver_dove/galcore_ko_src/Android.mk.def
new file mode 100644
index 0000000..344905c
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/Android.mk.def
@@ -0,0 +1,92 @@
+##############################################################################
+#
+# Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+#
+# The material in this file is confidential and contains trade secrets
+# of Vivante Corporation. This is proprietary information owned by
+# Vivante Corporation. No part of this work may be disclosed,
+# reproduced, copied, transmitted, or used in any way for any purpose,
+# without the express written permission of Vivante Corporation.
+#
+##############################################################################
+#
+#
+##############################################################################
+
+
+#
+# Common include file for Android build
+#
+
+################################################################
+# Options.
+
+# CPU arch type. Could be 'arm' or 'mips'
+ARCH_TYPE ?= arm
+FIXED_ARCH_TYPE ?=
+
+# CPU arch type.
+GPU_TYPE ?= XAQ2
+
+# Kernel directory
+export KERNEL_DIR ?= $(ANDROID_BUILD_TOP)/kernel/kernel
+
+# Cross compiler for building kernel module
+export CROSS_COMPILE ?= arm-eabi-
+
+# Driver build options.
+NO_DMA_COHERENT ?= 1
+ENABLE_GPU_CLOCK_BY_DRIVER ?= 1
+ENABLE_ARM_L2_CACHE ?= 1
+USE_PLATFORM_DRIVER ?= 1
+USE_NEW_LINUX_SIGNAL ?= 0
+USE_PROFILER ?= 0
+
+
+################################################################
+# Target INCLUDES.
+
+C_INCLUDES := $(TARGET_C_INCLUDES) $(filter-out %/opengl/include,$(TARGET_PROJECT_INCLUDES))
+
+
+################################################################
+# Target CFLAGS.
+
+CFLAGS := $(TARGET_GLOBAL_CFLAGS) $(TARGET_$(ARCH_TYPE)_CFLAGS)
+
+CFLAGS += -DANDROID=1 -DEGL_API_ANDROID=1 -DUSE_VDK=0 -DLINUX
+CFLAGS += -fno-strict-aliasing -fno-short-enums
+
+ifeq ($(PLATFORM_SDK_VERSION), 7)
+CFLAGS += -DANDROID_VERSION_ECLAIR
+else
+$(error This makefile is only for eclair)
+endif
+
+ifeq ($(USE_PROFILER), 1)
+CFLAGS += -DVIVANTE_PROFILER=1
+else
+CFLAGS += -DVIVANTE_PROFILER=0
+endif
+
+
+################################################################
+# Tag.
+
+TAG := VIVANTE
+
+################################################################
+# Variables.
+
+export AQROOT := $(abspath $(call my-dir))
+export AQARCH := $(AQROOT)/arch/$(GPU_TYPE)
+
+GC_HAL_USER_DIR := hal/user
+GC_HAL_ARCH_USER_DIR := arch/$(GPU_TYPE)/hal/user
+GC_HAL_OS_USER_DIR := hal/os/linux/user
+GC_HAL_OPTIMIZER_DIR := hal/optimizer
+GC_EGL_DIR := driver/openGL/egl
+GC_GLES11_DIR := driver/openGL/libGLESv11
+GC_GLESv2X_DIR := driver/openGL/libGLESv2x/driver
+GC_GLESv2SC_DIR := driver/openGL/libGLESv2x/compiler/libGLESv2SC
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile b/kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile
new file mode 100644
index 0000000..779d08c
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile
@@ -0,0 +1,187 @@
+PWD := $(srctree)/arch/arm/mach-dove/gc600_driver_dove/galcore_ko_src
+
+ARCH=arm
+#CROSS_COMPILE ?= /usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linux-gnueabi-
+GPU_TYPE = unified
+KERNEL_DIR = ${PWD}/linux
+
+DEBUG = 0
+ABI = aapcs-linux
+ENABLE_ARM_L2_CACHE = 1
+NO_DMA_COHERENT = 1
+CONFIG_DOVE_GPU = 1
+ANDROID = 0
+ENABLE_GPU_CLOCK_BY_DRIVER = 0
+
+BUILD_OPTIONS = DEBUG=${DEBUG}
+BUILD_OPTIONS += ABI=${ABI}
+BUILD_OPTIONS += ENABLE_ARM_L2_CACHE=${ENABLE_ARM_L2_CACHE}
+BUILD_OPTIONS += NO_DMA_COHERENT=${NO_DMA_COHERENT}
+BUILD_OPTIONS += CONFIG_DOVE_GPU=${CONFIG_DOVE_GPU}
+BUILD_OPTIONS += ANDROID=${ANDROID}
+BUILD_OPTIONS += ENABLE_GPU_CLOCK_BY_DRIVER=${ENABLE_GPU_CLOCK_BY_DRIVER}
+
+#AQROOT := ${PWD}
+AQROOT := $(srctree)/arch/arm/mach-dove/gc600_driver_dove/galcore_ko_src
+AQARCH=${PWD}/arch/${GPU_TYPE}
+GCX00_COMPILE_ENV = ${BUILD_OPTIONS} ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE}\
+ AQROOT=${PWD} AQARCH=${PWD}/arch/${GPU_TYPE} KERNEL_DIR=${KERNEL_DIR}
+
+# from Kbuild
+include $(AQROOT)/config
+
+DRIVER_OUT_DIR = hal/driver
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR := hal/os/linux/kernel
+ARCH_KERNEL_DIR := arch/$(notdir $(AQARCH))/hal/kernel
+HAL_KERNEL_DIR := hal/kernel
+
+EXTRA_CFLAGS += -Werror
+
+OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_debug.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_os.o
+
+ifeq ($(USE_3D_VG), 1)
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
+
+else
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o \
+ $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_command.o
+
+endif
+
+ifeq ($(KERNELRELEASE), )
+
+.PHONY: all clean install
+
+# Define targets.
+all:
+ @mkdir -p $(DRIVER_OUT_DIR)
+ @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+
+clean:
+ @rm -rf $(OBJS)
+ @rm -rf $(DRIVER_OUT_DIR)
+ @rm -rf modules.order Module.symvers
+
+install: all
+ @mkdir -p $(SDK_DIR)/drivers
+ @cp $(DRIVER_OUT_DIR)/galcore.ko $(SDK_DIR)/drivers
+
+else
+
+
+EXTRA_CFLAGS += -DLINUX -DDRIVER
+
+ifeq ($(ENUM_WORKAROUND), 1)
+EXTRA_CFLAGS += -DENUM_WORKAROUND=1
+else
+EXTRA_CFLAGS += -DENUM_WORKAROUND=0
+endif
+
+ifeq ($(FLAREON),1)
+EXTRA_CFLAGS += -DFLAREON
+endif
+
+ifeq ($(DEBUG), 1)
+EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
+else
+EXTRA_CFLAGS += -DDBG=0
+endif
+
+ifeq ($(NO_DMA_COHERENT), 1)
+EXTRA_CFLAGS += -DNO_DMA_COHERENT
+endif
+
+ifeq ($(ENABLE_ARM_L2_CACHE), 1)
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=1
+else
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=0
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifneq ($(USE_PLATFORM_DRIVER), 0)
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
+else
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
+endif
+
+ifeq ($(USE_PROFILER), 1)
+ EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
+else
+ EXTRA_CFLAGS += -DVIVANTE_PROFILER=0
+endif
+
+ifeq ($(USE_MRVL_PROFILER),1)
+ EXTRA_CFLAGS += -DMRVL_BENCH=1
+else
+ EXTRA_CFLAGS += -DMRVL_BENCH=0
+endif
+
+
+ifeq ($(ANDROID), 1)
+EXTRA_CFLAGS += -DANDROID=1
+endif
+
+ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
+else
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
+endif
+
+ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
+else
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
+endif
+
+ifeq ($(NO_USER_DIRECT_ACCESS_FROM_KERNEL), 1)
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=1
+else
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=0
+endif
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/cmodel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/user
+
+obj-y = galcore.o
+galcore-objs = $(OBJS)
+
+endif
+
+
+#all:
+# make ${GCX00_COMPILE_ENV} -C ${PWD} -f Kbuild
+# cp $(PWD)/hal/driver/galcore.ko .
+
+#clean:
+# make ${GCX00_COMPILE_ENV} -C ${PWD} -f Kbuild clean
+
+
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile.linux b/kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile.linux
new file mode 100644
index 0000000..0301743
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/Makefile.linux
@@ -0,0 +1,35 @@
+PWD := $(shell pwd)
+
+ARCH=arm
+CROSS_COMPILE = arm-marvell-linux-gnueabi-
+GPU_TYPE = Unified
+KERNEL_DIR = ${PWD}/linux
+
+DEBUG = 0
+ABI = aapcs-linux
+ENABLE_ARM_L2_CACHE = 1
+NO_DMA_COHERENT = 1
+CONFIG_DOVE_GPU = 1
+ANDROID = 0
+ENABLE_GPU_CLOCK_BY_DRIVER = 0
+
+BUILD_OPTIONS = DEBUG=${DEBUG}
+BUILD_OPTIONS += ABI=${ABI}
+BUILD_OPTIONS += ENABLE_ARM_L2_CACHE=${ENABLE_ARM_L2_CACHE}
+BUILD_OPTIONS += NO_DMA_COHERENT=${NO_DMA_COHERENT}
+BUILD_OPTIONS += CONFIG_DOVE_GPU=${CONFIG_DOVE_GPU}
+BUILD_OPTIONS += ANDROID=${ANDROID}
+BUILD_OPTIONS += ENABLE_GPU_CLOCK_BY_DRIVER=${ENABLE_GPU_CLOCK_BY_DRIVER}
+
+GCX00_COMPILE_ENV = ${BUILD_OPTIONS} ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE}\
+ AQROOT=${PWD} AQARCH=${PWD}/arch/${GPU_TYPE} KERNEL_DIR=${KERNEL_DIR}
+
+all:
+ make ${GCX00_COMPILE_ENV} -C ${PWD} -f Kbuild
+ cp $(PWD)/hal/driver/galcore.ko .
+
+clean:
+ make ${GCX00_COMPILE_ENV} -C ${PWD} -f Kbuild clean
+
+
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.c
new file mode 100644
index 0000000..a70f94d
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.c
@@ -0,0 +1,3695 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+
+#include <linux/delay.h>
+
+#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+static gceSTATUS
+_IdentifyHardware(
+ IN gckOS Os,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32_PTR ChipRevision,
+ OUT gctUINT32_PTR ChipFeatures,
+ OUT gctUINT32_PTR ChipMinorFeatures0,
+ OUT gctUINT32_PTR ChipMinorFeatures1
+ )
+{
+ gceSTATUS status;
+ gctUINT32 chipIdentity;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x00018, &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ *ChipModel = gcv500;
+ *ChipRevision = ( ((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os,
+ 0x00020,
+ (gctUINT32_PTR) ChipModel));
+
+ /* !!!! HACK ALERT !!!! */
+ /* Because people change device IDs without letting software know
+ ** about it - here is the hack to make it all look the same. Only
+ ** for GC400 family. Next time - TELL ME!!! */
+ if ((*ChipModel & 0xFF00) == 0x0400)
+ {
+ *ChipModel &= 0x0400;
+ }
+
+ /* Read CHIP_REV register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x00024, ChipRevision));
+
+ if ((*ChipModel == gcv300)
+ && (*ChipRevision == 0x2201)
+ )
+ {
+ gctUINT32 date, time;
+
+ /* Read date and time registers. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x00028, &date));
+
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x0002C, &time));
+
+ if ((date == 0x20080814) && (time == 0x12051100))
+ {
+ /* This IP has an ECO; put the correct revision in it. */
+ *ChipRevision = 0x1051;
+ }
+ }
+ }
+
+ /* Read chip feature register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x0001C, ChipFeatures));
+
+ /* Disable fast clear on GC700. */
+ if (*ChipModel == gcv700)
+ {
+ *ChipFeatures = ((((gctUINT32) (*ChipFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ if (((*ChipModel == gcv500) && (*ChipRevision < 2))
+ || ((*ChipModel == gcv300) && (*ChipRevision < 0x2000))
+ )
+ {
+ /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these registers. */
+ *ChipMinorFeatures0 = 0;
+ *ChipMinorFeatures1 = 0;
+ }
+ else
+ {
+ /* Read chip minor feature register #0. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os,
+ 0x00034,
+ ChipMinorFeatures0));
+
+ if (((((gctUINT32) (*ChipMinorFeatures0)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))))
+ )
+ {
+ /* Read chip minor featuress register #1. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os,
+ 0x00074,
+ ChipMinorFeatures1));
+ }
+ else
+ {
+ /* Chip doesn't has minor features register #1. */
+ *ChipMinorFeatures1 = 0;
+ }
+ }
+
+#if MRVL_DISABLE_FASTCLEAR
+ *ChipFeatures = *ChipFeatures & ~0x00000001;
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ChipModel=%x *ChipRevision=%x *ChipFeatures=%08x "
+ "*ChipMinorFeatures0=%08X *ChipMinorFeatures1=%08x",
+ *ChipModel, *ChipRevision, *ChipFeatures,
+ *ChipMinorFeatures0, *ChipMinorFeatures1);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_GetChipSpecs(
+ IN gckHARDWARE Hardware
+ )
+{
+ gctUINT32 streamCount = 0;
+ gctUINT32 registerMax = 0;
+ gctUINT32 threadCount = 0;
+ gctUINT32 shaderCoreCount = 0;
+ gctUINT32 vertexCacheSize = 0;
+ gctUINT32 vertexOutputBufferSize = 0;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ if (((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
+ {
+ gctUINT32 specs;
+
+ /* Read gcChipSpecs register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os, 0x00048, &specs));
+
+ /* Handy macro to improve reading. */
+#define gcmSPEC_FIELD(field) \
+ ( ((((gctUINT32) (specs)) >> (0 ? GC_CHIP_SPECS_field)) & ((gctUINT32) ((((1 ? GC_CHIP_SPECS_field) - (0 ? GC_CHIP_SPECS_field) + 1) == 32) ? ~0 : (~(~0 << ((1 ? GC_CHIP_SPECS_field) - (0 ? GC_CHIP_SPECS_field) + 1)))))) )
+
+ /* Extract the fields. */
+ streamCount = ( ((((gctUINT32) (specs)) >> (0 ? 3:0)) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1)))))) );
+ registerMax = ( ((((gctUINT32) (specs)) >> (0 ? 7:4)) & ((gctUINT32) ((((1 ? 7:4) - (0 ? 7:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:4) - (0 ? 7:4) + 1)))))) );
+ threadCount = ( ((((gctUINT32) (specs)) >> (0 ? 11:8)) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1)))))) );
+ shaderCoreCount = ( ((((gctUINT32) (specs)) >> (0 ? 24:20)) & ((gctUINT32) ((((1 ? 24:20) - (0 ? 24:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:20) - (0 ? 24:20) + 1)))))) );
+ vertexCacheSize = ( ((((gctUINT32) (specs)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
+ vertexOutputBufferSize = ( ((((gctUINT32) (specs)) >> (0 ? 31:28)) & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1)))))) );
+ }
+
+ /* Get the stream count. */
+ Hardware->streamCount = (streamCount != 0)
+ ? streamCount
+ : (Hardware->chipModel >= gcv1000) ? 4 : 1;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: streamCount=%u%s",
+ Hardware->streamCount,
+ (streamCount == 0) ? " (default)" : "");
+
+ /* Get the vertex output buffer size. */
+ Hardware->vertexOutputBufferSize = (vertexOutputBufferSize != 0)
+ ? 1 << vertexOutputBufferSize
+ : (Hardware->chipModel == gcv400)
+ ? (Hardware->chipRevision < 0x4000) ? 512
+ : (Hardware->chipRevision < 0x4200) ? 256
+ : 128
+ : (Hardware->chipModel == gcv530)
+ ? (Hardware->chipRevision < 0x4200) ? 512
+ : 128
+ : 512;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: vertexOutputBufferSize=%u%s",
+ Hardware->vertexOutputBufferSize,
+ (vertexOutputBufferSize == 0) ? " (default)" : "");
+
+ /* Get the maximum number of threads. */
+ Hardware->threadCount = (threadCount != 0)
+ ? 1 << threadCount
+ : (Hardware->chipModel == gcv400) ? 64
+ : (Hardware->chipModel == gcv500) ? 128
+ : (Hardware->chipModel == gcv530) ? 128
+ : 256;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: threadCount=%u%s",
+ Hardware->threadCount,
+ (threadCount == 0) ? " (default)" : "");
+
+ /* Get the number of shader cores. */
+ Hardware->shaderCoreCount = (shaderCoreCount != 0)
+ ? shaderCoreCount
+ : (Hardware->chipModel >= gcv1000) ? 2
+ : 1;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: shaderCoreCount=%u%s",
+ Hardware->shaderCoreCount,
+ (shaderCoreCount == 0) ? " (default)" : "");
+
+ /* Get the vertex cache size. */
+ Hardware->vertexCacheSize = (vertexCacheSize != 0)
+ ? vertexCacheSize
+ : 8;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: vertexCacheSize=%u%s",
+ Hardware->vertexCacheSize,
+ (vertexCacheSize == 0) ? " (default)" : "");
+
+ /* Get the maximum number of temporary registers. */
+ Hardware->registerMax = (registerMax != 0)
+ ? 1 << registerMax
+ : (Hardware->chipModel == gcv400) ? 32
+ : 64;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: registerMax=%u%s",
+ Hardware->registerMax,
+ (registerMax == 0) ? " (default)" : "");
+
+
+ gckOS_Log(_GFX_LOG_NOTIFY_,"[galcore] streamCount = %d\n", Hardware->streamCount);
+ gckOS_Log(_GFX_LOG_NOTIFY_,"[galcore] registerMax = %d\n", Hardware->registerMax);
+ gckOS_Log(_GFX_LOG_NOTIFY_,"[galcore] threadCount = %d\n", Hardware->threadCount);
+ gckOS_Log(_GFX_LOG_NOTIFY_,"[galcore] shaderCoreCount = %d\n", Hardware->shaderCoreCount);
+ gckOS_Log(_GFX_LOG_NOTIFY_,"[galcore] vertexCacheSize = %d\n", Hardware->vertexCacheSize);
+ gckOS_Log(_GFX_LOG_NOTIFY_,"[galcore] vertexOutputBufferSize = %d\n", Hardware->vertexOutputBufferSize);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/******************************************************************************\
+****************************** gckHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHARDWARE_Construct
+**
+** Construct a new gckHARDWARE object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an initialized gckOS object.
+**
+** OUTPUT:
+**
+** gckHARDWARE * Hardware
+** Pointer to a variable that will hold the pointer to the gckHARDWARE
+** object.
+*/
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckHARDWARE * Hardware
+ )
+{
+ gckHARDWARE hardware = gcvNULL;
+ gceSTATUS status;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures0;
+ gctUINT32 chipMinorFeatures1;
+ gctUINT16 data = 0xff00;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+ /* Enable the GPU. */
+ gcmkONERROR(gckOS_SetGPUPower(Os, gcvTRUE, gcvTRUE));
+ gcmkONERROR(gckOS_WriteRegister(Os, 0x00000, 0));
+
+ /* Identify the hardware. */
+ gcmkONERROR(_IdentifyHardware(Os,
+ &chipModel,
+ &chipRevision,
+ &chipFeatures,
+ &chipMinorFeatures0,
+ &chipMinorFeatures1));
+
+ /* Allocate the gckHARDWARE object. */
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckHARDWARE),
+ (gctPOINTER *) &hardware));
+
+ /* Initialize the gckHARDWARE object. */
+ hardware->object.type = gcvOBJ_HARDWARE;
+ hardware->os = Os;
+
+ /* Set chip identity. */
+ hardware->chipModel = chipModel;
+ hardware->chipRevision = chipRevision;
+ hardware->chipFeatures = chipFeatures;
+ hardware->chipMinorFeatures0 = chipMinorFeatures0;
+ hardware->chipMinorFeatures1 = chipMinorFeatures1;
+ hardware->powerBaseAddress = ( (chipModel == gcv300)
+ && (chipRevision < 0x2000)
+ ) ? 0x100 : 0x00;
+ hardware->powerMutex = gcvNULL;
+ hardware->recMutexPower = gcvNULL;
+
+ /* Get chip specs. */
+ gcmkONERROR(_GetChipSpecs(hardware));
+
+ /* Determine whether bug fixes #1 are present. */
+ hardware->extraEventStates = ((((gctUINT32) (chipMinorFeatures1)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
+
+ /* Check if big endian */
+ hardware->bigEndian = (*(gctUINT8 *)&data == 0xff);
+
+ /* Initialize the fast clear. */
+ gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
+
+ /* Set power state to ON. */
+ hardware->chipPowerState = gcvPOWER_ON;
+ hardware->lastWaitLink = ~0U;
+ hardware->hang = gcvFALSE;
+
+ gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
+
+ gcmkONERROR(gckOS_CreateRecMutex(Os, &hardware->recMutexPower));
+
+ /* Return pointer to the gckHARDWARE object. */
+ *Hardware = hardware;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Roll back. */
+ if (hardware != gcvNULL && hardware->recMutexPower != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteRecMutex(Os, hardware->recMutexPower));
+ hardware->recMutexPower = gcvNULL;
+ }
+
+ if (hardware != gcvNULL && hardware->powerMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
+ hardware->powerMutex = gcvNULL;
+ }
+
+ if (hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Free(Os, hardware));
+ hardware = gcvNULL;
+ }
+
+ /* 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);
+
+ if(Hardware->recMutexPower != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteRecMutex(Hardware->os, Hardware->recMutexPower));
+ Hardware->recMutexPower = gcvNULL;
+ }
+
+ /* Destroy the power mutex. */
+ if(Hardware->powerMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
+ Hardware->powerMutex = gcvNULL;
+ }
+
+ /* Mark the object as unknown. */
+ Hardware->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the object. */
+ gcmkONERROR(gckOS_Free(Hardware->os, Hardware));
+ Hardware = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_InitializeHardware
+**
+** Initialize the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 baseAddress;
+ gctUINT32 chipRev;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Read the chip revision register. */
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os,
+ 0x00024,
+ &chipRev));
+
+ if (chipRev != Hardware->chipRevision)
+ {
+ /* Chip is not there! */
+ gcmkONERROR(gcvSTATUS_CONTEXT_LOSSED);
+ }
+
+ /* Disable isolate GPU bit. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ ((((gctUINT32) (0x00000100)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)))));
+
+ /* Reset memory counters. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x0003C,
+ ~0U));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x0003C,
+ 0));
+
+ /* Get the system's physical base address. */
+ gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+ /* Program the base addesses. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x0041C,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00418,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00420,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00428,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00424,
+ baseAddress));
+
+#if !VIVANTE_PROFILER && MRVL_ENABLE_CLOCK_GATING
+ {
+ gctUINT32 data;
+
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os,
+ Hardware->powerBaseAddress +
+ 0x00100,
+ &data));
+
+ /* Enable clock gating. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ if ((Hardware->chipRevision == 0x4301)
+ || (Hardware->chipRevision == 0x4302)
+ )
+ {
+ /* Disable stall module level clock gating for 4.3.0.1 and 4.3.0.2
+ ** revisions. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
+ }
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ Hardware->powerBaseAddress
+ + 0x00100,
+ data));
+
+ /* Disable PE clock gating on revs < 5.0 when HZ is present without a
+ ** bug fix. */
+ if ((Hardware->chipRevision < 0x5000)
+ && ((((gctUINT32) (Hardware->chipMinorFeatures1)) >> (0 ? 9:9) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))))
+ && ((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))))
+ )
+ {
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &data));
+
+ /* Disable PE clock gating. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
+
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ data));
+ }
+ }
+#endif
+
+ /* Test if MMU is initialized. */
+ if ((Hardware->kernel != gcvNULL)
+ && (Hardware->kernel->mmu != gcvNULL)
+ )
+ {
+ /* Reset MMU. */
+ gcmkONERROR(
+ gckHARDWARE_SetMMU(Hardware,
+ Hardware->kernel->mmu->pageTableLogical));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryMemory
+**
+** Query the amount of memory available on the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * InternalSize
+** Pointer to a variable that will hold the size of the internal video
+** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
+** internal memory will be returned.
+**
+** gctUINT32 * InternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * InternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctSIZE_T * ExternalSize
+** Pointer to a variable that will hold the size of the external video
+** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
+** external memory will be returned.
+**
+** gctUINT32 * ExternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * ExternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * HorizontalTileSize
+** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
+** gcvNULL, no horizontal pixel per tile will be returned.
+**
+** gctUINT32 * VerticalTileSize
+** Number of vertical pixels per tile. If 'VerticalTileSize' is
+** gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (InternalSize != gcvNULL)
+ {
+ /* No internal memory. */
+ *InternalSize = 0;
+ }
+
+ if (ExternalSize != gcvNULL)
+ {
+ /* No external memory. */
+ *ExternalSize = 0;
+ }
+
+ if (HorizontalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *HorizontalTileSize = 4;
+ }
+
+ if (VerticalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *VerticalTileSize = 4;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*InternalSize=%lu *InternalBaseAddress=0x%08x "
+ "*InternalAlignment=0x%08x *ExternalSize=%lu "
+ "*ExternalBaseAddress=0x%08x *ExtenalAlignment=0x%08x "
+ "*HorizontalTileSize=%u *VerticalTileSize=%u",
+ gcmOPT_VALUE(InternalSize),
+ gcmOPT_VALUE(InternalBaseAddress),
+ gcmOPT_VALUE(InternalAlignment),
+ gcmOPT_VALUE(ExternalSize),
+ gcmOPT_VALUE(ExternalBaseAddress),
+ gcmOPT_VALUE(ExternalAlignment),
+ gcmOPT_VALUE(HorizontalTileSize),
+ gcmOPT_VALUE(VerticalTileSize));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryChipIdentity
+**
+** Query the identity of the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gceCHIPMODEL * ChipModel
+** If 'ChipModel' is not gcvNULL, the variable it points to will
+** receive the model of the chip.
+**
+** gctUINT32 * ChipRevision
+** If 'ChipRevision' is not gcvNULL, the variable it points to will
+** receive the revision of the chip.
+**
+** gctUINT32 * ChipFeatures
+** If 'ChipFeatures' is not gcvNULL, the variable it points to will
+** receive the feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures
+** If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
+** will receive the minor feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures1
+** If 'ChipMinorFeatures1' is not gcvNULL, the variable it points to
+** will receive the minor feature set 1 of the chip.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32 * ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures1
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Return chip model. */
+ if (ChipModel != gcvNULL)
+ {
+ *ChipModel = Hardware->chipModel;
+ }
+
+ /* Return revision number. */
+ if (ChipRevision != gcvNULL)
+ {
+ *ChipRevision = Hardware->chipRevision;
+ }
+
+ /* Return feature set. */
+ if (ChipFeatures != gcvNULL)
+ {
+ gctUINT32 features = Hardware->chipFeatures;
+
+ if (( ((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ /* Override fast clear by command line. */
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ if (( ((((gctUINT32) (features)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ))
+ {
+ /* Override compression by command line. */
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (Hardware->allowCompression) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ }
+
+ /* Mark 2D pipe as available for GC500.0 through GC500.2 and GC300,
+ ** since they did not have this bit. */
+ if (( (Hardware->chipModel == gcv500)
+ && (Hardware->chipRevision <= 2)
+ )
+ || (Hardware->chipModel == gcv300)
+ )
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+ }
+
+ *ChipFeatures = features;
+ }
+
+ /* Return minor feature set. */
+ if (ChipMinorFeatures != gcvNULL)
+ {
+ *ChipMinorFeatures = Hardware->chipMinorFeatures0;
+ }
+
+ /* Return minor feature set 1. */
+ if (ChipMinorFeatures1 != gcvNULL)
+ {
+ *ChipMinorFeatures1 = Hardware->chipMinorFeatures1;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ChipModel=0x%x *ChipRevision=0x%x *ChipFeatures=0x%08x "
+ "*ChipMinorFeatures=0x%08x *ChipMinorFeatures1=0x%08x",
+ gcmOPT_VALUE(ChipModel), gcmOPT_VALUE(ChipRevision),
+ gcmOPT_VALUE(ChipFeatures), gcmOPT_VALUE(ChipMinorFeatures),
+ gcmOPT_VALUE(ChipMinorFeatures1));
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_QueryChipSpecs(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR StreamCount,
+ OUT gctUINT32_PTR RegisterMax,
+ OUT gctUINT32_PTR ThreadCount,
+ OUT gctUINT32_PTR ShaderCoreCount,
+ OUT gctUINT32_PTR VertexCacheSize,
+ OUT gctUINT32_PTR VertexOutputBufferSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Return the number of streams. */
+ if (StreamCount != gcvNULL)
+ {
+ *StreamCount = Hardware->streamCount;
+ }
+
+ /* Return the number of temporary registers. */
+ if (RegisterMax != gcvNULL)
+ {
+ *RegisterMax = Hardware->registerMax;
+ }
+
+ /* Return the maximum number of thrteads. */
+ if (ThreadCount != gcvNULL)
+ {
+ *ThreadCount = Hardware->threadCount;
+ }
+
+ /* Return the number of shader cores. */
+ if (ShaderCoreCount != gcvNULL)
+ {
+ *ShaderCoreCount = Hardware->shaderCoreCount;
+ }
+
+ /* Return the number of entries in the vertex cache. */
+ if (VertexCacheSize != gcvNULL)
+ {
+ *VertexCacheSize = Hardware->vertexCacheSize;
+ }
+
+ /* Return the number of entries in the vertex output buffer. */
+ if (VertexOutputBufferSize != gcvNULL)
+ {
+ *VertexOutputBufferSize = Hardware->vertexOutputBufferSize;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*StreamCount=%u *RegisterMax=%u *ThreadCount=%u "
+ "*ShaderCoreCount=%u *VertexCacheSize=%u "
+ "*VertexOutputBufferSize=%u",
+ gcmOPT_VALUE(StreamCount), gcmOPT_VALUE(RegisterMax),
+ gcmOPT_VALUE(ThreadCount), gcmOPT_VALUE(ShaderCoreCount),
+ gcmOPT_VALUE(VertexCacheSize),
+ gcmOPT_VALUE(VertexOutputBufferSize));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertFormat
+**
+** Convert an API format to hardware parameters.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gceSURF_FORMAT Format
+** API format to convert.
+**
+** OUTPUT:
+**
+** gctUINT32 * BitsPerPixel
+** Pointer to a variable that will hold the number of bits per pixel.
+**
+** gctUINT32 * BytesPerTile
+** Pointer to a variable that will hold the number of bytes per tile.
+*/
+gceSTATUS
+gckHARDWARE_ConvertFormat(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ )
+{
+ gctUINT32 bitsPerPixel;
+ gctUINT32 bytesPerTile;
+
+ gcmkHEADER_ARG("Hardware=0x%x Format=%d", Hardware, Format);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Dispatch on format. */
+ switch (Format)
+ {
+ case gcvSURF_INDEX8:
+ case gcvSURF_A8:
+ case gcvSURF_L8:
+ /* 8-bpp format. */
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_YV12:
+ case gcvSURF_I420:
+ case gcvSURF_NV12:
+ case gcvSURF_NV21:
+ /* 12-bpp planar YUV formats. */
+ bitsPerPixel = 12;
+ bytesPerTile = (12 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_A8L8:
+ case gcvSURF_X4R4G4B4:
+ case gcvSURF_A4R4G4B4:
+ case gcvSURF_X1R5G5B5:
+ case gcvSURF_A1R5G5B5:
+ case gcvSURF_R5G5B5X1:
+ case gcvSURF_R4G4B4X4:
+ case gcvSURF_X4B4G4R4:
+ case gcvSURF_X1B5G5R5:
+ case gcvSURF_B4G4R4X4:
+ case gcvSURF_R5G6B5:
+ case gcvSURF_B5G5R5X1:
+ case gcvSURF_YUY2:
+ case gcvSURF_UYVY:
+ case gcvSURF_YVYU:
+ case gcvSURF_VYUY:
+ case gcvSURF_NV16:
+ case gcvSURF_NV61:
+ case gcvSURF_D16:
+ /* 16-bpp format. */
+ bitsPerPixel = 16;
+ bytesPerTile = (16 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_X8R8G8B8:
+ case gcvSURF_A8R8G8B8:
+ case gcvSURF_X8B8G8R8:
+ case gcvSURF_A8B8G8R8:
+ case gcvSURF_R8G8B8X8:
+ case gcvSURF_D32:
+ /* 32-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_D24S8:
+ case gcvSURF_D24X8:
+ /* 24-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT1:
+ case gcvSURF_ETC1:
+ bitsPerPixel = 4;
+ bytesPerTile = (4 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT2:
+ case gcvSURF_DXT3:
+ case gcvSURF_DXT4:
+ case gcvSURF_DXT5:
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ default:
+ /* Invalid format. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Set the result. */
+ if (BitsPerPixel != gcvNULL)
+ {
+ * BitsPerPixel = bitsPerPixel;
+ }
+
+ if (BytesPerTile != gcvNULL)
+ {
+ * BytesPerTile = bytesPerTile;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BitsPerPixel=%u *BytesPerTile=%u",
+ gcmOPT_VALUE(BitsPerPixel), gcmOPT_VALUE(BytesPerTile));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SplitMemory
+**
+** Split a hardware specific memory address into a pool and offset.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT32 Address
+** Address in hardware specific format.
+**
+** OUTPUT:
+**
+** gcePOOL * Pool
+** Pointer to a variable that will hold the pool type for the address.
+**
+** gctUINT32 * Offset
+** Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Addres=%08x", Hardware, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+ /* Dispatch on memory type. */
+ switch (( ((((gctUINT32) (Address)) >> (0 ? 31:31)) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) ))
+ {
+ case 0x0:
+ /* System memory. */
+ *Pool = gcvPOOL_SYSTEM;
+ break;
+
+ case 0x1:
+ /* Virtual memory. */
+ *Pool = gcvPOOL_VIRTUAL;
+ break;
+
+ default:
+ /* Invalid memory type. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Return offset of address. */
+ *Offset = ( ((((gctUINT32) (Address)) >> (0 ? 30:0)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1)))))) );
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Pool=%d *Offset=%08x", *Pool, *Offset);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Execute
+**
+** Kickstart the hardware's command processor with an initialized command
+** buffer.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of command buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes for the prefetch unit (until after the first LINK).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+#ifdef __QNXNTO__
+ IN gctPOINTER Physical,
+ IN gctBOOL PhysicalAddresses,
+#endif
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0, control;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Bytes=%lu",
+ Hardware, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+#ifdef __QNXNTO__
+ if (PhysicalAddresses)
+ {
+ /* Convert physical into hardware specific address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertPhysical(Hardware, Physical, &address));
+ }
+ else
+ {
+#endif
+ /* Convert logical into hardware specific address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
+#ifdef __QNXNTO__
+ }
+#endif
+
+ /* Enable all events. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00014, ~0U));
+
+ /* Write address register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00654, address));
+
+ /* Build control register. */
+ control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes+7)>>3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ /* Set big endian */
+ if (Hardware->bigEndian)
+ {
+ control |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20)));
+ }
+
+ /* Write control register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00658, control));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Started command buffer @ %08x",
+ address);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_WaitLink
+**
+** Append a WAIT/LINK command sequence at the specified location in the command
+** queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** WAIT/LINK command sequence at or gcvNULL just to query the size of the
+** WAIT/LINK command sequence.
+**
+** gctUINT32 Offset
+** Offset into command buffer required for alignment.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the WAIT/LINK command
+** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** by the WAIT/LINK command sequence. If 'Bytes' is gcvNULL, nothing will
+** be returned.
+**
+** gctPOINTER * Wait
+** Pointer to a variable that will receive the pointer to the WAIT
+** command. If 'Wait' is gcvNULL nothing will be returned.
+**
+** gctSIZE_T * WaitSize
+** Pointer to a variable that will receive the number of bytes used by
+** the WAIT command. If 'LinkSize' is gcvNULL nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPOINTER * Wait,
+ OUT gctSIZE_T * WaitSize
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gctSIZE_T bytes;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=%08x *Bytes=%lu",
+ Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ /* Compute number of bytes required. */
+ bytes = gcmALIGN(Offset + 16, 8) - Offset;
+
+ if (Logical != gcvNULL)
+ {
+ /* Convert logical into hardware specific address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware,
+ Logical,
+ &address));
+
+ if (*Bytes < bytes)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append WAIT(200). */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (200) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: WAIT", address);
+
+ /* Append LINK(2, address). */
+ logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes>>3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ logical[3] = address;
+
+ Hardware->lastWaitLink = address;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: LINK %08x, #%lu",
+ address + 8, address, bytes);
+
+ if (Wait != gcvNULL)
+ {
+ /* Return pointer to WAIT command. */
+ *Wait = Logical;
+ }
+
+ if (WaitSize != gcvNULL)
+ {
+ /* Return number of bytes used by the WAIT command. */
+ *WaitSize = 8;
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the WAIT/LINK command
+ ** sequence. */
+ *Bytes = bytes;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *Wait=0x%x *WaitSize=%lu",
+ gcmOPT_VALUE(Bytes), gcmOPT_POINTER(Wait),
+ gcmOPT_VALUE(WaitSize));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_End
+**
+** Append an END command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** END command at or gcvNULL just to query the size of the END command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the END command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append END. */
+ logical[0] =
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
+
+ /* Make sure the CPU writes out the data to memory. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Nop
+**
+** Append a NOP command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** NOP command at or gcvNULL just to query the size of the NOP command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the NOP command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append NOP. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the NOP command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Wait
+**
+** Append a WAIT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** WAIT command at or gcvNULL just to query the size of the WAIT command.
+**
+** gctUINT32 Count
+** Number of cycles to wait.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the WAIT command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Wait(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Count,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Count=%u *Bytes=%lu",
+ Hardware, Logical, Count, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append WAIT. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: WAIT %u", Logical, Count);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the WAIT command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Event
+**
+** Append an EVENT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the EVENT command at or gcvNULL just to query the size of the EVENT
+** command.
+**
+** gctUINT8 Event
+** Event ID to program.
+**
+** gceKERNEL_WHERE FromWhere
+** Location of the pipe to send the event.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the EVENT command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the EVENT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT size;
+ gctUINT32 destination = 0;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
+ Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+ gcmkVERIFY_ARGUMENT(Event < 32);
+
+ /* Determine the size of the command. */
+ size = (Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL))
+ ? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
+ : 8;
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < size)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ switch (FromWhere)
+ {
+ case gcvKERNEL_COMMAND:
+ /* From command processor. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1&((gctUINT32)((((1?5:5)-(0?5:5)+1)==32)?~0:(~(~0<<((1?5:5)-(0?5:5)+1)))))))<<(0?5:5)));
+ break;
+
+ case gcvKERNEL_PIXEL:
+ /* From pixel engine. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1&((gctUINT32)((((1?6:6)-(0?6:6)+1)==32)?~0:(~(~0<<((1?6:6)-(0?6:6)+1)))))))<<(0?6:6)));
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Append EVENT(Event, destiantion). */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1] = ((((gctUINT32) (destination)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (Event) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+
+ /* Make sure the event ID gets written out before GPU can access it. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+#if gcdDEBUG
+ {
+ gctUINT32 phys;
+ gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: EVENT %d", phys, Event);
+ }
+#endif
+
+ /* Append the extra states. These are needed for the chips that do not
+ ** support back-to-back events due to the async interface. The extra
+ ** states add the necessary delay to ensure that event IDs do not
+ ** collide. */
+ if (size > 8)
+ {
+ logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0100) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+ logical[3] = 0;
+ logical[4] = 0;
+ logical[5] = 0;
+ logical[6] = 0;
+ logical[7] = 0;
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT command. */
+ *Bytes = size;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_PipeSelect
+**
+** Append a PIPESELECT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the PIPESELECT command at or gcvNULL just to query the size of the
+** PIPESELECT command.
+**
+** gctUINT32 Pipe
+** Pipe value to select.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the PIPESELECT command.
+** If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the PIPESELECT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pipe,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%u *Bytes=%lu",
+ Hardware, Logical, Pipe, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ /* Append a PipeSelect. */
+ if (Logical != gcvNULL)
+ {
+ gctUINT32 flush, stall;
+
+ if (*Bytes < 32)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ flush = (Pipe == 0x1)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1&((gctUINT32)((((1?1:1)-(0?1:1)+1)==32)?~0:(~(~0<<((1?1:1)-(0?1:1)+1)))))))<<(0?1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1&((gctUINT32)((((1?0:0)-(0?0:0)+1)==32)?~0:(~(~0<<((1?0:0)-(0?0:0)+1)))))))<<(0?0:0)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1&((gctUINT32)((((1?3:3)-(0?3:3)+1)==32)?~0:(~(~0<<((1?3:3)-(0?3:3)+1)))))))<<(0?3:3)));
+
+ stall = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* LoadState(AQFlush, 1), flush. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1] = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH %x", logical, flush);
+
+ /* LoadState(AQSempahore, 1), stall. */
+ logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[3] = stall;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: SEMAPHORE %x", logical + 2, stall);
+
+ /* Stall, stall. */
+ logical[4] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ logical[5] = stall;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: STALL %x", logical + 4, stall);
+
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ logical[6] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[7] = Pipe;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: PIPE %u", logical + 6, Pipe);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the PIPESELECT command. */
+ *Bytes = 32;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Link
+**
+** Append a LINK command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the LINK command at or gcvNULL just to query the size of the LINK
+** command.
+**
+** gctPOINTER FetchAddress
+** Logical address of destination of LINK.
+**
+** gctSIZE_T FetchSize
+** Number of bytes in destination of LINK.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the LINK command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the LINK command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctPOINTER FetchAddress,
+ IN gctSIZE_T FetchSize,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gctUINT32 address;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x FetchAddress=0x%x FetchSize=%lu "
+ "*Bytes=%lu",
+ Hardware, Logical, FetchAddress, FetchSize,
+ gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Convert logical address to hardware address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware, FetchAddress, &address));
+
+ logical[1] = address;
+
+ if(Hardware->hang)
+ {
+ static gctUINT32 count = 0;
+
+ if( ( ++count % 50 ) == 0 )
+ {
+ /* simulate GPU hangs only once */
+ logical[1] = address & 0xffffff00;
+ gcmkPRINT("@@@pollute link chain \n");
+ }
+ }
+
+ /* Make sure the address got written before the LINK command. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+ /* Compute number of 64-byte aligned bytes to fetch. */
+ bytes = gcmALIGN(address + FetchSize, 64) - address;
+
+ /* Append LINK(bytes / 8), FetchAddress. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes>>3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+#if gcdDEBUG
+ {
+ gctUINT32 phys;
+ gckHARDWARE_ConvertLogical(Hardware, Logical, &phys);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: LINK %08x, #%lu", phys, address, bytes);
+ }
+#endif
+
+ /* Memory barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the LINK command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_AlignToTile
+**
+** Align the specified width and height to tile boundaries.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gceSURF_TYPE Type
+** Type of alignment.
+**
+** gctUINT32 * Width
+** Pointer to the width to be aligned. If 'Width' is gcvNULL, no width
+** will be aligned.
+**
+** gctUINT32 * Height
+** Pointer to the height to be aligned. If 'Height' is gcvNULL, no height
+** will be aligned.
+**
+** OUTPUT:
+**
+** gctUINT32 * Width
+** Pointer to a variable that will receive the aligned width.
+**
+** gctUINT32 * Height
+** Pointer to a variable that will receive the aligned height.
+**
+** gctBOOL_PTR SuperTiled
+** Pointer to a variable that receives the super-tiling flag for the
+** surface.
+*/
+gceSTATUS
+gckHARDWARE_AlignToTile(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height,
+ OUT gctBOOL_PTR SuperTiled
+ )
+{
+ gctBOOL superTiled = gcvFALSE;
+ gctUINT32 xAlignment, yAlignment;
+
+ gcmkHEADER_ARG("Hardware=0x%x Type=%d *Width=%u *Height=%u",
+ Hardware, Type, gcmOPT_VALUE(Width), gcmOPT_VALUE(Height));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Super tiling can be enabled for render targets and depth buffers. */
+ superTiled =
+ ( (Type == gcvSURF_RENDER_TARGET)
+ || (Type == gcvSURF_DEPTH)
+ )
+ &&
+ /* Of course, hardware needs to support super tiles. */
+ ((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 12:12) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1)))))));
+
+ /* Compute alignment factors. */
+ xAlignment = superTiled ? 64
+ : (Type == gcvSURF_TEXTURE) ? 4
+ : 16;
+ yAlignment = superTiled ? 64 : 4;
+
+ if (Width != gcvNULL)
+ {
+ /* Align the width. */
+ *Width = gcmALIGN(*Width, xAlignment);
+ }
+
+ if (Height != gcvNULL)
+ {
+ /* Align the height. */
+ *Height = gcmALIGN(*Height, yAlignment);
+ }
+
+ if (SuperTiled != gcvNULL)
+ {
+ /* Copy the super tiling. */
+ *SuperTiled = superTiled;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Width=%u *Height=%u *SuperTiled=%d",
+ gcmOPT_VALUE(Width), gcmOPT_VALUE(Height),
+ gcmOPT_VALUE(SuperTiled));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_UpdateQueueTail
+**
+** Update the tail of the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the start of the command queue.
+**
+** gctUINT32 Offset
+** Offset into the command queue of the tail (last command).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=%08x",
+ Hardware, Logical, Offset);
+
+ /* Verify the hardware. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Force a barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+
+ /* Notify gckKERNEL object of change. */
+ gcmkONERROR(
+ gckKERNEL_Notify(Hardware->kernel,
+ gcvNOTIFY_COMMAND_QUEUE,
+ gcvFALSE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertLogical
+**
+** Convert a logical system address into a hardware specific address.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address to convert.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address = 0;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ if (Logical == gcvNULL || Address == gcvNULL)
+ return gcvSTATUS_INVALID_ARGUMENT;
+
+ /* Convert logical address into a physical address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Hardware->os, Logical, &address));
+
+ /* Return hardware specific address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertPhysical
+**
+** Convert a physical address into a hardware specific address.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPHYS_ADDR Physical
+** Physical address to convert.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertPhysical(
+ IN gckHARDWARE Hardware,
+ IN gctPHYS_ADDR Physical,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ address = (gctUINT32)Physical;
+
+ /* Return hardware specific address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+ /* Return the status. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Interrupt
+**
+** Process an interrupt.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL InterruptValid
+** If gcvTRUE, this function will read the interrupt acknowledge
+** register, stores the data, and return whether or not the interrupt
+** is ours or not. If gcvFALSE, this functions will read the interrupt
+** acknowledge register and combine it with any stored value to handle
+** the event notifications.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL InterruptValid
+ )
+{
+ gckEVENT event;
+ gctUINT32 data;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Extract gckEVENT object. */
+ event = Hardware->kernel->event;
+ gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+ if (InterruptValid)
+ {
+ /* Read AQIntrAcknowledge register. */
+ gcmkONERROR(
+ gckOS_DirectReadRegister(Hardware->os,
+ 0x00010,
+ &data));
+
+#if gcdDEBUG && VIVANTE_POWER_MANAGE
+ if (data & 0x80000000)
+ {
+ gcmkONERROR(gckOS_Broadcast(Hardware->os,
+ Hardware,
+ gcvBROADCAST_AXI_BUS_ERROR));
+ }
+#endif
+
+ if (data == 0)
+ {
+ /* Not our interrupt. */
+ status = gcvSTATUS_NOT_OUR_INTERRUPT;
+ }
+ else
+ {
+ /* Inform gckEVENT of the interrupt. */
+ status = gckEVENT_Interrupt(event, data & 0x7FFFFFFF);
+ }
+ }
+ else
+ {
+ /* Handle events. */
+ status = gckEVENT_Notify(event, 0);
+ }
+
+OnError:
+ if (!gcmIS_SUCCESS(status))
+ {
+ gcmkLOG_ERROR_STATUS();
+ }
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryCommandBuffer
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Alignment
+** Pointer to a variable receiving the alignment for each command.
+**
+** gctSIZE_T * ReservedHead
+** Pointer to a variable receiving the number of reserved bytes at the
+** head of each command buffer.
+**
+** gctSIZE_T * ReservedTail
+** Pointer to a variable receiving the number of bytes reserved at the
+** tail of each command buffer.
+*/
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * Alignment,
+ OUT gctSIZE_T * ReservedHead,
+ OUT gctSIZE_T * ReservedTail
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Alignment != gcvNULL)
+ {
+ /* Align every 8 bytes. */
+ *Alignment = 8;
+ }
+
+ if (ReservedHead != gcvNULL)
+ {
+ /* Reserve space for SelectPipe(). */
+ *ReservedHead = 32;
+ }
+
+ if (ReservedTail != gcvNULL)
+ {
+ /* Reserve space for Link(). */
+ *ReservedTail = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Alignment=%lu *ReservedHead=%lu *ReservedTail=%lu",
+ gcmOPT_VALUE(Alignment), gcmOPT_VALUE(ReservedHead),
+ gcmOPT_VALUE(ReservedTail));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QuerySystemMemory
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * SystemSize
+** Pointer to a variable that receives the maximum size of the system
+** memory.
+**
+** gctUINT32 * SystemBaseAddress
+** Poinetr to a variable that receives the base address for system
+** memory.
+*/
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (SystemSize != gcvNULL)
+ {
+ /* Maximum system memory can be 2GB. */
+ *SystemSize = 1U << 31;
+ }
+
+ if (SystemBaseAddress != gcvNULL)
+ {
+ /* Set system memory base address. */
+ *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*SystemSize=%lu *SystemBaseAddress=%lu",
+ gcmOPT_VALUE(SystemSize), gcmOPT_VALUE(SystemBaseAddress));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetMMU
+**
+** Set the page table base address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the page table.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0;
+ gctUINT32 baseAddress;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Convert the logical address into an hardware address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
+
+ /* Also get the base address - we need a real physical address. */
+ gcmkONERROR(
+ gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Setting page table to 0x%08X",
+ address + baseAddress);
+
+ /* Write the AQMemoryFePageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00400,
+ address + baseAddress));
+
+ /* Write the AQMemoryRaPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00410,
+ address + baseAddress));
+
+ /* Write the AQMemoryTxPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00404,
+ address + baseAddress));
+
+ /* Write the AQMemoryPePageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00408,
+ address + baseAddress));
+
+ /* Write the AQMemoryPezPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x0040C,
+ address + baseAddress));
+
+ /* Return the status. */
+ gcmkFOOTER_NO();
+ return status;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_FlushMMU
+**
+** Flush the page table.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 flush;
+ gctUINT32_PTR buffer;
+ gctSIZE_T bufferSize;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Flush the memory controller. */
+ flush = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1&((gctUINT32)((((1?0:0)-(0?0:0)+1)==32)?~0:(~(~0<<((1?0:0)-(0?0:0)+1)))))))<<(0?0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1&((gctUINT32)((((1?1:1)-(0?1:1)+1)==32)?~0:(~(~0<<((1?1:1)-(0?1:1)+1)))))))<<(0?1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1&((gctUINT32)((((1?2:2)-(0?2:2)+1)==32)?~0:(~(~0<<((1?2:2)-(0?2:2)+1)))))))<<(0?2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1&((gctUINT32)((((1?3:3)-(0?3:3)+1)==32)?~0:(~(~0<<((1?3:3)-(0?3:3)+1)))))))<<(0?3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1&((gctUINT32)((((1?4:4)-(0?4:4)+1)==32)?~0:(~(~0<<((1?4:4)-(0?4:4)+1)))))))<<(0?4:4)));
+
+ gcmkONERROR(
+ gckCOMMAND_Reserve(Hardware->kernel->command,
+ 8,
+ (gctPOINTER *) &buffer,
+ &bufferSize));
+
+ buffer[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ buffer[1] = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH MMU", buffer);
+
+ gcmkONERROR(
+ gckCOMMAND_Execute(Hardware->kernel->command, 8));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_BuildVirtualAddress
+**
+** Build a virtual address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctUINT32 Index
+** Index into page table.
+**
+** gctUINT32 Offset
+** Offset into page.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Index=%u Offset=%u", Hardware, Index, Offset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Build virtual address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (Offset|(Index<<12)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_GetIdle(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle = 0;
+ gctINT retry;
+
+ gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ /* At most, try for 1 second. */
+ for (retry = 0; retry < 1000; ++retry)
+ {
+ /* Read register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os, 0x00004, &idle));
+
+ /* See if we have to wait for FE idle. */
+ if (!Wait
+ || ( ((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) )
+ )
+ {
+ /* FE is not idle yet. */
+ break;
+ }
+
+ /* Wait a little. */
+ gcmkVERIFY_OK(gckOS_Delay(Hardware->os, 1));
+ }
+
+ /* Return idle to caller. */
+ *Data = idle;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=%08x", *Data);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32 pipe;
+ gctUINT32 flush = 0;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Flush=%x Logical=0x%x *Bytes=%lu",
+ Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
+
+ /* Get current pipe. */
+ pipe = Hardware->kernel->command->pipeSelect;
+
+ /* Flush 3D color cache. */
+ if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1&((gctUINT32)((((1?1:1)-(0?1:1)+1)==32)?~0:(~(~0<<((1?1:1)-(0?1:1)+1)))))))<<(0?1:1)));
+ }
+
+ /* Flush 3D depth cache. */
+ if ((Flush & gcvFLUSH_DEPTH) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1&((gctUINT32)((((1?0:0)-(0?0:0)+1)==32)?~0:(~(~0<<((1?0:0)-(0?0:0)+1)))))))<<(0?0:0)));
+ }
+
+ /* Flush 3D texture cache. */
+ if ((Flush & gcvFLUSH_TEXTURE) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1&((gctUINT32)((((1?2:2)-(0?2:2)+1)==32)?~0:(~(~0<<((1?2:2)-(0?2:2)+1)))))))<<(0?2:2)));
+ }
+
+ /* Flush 2D cache. */
+ if ((Flush & gcvFLUSH_2D) && (pipe == 0x1))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1&((gctUINT32)((((1?3:3)-(0?3:3)+1)==32)?~0:(~(~0<<((1?3:3)-(0?3:3)+1)))))))<<(0?3:3)));
+ }
+
+ /* See if there is a valid flush. */
+ if (flush == 0)
+ {
+ if (Bytes != gcvNULL)
+ {
+ /* No bytes required. */
+ *Bytes = 0;
+ }
+ }
+
+ else
+ {
+ /* Copy to command queue. */
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append LOAD_STATE to AQFlush. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1] = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH %x", logical, flush);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* 8 bytes required. */
+ *Bytes = 8;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ )
+{
+ gctUINT32 debug;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Enable=%d Compression=%d",
+ Hardware, Enable, Compression);
+
+ /* Only process if fast clear is available. */
+ if (( ((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ if (Enable == -1)
+ {
+ /* Determine automatic value for fast clear. */
+ Enable = (Hardware->chipModel != gcv500)
+ | (Hardware->chipRevision >= 3);
+ }
+
+#if MRVL_DISABLE_FASTCLEAR
+ Enable = 0;
+#endif
+
+ if (Compression == -1)
+ {
+ /* Determine automatic value for compression. */
+ Compression = Enable
+ & ( ((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) );
+ }
+
+ /* Read AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os, 0x00414, &debug));
+
+ /* Set fast clear bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable==0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
+
+ /* Set copression bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21))) | (((gctUINT32) ((gctUINT32) (Compression==0) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21)));
+
+ /* Write back AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00414,
+ debug));
+
+ /* Store fast clear and comprersison flags. */
+ Hardware->allowFastClear = Enable;
+ Hardware->allowCompression = Compression;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "FastClear=%d Compression=%d", Enable, Compression);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+typedef enum
+{
+ gcvPOWER_FLAG_INITIALIZE = 1 << 0,
+ gcvPOWER_FLAG_STALL = 1 << 1,
+ gcvPOWER_FLAG_STOP = 1 << 2,
+ gcvPOWER_FLAG_START = 1 << 3,
+ gcvPOWER_FLAG_RELEASE = 1 << 4,
+ gcvPOWER_FLAG_DELAY = 1 << 5,
+ gcvPOWER_FLAG_SAVE = 1 << 6,
+ gcvPOWER_FLAG_ACQUIRE = 1 << 7,
+ gcvPOWER_FLAG_PWR_OFF = 1 << 28,
+ gcvPOWER_FLAG_PWR_ON = 1 << 29,
+ gcvPOWER_FLAG_CLK_OFF = 1 << 30,
+ gcvPOWER_FLAG_CLK_ON = 1 << 31,
+}
+gcePOWER_FLAGS;
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagementState
+**
+** Set GPU to a specified power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ )
+{
+#if !gcdNO_POWER_MANAGEMENT
+ gceSTATUS status;
+ gckCOMMAND command = gcvNULL;
+ gckOS os;
+ gctUINT flag, clock;
+ gctBOOL semaAcquired = gcvFALSE;
+ gctBOOL mutexAcquired = gcvFALSE;
+ gctBOOL stall = gcvTRUE;
+
+ /* 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_PWR_OFF |
+ gcvPOWER_FLAG_CLK_OFF,
+ /* IDLE */ 0,
+ /* SUSPEND */ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLK_OFF,
+ },
+
+ /* gcvPOWER_OFF */
+ { /* ON */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_PWR_ON |
+ gcvPOWER_FLAG_CLK_ON,
+ /* OFF */ 0,
+ /* IDLE */ 0,
+ /* SUSPEND */ 0,
+ },
+
+ /* gcvPOWER_IDLE */
+ { /* ON */ 0,
+ /* OFF */ 0,
+ /* IDLE */ 0,
+ /* SUSPEND */ 0,
+ },
+
+ /* gcvPOWER_SUSPEND */
+ { /* ON */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY |
+ gcvPOWER_FLAG_CLK_ON,
+ /* OFF */ gcvPOWER_FLAG_SAVE |
+ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_PWR_OFF,
+ /* IDLE */ 0,
+ /* SUSPEND */ 0,
+ },
+ };
+
+ /* Clocks. */
+ static const gctUINT clocks[4] =
+ {
+ /* gcvPOWER_ON */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (64) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ,
+ /* gcvPOWER_OFF */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ,
+ /* gcvPOWER_IDLE */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ,
+ /* gcvPOWER_SUSPEND */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))), };
+
+ gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get the gckOS object pointer. */
+ os = Hardware->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ gcmkONERROR(gckOS_AcquireRecMutex(os, Hardware->recMutexPower, gcvINFINITE));
+ mutexAcquired = gcvTRUE;
+
+ if ( (Hardware->chipPowerState == gcvPOWER_OFF)
+ && (State == gcvPOWER_SUSPEND) )
+ {
+ State = gcvPOWER_OFF;
+ }
+
+ /* Grab control flags and clock. */
+ flag = flags[Hardware->chipPowerState][State];
+ clock = clocks[State];
+
+ if (flag == 0)
+ {
+ /* Save new power state. */
+ Hardware->chipPowerState = State;
+
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(os, Hardware->recMutexPower));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ gcmkASSERT(Hardware->kernel != gcvNULL);
+ gcmkASSERT(Hardware->kernel->command != gcvNULL);
+ command = Hardware->kernel->command;
+
+ if (flag & (gcvPOWER_FLAG_CLK_ON | gcvPOWER_FLAG_PWR_ON))
+ {
+ gckOS_SetConstraint(os,
+ (flag & gcvPOWER_FLAG_CLK_ON) ? gcvTRUE : gcvFALSE,
+ (flag & gcvPOWER_FLAG_PWR_ON) ? gcvTRUE : gcvFALSE);
+
+ gckOS_ClockOn(os,
+ (flag & gcvPOWER_FLAG_CLK_ON) ? gcvTRUE : gcvFALSE,
+ (flag & gcvPOWER_FLAG_PWR_ON) ? gcvTRUE : gcvFALSE,
+ 0);
+ }
+
+ if(flag & gcvPOWER_FLAG_CLK_ON)
+ {
+ gckOS_ResumeInterrupt(os);
+ }
+
+ if ((flag & gcvPOWER_FLAG_STALL) && stall)
+ {
+ gctBOOL idle;
+
+ /* Check for idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Hardware, &idle));
+
+ if (!idle)
+ {
+ status = gcvSTATUS_CHIP_NOT_READY;
+ goto OnError;
+ }
+ }
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+ semaAcquired = gcvTRUE;
+ }
+ if (flag & gcvPOWER_FLAG_STOP)
+ {
+ /* Stop the command parser. */
+ gcmkONERROR(gckCOMMAND_Stop(command));
+ }
+
+ if (flag & (gcvPOWER_FLAG_CLK_ON | gcvPOWER_FLAG_CLK_OFF) )
+ {
+ /* Write the clock control register. */
+ gcmkONERROR(gckOS_WriteRegister(os,
+ 0x00000,
+ clock));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegister(os,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
+ }
+
+ if (flag & gcvPOWER_FLAG_INITIALIZE)
+ {
+ /* Initialize hardware. */
+ gcmkONERROR(
+ gckHARDWARE_InitializeHardware(Hardware));
+
+ gcmkONERROR(
+ gckHARDWARE_SetFastClear(Hardware,
+ Hardware->allowFastClear,
+ Hardware->allowCompression));
+
+ /* Force the command queue to reload the next context. */
+ command->currentContext = 0;
+ }
+
+ if(flag & gcvPOWER_FLAG_CLK_OFF)
+ {
+ gckOS_SuspendInterrupt(os);
+ }
+
+ if (flag & (gcvPOWER_FLAG_CLK_OFF | gcvPOWER_FLAG_PWR_OFF))
+ {
+ gckOS_ClockOff(os,
+ (flag & gcvPOWER_FLAG_CLK_OFF) ? gcvTRUE : gcvFALSE,
+ (flag & gcvPOWER_FLAG_PWR_OFF) ? gcvTRUE : gcvFALSE);
+
+ gckOS_UnSetConstraint(os,
+ (flag & gcvPOWER_FLAG_CLK_OFF) ? gcvTRUE : gcvFALSE,
+ (flag & gcvPOWER_FLAG_PWR_OFF) ? gcvTRUE : gcvFALSE);
+ }
+
+ if (flag & gcvPOWER_FLAG_START)
+ {
+ /* Start the command processor. */
+ gcmkONERROR(gckCOMMAND_Start(command));
+ }
+
+ if (flag & gcvPOWER_FLAG_RELEASE)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+ }
+
+ /* Save the new power state. */
+ Hardware->chipPowerState = State;
+
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(os, Hardware->recMutexPower));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if(status < 0)
+ {
+ gcmkLOG_ERROR_ARGS("status=%d, semaAcquired=%d, mutexAcquired=%d",
+ status, semaAcquired, mutexAcquired);
+ }
+
+ if (semaAcquired)
+ {
+ /* Release semaphore. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
+ }
+
+ if (mutexAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(os, Hardware->recMutexPower));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ /* Do nothing */
+ return gcvSTATUS_OK;
+#endif
+}
+
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryPowerManagementState
+**
+** Get GPU power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE* State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(State != gcvNULL);
+
+ /* Return the statue. */
+ *State = Hardware->chipPowerState;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*State=%d", *State);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle, address;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
+
+ /* We are idle when the power is not ON. */
+ if (Hardware->chipPowerState != gcvPOWER_ON)
+ {
+ *IsIdle = gcvTRUE;
+ }
+
+ else
+ {
+ /* Read the current FE address. */
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os,
+ 0x00664,
+ &address));
+
+ /* Read idle register. */
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00004, &idle));
+
+ /* Pipe must be idle. */
+ /* if ((( ((((gctUINT32) (idle)) >> (0 ? 1:1)) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 3:3)) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) )!=1)
+ ) */
+ /*
+ For GC800 or higher, there are more modules like VG IM FP TS, we need
+ to check more bits
+ */
+ if( (idle & 0x7FFFFFFE) != 0x7FFFFFFE )
+ {
+ /* Something is busy. */
+ *IsIdle = gcvFALSE;
+ }
+ else
+ {
+ /* Test if address is inside the last WAIT/LINK sequence. */
+ if ((address >= Hardware->lastWaitLink)
+ && (address <= Hardware->lastWaitLink + 16)
+ )
+ {
+ /* FE is in last WAIT/LINK and the pipe is idle. */
+ *IsIdle = gcvTRUE;
+ }
+ else
+ {
+ /* FE is not in WAIT/LINK yet. */
+ *IsIdle = gcvFALSE;
+ }
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** Handy macros that will help in reading those debug registers.
+*/
+
+#define gcmkREAD_DEBUG_REGISTER(control, block, index, data) \
+ gcmkONERROR( \
+ gckOS_WriteRegister(Hardware->os, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR( \
+ gckOS_ReadRegister(Hardware->os, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &profiler->data))
+
+#define gcmkRESET_DEBUG_REGISTER(control, block) \
+ gcmkONERROR( \
+ gckOS_WriteRegister(Hardware->os, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ 15))); \
+ gcmkONERROR( \
+ gckOS_WriteRegister(Hardware->os, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ 0)))
+
+/*******************************************************************************
+**
+** gckHARDWARE_ProfileEngine2D
+**
+** Read the profile registers available in the 2D engine and sets them in the
+** profile. The function will also reset the pixelsRendered counter every time.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** OPTIONAL gcs2D_PROFILE_PTR Profile
+** Pointer to a gcs2D_Profile structure.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ )
+{
+ gceSTATUS status;
+ gcs2D_PROFILE_PTR profiler = Profile;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Profile != gcvNULL)
+ {
+ /* Read the cycle count. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00438,
+ &Profile->cycleCount));
+
+ /* Read pixels rendered by 2D engine. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pixelsRendered));
+
+ /* Reset counter. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ OUT gcsPROFILER_COUNTERS * Counters
+ )
+{
+ gceSTATUS status;
+ gcsPROFILER_COUNTERS * profiler = Counters;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Read the counters. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00040,
+ &profiler->gpuTotalRead64BytesPerFrame));
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00044,
+ &profiler->gpuTotalWrite64BytesPerFrame));
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00438,
+ &profiler->gpuCyclesCounter));
+
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x0003C, 1));
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x0003C, 0));
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00438, 0));
+
+ /* PE */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_killed_by_color_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_killed_by_depth_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_drawn_by_color_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_drawn_by_depth_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+
+ /* SH */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->ps_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->rendered_pixel_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->vs_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->rendered_vertice_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->vtx_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->vtx_texld_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->pxl_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->pxl_texld_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)))
+)));
+
+ /* PA */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_input_vtx_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_input_prim_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_output_prim_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_depth_clipped_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_trivial_rejected_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_culled_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0)))
+)));
+
+ /* SE */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00464, &profiler->se_culled_triangle_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00464, &profiler->se_culled_lines_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8)))
+)));
+
+ /* RA */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_valid_pixel_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_total_quad_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_total_primitive_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_pipe_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+
+ /* TX */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_bilinear_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_trilinear_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_discarded_texture_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_texture_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_mem_read_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_mem_read_in_8B_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_miss_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_hit_texel_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_miss_texel_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)))
+)));
+
+ /* MC */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0)))
+)));
+
+ /* HI */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8)))
+)));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 control, idle;
+ gckCOMMAND command;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkASSERT(Hardware->kernel != gcvNULL);
+ command = Hardware->kernel->command;
+ gcmkASSERT(command != gcvNULL);
+
+ if (Hardware->chipRevision < 0x4600)
+ {
+ /* Not supported - we need the isolation bit. */
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(
+ gckOS_AcquireSemaphore(Hardware->os, command->powerSemaphore));
+ acquired = gcvTRUE;
+ }
+
+ if ((Hardware->chipPowerState == gcvPOWER_ON)
+ || (Hardware->chipPowerState == gcvPOWER_IDLE)
+ )
+ {
+ /* Stop the command processor. */
+ gcmkONERROR(
+ gckCOMMAND_Stop(command));
+
+ /* Grab the queue mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Hardware->os,
+ command->mutexQueue,
+ gcvINFINITE));
+ }
+
+ /* Read register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00000,
+ &control));
+
+ for (;;)
+ {
+ /* Isolate the GPU. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ control));
+
+ /* Set soft reset. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Wait for reset. */
+ gcmkONERROR(
+ gckOS_Delay(Hardware->os, 1));
+
+ /* Reset soft reset bit. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Reset GPU isolation. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ control));
+
+ /* Read idle register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00004,
+ &idle));
+
+ if (( ((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) )==0)
+ {
+ continue;
+ }
+
+ /* Read reset register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00000,
+ &control));
+
+ if ((( ((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) )==0)
+ || (( ((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) )==0)
+ )
+ {
+ continue;
+ }
+
+ /* GPU is idle. */
+ break;
+ }
+
+ /* Force an OFF to ON power switch. */
+ Hardware->chipPowerState = gcvPOWER_OFF;
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the power management semaphore. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
+ }
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Test if we have a new Memory Controller. */
+ if (((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 22:22) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))))
+ {
+ /* No base address required. */
+ *BaseAddress = 0;
+ }
+ else
+ {
+ /* Get the base address from the OS. */
+ gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, BaseAddress));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ )
+{
+ gctBOOL need = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x State=0x%08x", Hardware, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(NeedBase != gcvNULL);
+
+ /* Make sure this is a load state. */
+ if (((((gctUINT32) (State)) >> (0 ? 31:27) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27)+1))))))))
+ {
+ /* Get the state address. */
+ switch (( ((((gctUINT32) (State)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0)+1))))))))
+ {
+ case 0x0596:
+ case 0x0597:
+ case 0x0599:
+ case 0x059A:
+ case 0x05A9:
+ /* These states need a TRUE physical address. */
+ need = gcvTRUE;
+ break;
+ }
+ }
+
+ /* Return the flag. */
+ *NeedBase = need;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
+ return gcvSTATUS_OK;
+}
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.h
new file mode 100644
index 0000000..e960780
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/gc_hal_kernel_hardware.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_hardware_h_
+#define __gc_hal_kernel_hardware_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* gckHARDWARE object. */
+struct _gckHARDWARE
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gctKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Pointer to gctOS object. */
+ gckOS os;
+
+ /* Chip characteristics. */
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures0;
+ gctUINT32 chipMinorFeatures1;
+ gctBOOL allowFastClear;
+ gctBOOL allowCompression;
+ gctUINT32 powerBaseAddress;
+ gctBOOL extraEventStates;
+
+ gctUINT32 streamCount;
+ gctUINT32 registerMax;
+ gctUINT32 threadCount;
+ gctUINT32 shaderCoreCount;
+ gctUINT32 vertexCacheSize;
+ gctUINT32 vertexOutputBufferSize;
+
+ /* Big endian */
+ gctBOOL bigEndian;
+
+ /* Chip status */
+ gctPOINTER powerMutex;
+ gctUINT32 powerProcess;
+ gctUINT32 powerThread;
+ gceCHIPPOWERSTATE chipPowerState;
+ gctUINT32 lastWaitLink;
+ gckRecursiveMutex recMutexPower;
+
+ /* force GC to hang once */
+ gctBOOL hang;
+};
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/makefile.linux b/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/makefile.linux
new file mode 100644
index 0000000..ca9f433
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/arch/unified/hal/kernel/makefile.linux
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+
+#
+# Linux build file for architecture dependent kernel HAL layer.
+#
+#
+
+
+################################################################################
+# Include common definitions.
+
+include $(AQROOT)/makefile.linux.def
+
+################################################################################
+# Define a shortcut for the main target.
+
+STATIC = 1
+TARGET_NAME = libhalarchkernel.a
+
+################################################################################
+# Supply additional include directories.
+
+INCLUDE += -I$(AQROOT)/hal/inc
+INCLUDE += -I$(AQROOT)/hal/kernel
+INCLUDE += -I$(AQARCH)/hal/kernel
+INCLUDE += -I$(AQARCH)/cmodel/inc
+
+CFLAGS += $(INCLUDE) -Werror -ansi
+
+################################################################################
+# Describe object files.
+
+OBJECTS = $(OBJ_DIR)/gc_hal_kernel_hardware.o
+
+include $(AQROOT)/common.target
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/common.node b/kernel_drivers/gc600_driver_dove/galcore_ko_src/common.node
new file mode 100644
index 0000000..5a2c914
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/common.node
@@ -0,0 +1,45 @@
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public Lisence 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.
+#
+##############################################################################
+
+
+#
+# Common makefile for the node.
+#
+
+################################################################################
+# Specify the targets.
+
+.PHONY: all clean install $(MODULES)
+
+all: $(MAIN_MODULE)
+
+clean:
+ $(MAKE) V_TARGET=clean STATIC_LINK=$(STATIC_LINK)
+
+install:
+ $(MAKE) V_TARGET=install STATIC_LINK=$(STATIC_LINK)
+
+ifneq ($(VIVANTE_NO_3D), 1)
+$(MODULES):
+ @test ! -d $@ || $(MAKE) --directory=$@ $(V_TARGET) STATIC_LINK=$(STATIC_LINK)
+else
+$(MODULES):
+ @test ! -d $@ || $(MAKE) --directory=$@ $(V_TARGET) VIVANTE_NO_3D=1 STATIC_LINK=$(STATIC_LINK)
+endif
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/common.target b/kernel_drivers/gc600_driver_dove/galcore_ko_src/common.target
new file mode 100644
index 0000000..d28664d
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/common.target
@@ -0,0 +1,116 @@
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public Lisence 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.
+#
+##############################################################################
+
+
+################################################################################
+# Define a shortcut for the main target.
+#SO_SUFFIX = .1
+SO_SUFFIX =
+TARGET_OUTPUT = $(OBJ_DIR)/$(TARGET_NAME)
+
+################################################################################
+# Specify targets.
+
+all: $(TARGET_OUTPUT)
+
+clean:
+ @rm -f $(PREREQUISITES)
+ @rm -rf $(OBJ_DIR)/* $(OBJ_DIR)
+ @rm -rf $(CLEAN_EXTRA)
+
+install: $(TARGET_OUTPUT)
+ifneq ($(INSTALL_DIR),)
+ @mkdir -p $(INSTALL_DIR)
+ @-cp $(TARGET_OUTPUT) $(INSTALL_DIR)
+endif
+
+ifeq ($(COMMON_LITE), 1)
+ PREREQUISITES := .Prerequisites_cl
+else
+ PREREQUISITES := .Prerequisites
+endif
+
+ifeq ($(DEBUG), 1)
+ PREREQUISITES := $(PREREQUISITES)_d
+else
+ PREREQUISITES := $(PREREQUISITES)_r
+endif
+
+MAKEFILE_NAME = makefile.linux
+
+ifeq ($(STATIC_LINK),1)
+ifneq ($(USE_ARMCC), 1)
+ PFLAGS += -static
+else
+ PFLAGS += -L--no_search_dynamic_libraries
+endif
+endif
+
+ifeq ($(PROGRAM), 1)
+$(TARGET_OUTPUT): $(PREREQUISITES) $(OBJECTS)
+ifeq ($(SRC_CXX),)
+ $(CC) $(PFLAGS) $(OBJECTS) $(LIBS) -o $(TARGET_OUTPUT)
+else
+ $(CXX) $(PFLAGS) $(OBJECTS) $(LIBS) -o $(TARGET_OUTPUT)
+endif
+
+ifneq ($(USE_ARMCC), 1)
+ifneq ($(DEBUG), 1)
+ $(STRIP) $(TARGET_OUTPUT)
+endif
+endif
+endif
+
+ifeq ($(DYNAMIC), 1)
+ifeq ($(USE_ARMCC), 1)
+LFLAGS += --shared -L--soname=,$(TARGET_NAME)$(SO_SUFFIX)
+else
+LFLAGS += --shared -L--soname=,$(TARGET_NAME)
+endif
+else
+ifeq ($(CONFIG_DOVE_GPU), 1)
+LFLAGS += -Wall -shared -Wl,-soname,$(TARGET_NAME)$(SO_SUFFIX)
+else
+LFLAGS += -Wall -shared -Wl,-soname,$(TARGET_NAME)
+endif
+endif
+$(TARGET_OUTPUT): $(PREREQUISITES) $(OBJECTS)
+ $(CC) $(LFLAGS) $(OBJECTS) $(LIBS) -o $(TARGET_OUTPUT)
+endif
+
+ifeq ($(STATIC), 1)
+$(TARGET_OUTPUT): $(PREREQUISITES) $(OBJECTS)
+ $(AR) -r $(TARGET_OUTPUT) $(OBJECTS)
+ifneq ($(USE_ARMCC), 1)
+ $(RANLIB) $(TARGET_OUTPUT)
+endif
+endif
+
+$(PREREQUISITES): $(MAKEFILE_NAME)
+ @-mkdir -p $(OBJ_DIR)
+ @-touch $(PREREQUISITES)
+
+$(OBJ_DIR)/%.o: %.c $(PREREQUISITES)
+ @mkdir -p $(OBJ_DIR)
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+$(OBJ_DIR)/%.o: %.cpp $(PREREQUISITES)
+ @mkdir -p $(OBJ_DIR)
+ $(CXX) -c $(CFLAGS) -o $@ $<
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/config b/kernel_drivers/gc600_driver_dove/galcore_ko_src/config
new file mode 100644
index 0000000..22fda3c
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/config
@@ -0,0 +1,27 @@
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public Lisence for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+ARCH_TYPE ?= arm
+SDK_DIR ?= $(AQROOT)/build/sdk
+USE_3D_VG = 1
+USE_PROFILER ?= 0
+USE_MRVL_PROFILER ?= 0
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/Kbuild b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/Kbuild
new file mode 100644
index 0000000..21c0ac6
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/Kbuild
@@ -0,0 +1,134 @@
+##############################################################################
+#
+# Copyright (C) 2002 - 2009 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public Lisence 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 Lisence for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+
+#
+# Linux build file for kernel HAL driver.
+#
+
+include $(AQROOT)/config
+
+DRIVER_OUT_DIR = hal/driver
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+ifeq ($(KERNELRELEASE), )
+
+.PHONY: all clean install
+
+# Define targets.
+all:
+ @mkdir -p $(DRIVER_OUT_DIR)
+ @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+
+clean:
+ @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` clean
+ @rm -rf $(DRIVER_OUT_DIR)
+ @rm -rf modules.order Module.symvers
+
+install: all
+ @mkdir -p $(SDK_DIR)/drivers
+ @cp $(DRIVER_OUT_DIR)/galcore.ko $(SDK_DIR)/drivers
+
+else
+
+
+EXTRA_CFLAGS += -DLINUX -DDRIVER
+
+ifeq ($(ABI), 0)
+else
+EXTRA_CFLAGS += -mabi=$(ABI)
+endif
+
+ifeq ($(ENUM_WORKAROUND), 1)
+EXTRA_CFLAGS += -DENUM_WORKAROUND=1
+else
+EXTRA_CFLAGS += -DENUM_WORKAROUND=0
+endif
+
+ifeq ($(FLAREON),1)
+EXTRA_CFLAGS += -DFLAREON
+endif
+
+ifeq ($(DEBUG), 1)
+EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
+else
+EXTRA_CFLAGS += -DDBG=0
+endif
+
+ifeq ($(NO_DMA_COHERENT), 1)
+EXTRA_CFLAGS += -DNO_DMA_COHERENT
+endif
+
+ifeq ($(ENABLE_ARM_L2_CACHE), 1)
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=1
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifeq ($(USE_VIVANTE), 1)
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
+else
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=0
+endif
+
+ifeq ($(ANDROID), 1)
+EXTRA_CFLAGS += -DANDROID=1
+endif
+
+ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
+else
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
+endif
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/cmodel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/user
+
+OS_KERNEL_DIR := os/linux/kernel
+ARCH_KERNEL_DIR := ../arch/$(notdir $(AQARCH))/hal/kernel
+HAL_KERNEL_DIR := kernel
+
+OBJS := $(OS_KERNEL_DIR)/Driver.o \
+ $(OS_KERNEL_DIR)/Device.o \
+ $(OS_KERNEL_DIR)/Debug.o \
+ $(OS_KERNEL_DIR)/Kernel.o \
+ $(OS_KERNEL_DIR)/Os.o
+
+OBJS += $(HAL_KERNEL_DIR)/Command.o \
+ $(HAL_KERNEL_DIR)/Event.o \
+ $(HAL_KERNEL_DIR)/Heap.o \
+ $(HAL_KERNEL_DIR)/Kernel.o \
+ $(HAL_KERNEL_DIR)/Mmu.o \
+ $(HAL_KERNEL_DIR)/VidMem.o
+
+OBJS += $(ARCH_KERNEL_DIR)/Hardware.o
+
+obj-m = $(DRIVER_OUT_DIR)/galcore.o
+
+$(DRIVER_OUT_DIR)/galcore-objs = $(OBJS)
+
+endif
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal.h
new file mode 100644
index 0000000..e9ce46f
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal.h
@@ -0,0 +1,2071 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_h_
+#define __gc_hal_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+#include "gc_hal_profiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* the number of profiling nodes */
+#define NUM_PROFILE_NODES 100
+
+/* temporarily place gralloc defination here, should be moved to android header file later */
+#define GRALLOC_USAGE_GLES20_RENDER 0x10000000
+
+/* BSP idle profile Macros */
+#if ENABLE_BSP_IDLE_PROFILE
+/*
+dev_id: 1 vpu 0 gpu
+State: 1 run 0 idle
+Start: 2 init 1 start 0 stop
+*/
+#define BSP_IDLE_PROFILE(dev_id,state,start) \
+do { \
+ if(1) \
+ gcmkPRINT("--->%s\t\tstart_profile(0,%d,%d)\t%s\n", \
+ __FUNCTION__,state,start,(start==1)?(state?"busy-time":"\tidle-time"):"init"); \
+ start_profile(dev_id,state,start); \
+} while(0);
+#define BSP_IDLE_PROFILE_INIT BSP_IDLE_PROFILE(0, 0, 2)
+#define BSP_IDLE_PROFILE_CALC_BUSY_TIME BSP_IDLE_PROFILE(0, 1, 1)
+#define BSP_IDLE_PROFILE_CALC_IDLE_TIME BSP_IDLE_PROFILE(0, 0, 1)
+#else /* Disable bsp_idle_profile or OTHER PLATFORMs */
+#define BSP_IDLE_PROFILE_INIT
+#define BSP_IDLE_PROFILE_CALC_BUSY_TIME
+#define BSP_IDLE_PROFILE_CALC_IDLE_TIME
+#endif
+
+/******************************************************************************\
+******************************* Alignment Macros *******************************
+\******************************************************************************/
+#define GC_NOP_COMMAND 0x18000000
+
+#define gcmALIGN(n, align) \
+( \
+ ((n) + ((align) - 1)) & ~((align) - 1) \
+)
+
+/******************************************************************************\
+***************************** Element Count Macro *****************************
+\******************************************************************************/
+
+#define gcmSIZEOF(a) \
+( \
+ (gctSIZE_T) (sizeof(a)) \
+)
+
+#define gcmCOUNTOF(a) \
+( \
+ sizeof(a) / sizeof(a[0]) \
+)
+
+/******************************************************************************\
+******************************** gcsOBJECT Object *******************************
+\******************************************************************************/
+
+/* Type of objects. */
+typedef enum _gceOBJECT_TYPE
+{
+ gcvOBJ_UNKNOWN = 0,
+ gcvOBJ_2D = gcmCC('2','D',' ',' '),
+ gcvOBJ_3D = gcmCC('3','D',' ',' '),
+ gcvOBJ_ATTRIBUTE = gcmCC('A','T','T','R'),
+ gcvOBJ_BRUSHCACHE = gcmCC('B','R','U','$'),
+ gcvOBJ_BRUSHNODE = gcmCC('B','R','U','n'),
+ gcvOBJ_BRUSH = gcmCC('B','R','U','o'),
+ gcvOBJ_BUFFER = gcmCC('B','U','F','R'),
+ gcvOBJ_COMMAND = gcmCC('C','M','D',' '),
+ gcvOBJ_COMMANDBUFFER = gcmCC('C','M','D','B'),
+ gcvOBJ_CONTEXT = gcmCC('C','T','X','T'),
+ gcvOBJ_CONTEXTBUFFER = gcmCC('C','T','X','B'),
+ gcvOBJ_DEVICE = gcmCC('D','E','V',' '),
+ gcvOBJ_DUMP = gcmCC('D','U','M','P'),
+ gcvOBJ_EVENT = gcmCC('E','V','N','T'),
+ gcvOBJ_FUNCTION = gcmCC('F','U','N','C'),
+ gcvOBJ_HAL = gcmCC('H','A','L',' '),
+ gcvOBJ_HARDWARE = gcmCC('H','A','R','D'),
+ gcvOBJ_HEAP = gcmCC('H','E','A','P'),
+ gcvOBJ_INDEX = gcmCC('I','N','D','X'),
+ gcvOBJ_INTERRUPT = gcmCC('I','N','T','R'),
+ gcvOBJ_KERNEL = gcmCC('K','E','R','N'),
+ gcvOBJ_MEMORYBUFFER = gcmCC('M','E','M','B'),
+ gcvOBJ_MMU = gcmCC('M','M','U',' '),
+ gcvOBJ_OS = gcmCC('O','S',' ',' '),
+ gcvOBJ_OUTPUT = gcmCC('O','U','T','P'),
+ gcvOBJ_PAINT = gcmCC('P','N','T',' '),
+ gcvOBJ_PATH = gcmCC('P','A','T','H'),
+ gcvOBJ_QUEUE = gcmCC('Q','U','E',' '),
+ gcvOBJ_SAMPLER = gcmCC('S','A','M','P'),
+ gcvOBJ_SHADER = gcmCC('S','H','D','R'),
+ gcvOBJ_STREAM = gcmCC('S','T','R','M'),
+ gcvOBJ_SURF = gcmCC('S','U','R','F'),
+ gcvOBJ_TEXTURE = gcmCC('T','X','T','R'),
+ gcvOBJ_UNIFORM = gcmCC('U','N','I','F'),
+ gcvOBJ_VARIABLE = gcmCC('V','A','R','I'),
+ gcvOBJ_VERTEX = gcmCC('V','R','T','X'),
+ gcvOBJ_VIDMEM = gcmCC('V','M','E','M'),
+ gcvOBJ_VG = gcmCC('V','G',' ',' '),
+}
+gceOBJECT_TYPE;
+
+/* gcsOBJECT object defintinon. */
+typedef struct _gcsOBJECT
+{
+ /* Type of an object. */
+ gceOBJECT_TYPE type;
+}
+gcsOBJECT;
+
+/* Kernel settings. */
+typedef struct _gcsKERNEL_SETTINGS
+{
+ /* Used RealTime signal between kernel and user. */
+ gctINT signal;
+}
+gcsKERNEL_SETTINGS;
+
+typedef struct _gckHARDWARE * gckHARDWARE;
+
+/*******************************************************************************
+**
+** gcmVERIFY_OBJECT
+**
+** Assert if an object is invalid or is not of the specified type. If the
+** object is invalid or not of the specified type, gcvSTATUS_INVALID_OBJECT
+** will be returned from the current function. In retail mode this macro
+** does nothing.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_OBJECT(prefix, obj, t) \
+ do \
+ { \
+ if ((obj) == gcvNULL) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: NULL"); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT((obj) != gcvNULL); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ } \
+ else if (((gcsOBJECT*) (obj))->type != t) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: %c%c%c%c", \
+ gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcm, obj, t)
+# define gcmkVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcmk, obj, t)
+#else
+# define gcmVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+# define gcmkVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************\
+********************************** gckOS Object *********************************
+\******************************************************************************/
+
+typedef struct _gckOS * gckOS;
+
+/*!
+*********************************************************************
+* \struct _gckRecursiveMutex
+* \brief
+* Data structure for recursive lock.
+*********************************************************************
+*/
+typedef struct _gckRecursiveMutex * gckRecursiveMutex;
+struct _gckRecursiveMutex
+{
+ /* Thread lock the mutex. */
+ gctINT32 pThread;
+ /* Lock times. */
+ gctUINT32 nReference;
+ /* Access mutex. */
+ gctPOINTER accMutex;
+ /* Underly mutex. */
+ gctPOINTER undMutex;
+};
+
+/* 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
+ );
+
+/*Simulate allocate memory random fail */
+gctBOOL
+gckOS_ForceMemAllocFail(gckOS Os);
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Wrapper for allocation memory.. */
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Wrapper for freeing memory. */
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Lock pages. */
+gceSTATUS
+gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+#endif
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+#ifdef __QNXNTO__
+ IN gctPOINTER Logical,
+#endif
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ );
+
+/* Unlock pages. */
+gceSTATUS
+gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+#endif
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Free paged memory. */
+gceSTATUS
+gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Allocate non-paged memory. */
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non-paged memory. */
+gceSTATUS
+gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get the number fo bytes per page. */
+gceSTATUS
+gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ );
+
+/* Get the physical address of a corresponding logical address. */
+gceSTATUS
+gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ );
+
+/* Map physical memory. */
+gceSTATUS
+gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctUINT32 OriginalLogical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap previously mapped physical memory. */
+gceSTATUS
+gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+/* Read data from a register directly without mutex protection. */
+gceSTATUS
+gckOS_DirectReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Write data to a 32-bit memory location. */
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ );
+
+/* Map physical memory into the process space. */
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap physical memory from the process space. */
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Create a new mutex. */
+gceSTATUS
+gckOS_CreateMutex(
+ IN gckOS Os,
+ OUT gctPOINTER * Mutex
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Create a new recursive mutex. */
+gceSTATUS
+gckOS_CreateRecMutex(
+ IN gckOS Os,
+ OUT gckRecursiveMutex *Mutex
+ );
+
+/* Delete a recursive mutex. */
+gceSTATUS
+gckOS_DeleteRecMutex(
+ IN gckOS Os,
+ IN gckRecursiveMutex Mutex
+ );
+
+/* Acquire a recursive mutex. */
+gceSTATUS
+gckOS_AcquireRecMutex(
+ IN gckOS Os,
+ IN gckRecursiveMutex Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a recursive mutex. */
+gceSTATUS
+gckOS_ReleaseRecMutex(
+ IN gckOS Os,
+ IN gckRecursiveMutex 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
+ );
+
+/* Update video memory usage. */
+gceSTATUS
+gckOS_UpdateVidMemUsage(
+ IN gckOS Os,
+ IN gctBOOL IsAllocated,
+ IN gctSIZE_T Bytes
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS gckOS_Udelay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ );
+
+/* Memory barrier. */
+gceSTATUS
+gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ );
+
+/* Map user pointer. */
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Unmap user pointer. */
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ );
+
+gceSTATUS
+gckOS_ClockOff(
+ IN gckOS Os,
+ IN gctBOOL disableClk,
+ IN gctBOOL disablePwr
+ );
+
+gceSTATUS
+gckOS_ClockOn(
+ IN gckOS Os,
+ IN gctBOOL enableClk,
+ IN gctBOOL enablePwr,
+ IN gctUINT64 Frequency
+ );
+
+gceSTATUS
+gckOS_PowerOff(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_PowerOn(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_PowerOffWhenIdle(
+ IN gckOS Os,
+ IN gctBOOL needProfile
+ );
+
+gceSTATUS
+gckOS_Reset(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_SetConstraint(
+ IN gckOS Os,
+ IN gctBOOL enableDVFM,
+ IN gctBOOL enableLPM
+ );
+
+gceSTATUS
+gckOS_UnSetConstraint(
+ IN gckOS Os,
+ IN gctBOOL enableDVFM,
+ IN gctBOOL enableLPM
+ );
+
+gceSTATUS
+gckOS_NotifyIdle(
+ IN gckOS Os,
+ IN gctBOOL Idle
+ );
+
+gctUINT32
+gckOS_GetTicks(
+ void
+ );
+
+gceSTATUS
+gckOS_IdleProfile(
+ IN gckOS Os,
+ IN OUT gctUINT32* Timeslice,
+ OUT gctUINT32* IdleTime,
+ OUT gctUINT32* StateSwitchTimes
+ );
+
+gceSTATUS gckOS_DumpToFile(
+ IN gckOS Os,
+ IN gctCONST_STRING filename,
+ IN gctPOINTER logical,
+ IN gctSIZE_T size
+ );
+
+#ifdef __QNXNTO__
+/* Map user physical address. */
+gceSTATUS
+gckOS_MapUserPhysical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Phys,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Allocate from user's shared pool. */
+gceSTATUS
+gckOS_AllocateNonPagedMemoryShmPool(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+#endif
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Perform a memory copy. */
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ );
+
+/* Zero memory. */
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Device I/O control to the kernel HAL layer. */
+gceSTATUS
+gckOS_DeviceControl(
+ IN gckOS Os,
+ IN gctBOOL FromUser,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ OUT gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+gceSTATUS gckOS_FreeProcessResource(IN gckOS os, gctUINT32 pid);
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ );
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ );
+
+/******************************************************************************\
+********************************** Signal Object *********************************
+\******************************************************************************/
+
+/* User signal command codes. */
+typedef enum _gceUSER_SIGNAL_COMMAND_CODES
+{
+ gcvUSER_SIGNAL_CREATE,
+ gcvUSER_SIGNAL_DESTROY,
+ gcvUSER_SIGNAL_SIGNAL,
+ gcvUSER_SIGNAL_WAIT,
+}
+gceUSER_SIGNAL_COMMAND_CODES;
+
+/* Create a signal. */
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gckOS_WaitSignalNoInterruptible(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+/* Map a user signal to the kernel space. */
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ );
+
+/* UnMap a user signal */
+gceSTATUS
+gckOS_UnMapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL MappedSignal
+ );
+
+/* Map user memory. */
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+#ifdef ANDROID_VERSION_ECLAIR
+gceSTATUS
+gcoOS_FlushCache(
+ int fd,
+ int offset,
+ int size
+ );
+#endif
+#if !USE_NEW_LINUX_SIGNAL
+/* Create signal to be used in the user space. */
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ IN gceSIGNAL_TYPE SignalType,
+ OUT gctINT * SignalID
+ );
+
+/* Destroy signal used in the user space. */
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ );
+
+/* Wait for signal used in the user space. */
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ );
+
+/* Signal a signal used in the user space. */
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ );
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/* Set a signal owned by a process. */
+#if defined(__QNXNTO__)
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctINT Recvid,
+ IN gctINT Coid
+ );
+#else
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ );
+#endif
+
+/******************************************************************************\
+** Cache Support
+*/
+
+gceSTATUS
+gckOS_CacheFlush(
+ gckOS Os,
+ gctHANDLE ProcessId,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CacheInvalidate(
+ gckOS Os,
+ gctHANDLE ProcessId,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+/******************************************************************************\
+** Debug Support
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gckOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+/*******************************************************************************
+** Broadcast interface.
+*/
+
+typedef enum _gceBROADCAST
+{
+ /* GPU might be idle. */
+ gcvBROADCAST_GPU_IDLE,
+
+ /* A commit is going to happen. */
+ gcvBROADCAST_GPU_COMMIT,
+
+ /* GPU seems to be stuck. */
+ gcvBROADCAST_GPU_STUCK,
+
+ /* First process gets attached. */
+ gcvBROADCAST_FIRST_PROCESS,
+
+ /* Last process gets detached. */
+ gcvBROADCAST_LAST_PROCESS,
+
+ /* AXI bus error. */
+ gcvBROADCAST_AXI_BUS_ERROR,
+}
+gceBROADCAST;
+
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ );
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.?
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ );
+
+/*******************************************************************************
+** Semaphores.
+*/
+
+/* Create a new semaphore. */
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ );
+
+/* Delete a semahore. */
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Acquire a semahore. */
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Release a semahore. */
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/******************************************************************************\
+********************************* gckHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gckHEAP * gckHEAP;
+
+/* Construct a new gckHEAP object. */
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ );
+
+/* Destroy an gckHEAP object. */
+gceSTATUS
+gckHEAP_Destroy(
+ IN gckHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+/* Profile the heap. */
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ );
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gckHEAP_Test(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Vectors,
+ IN gctSIZE_T MaxSize
+ );
+#endif
+
+/******************************************************************************\
+******************************** gckVIDMEM Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVIDMEM * gckVIDMEM;
+typedef union _gcuVIDMEM_NODE * gcuVIDMEM_NODE_PTR;
+typedef struct _gckKERNEL * gckKERNEL;
+
+/* Construct a new gckVIDMEM object. */
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T Banking,
+ OUT gckVIDMEM * Memory
+ );
+
+/* Destroy an gckVDIMEM object. */
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ );
+
+/* Allocate rectangular memory. */
+gceSTATUS
+gckVIDMEM_Allocate(
+ IN gckVIDMEM Memory,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT BytesPerPixel,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Allocate linear memory. */
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+ IN gckVIDMEM Memory,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gckVIDMEM_Free(
+ IN gcuVIDMEM_NODE_PTR Node
+ );
+
+/* Lock memory. */
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ OUT gctUINT32 * Address
+ );
+
+/* Unlock memory. */
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ );
+
+/* Construct a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+ IN gcuVIDMEM_NODE_PTR Node
+ );
+
+#ifdef __QNXNTO__
+/* Set the allocating process' PID for this node. */
+gceSTATUS
+gckVIDMEM_SetPID(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctUINT32 Pid);
+#endif
+
+/******************************************************************************\
+******************************** gckKERNEL Object ******************************
+\******************************************************************************/
+
+struct _gcsHAL_INTERFACE;
+
+/* Notifications. */
+typedef enum _gceNOTIFY
+{
+ gcvNOTIFY_INTERRUPT,
+ gcvNOTIFY_COMMAND_QUEUE,
+}
+gceNOTIFY;
+
+/* Event locations. */
+typedef enum _gceKERNEL_WHERE
+{
+ gcvKERNEL_COMMAND,
+ gcvKERNEL_VERTEX,
+ gcvKERNEL_TRIANGLE,
+ gcvKERNEL_TEXTURE,
+ gcvKERNEL_PIXEL,
+}
+gceKERNEL_WHERE;
+
+/* Flush flags. */
+typedef enum _gceKERNEL_FLUSH
+{
+ gcvFLUSH_COLOR = 0x01,
+ gcvFLUSH_DEPTH = 0x02,
+ gcvFLUSH_TEXTURE = 0x04,
+ gcvFLUSH_2D = 0x08,
+ gcvFLUSH_ALL = gcvFLUSH_COLOR
+ | gcvFLUSH_DEPTH
+ | gcvFLUSH_TEXTURE
+ | gcvFLUSH_2D,
+}
+gceKERNEL_FLUSH;
+
+/* Construct a new gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ OUT gckKERNEL * Kernel
+ );
+
+/* Destroy an gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Lookup the gckVIDMEM object for a pool. */
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ );
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes,
+#endif
+ OUT gctPOINTER * Logical
+ );
+
+#ifdef __QNXNTO__
+/* Unmap video memory. */
+gceSTATUS
+gckKERNEL_UnmapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes
+ );
+#endif
+
+/* Map memory. */
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Notification of events. */
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+ IN gceNOTIFY Notifcation,
+ IN gctBOOL Data
+ );
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ );
+
+/*******************************************************************************
+**
+** gckKERNEL_Recovery
+**
+** Try to recover the GPU from a fatal error.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+ IN gckKERNEL Kernel
+ );
+
+/******************************************************************************\
+******************************* gckHARDWARE Object *****************************
+\******************************************************************************/
+
+/* Construct a new gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckHARDWARE * Hardware
+ );
+
+/* Destroy an gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Destroy(
+ IN gckHARDWARE Hardware
+ );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ );
+
+/* Build virtual address. */
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * Alignment,
+ OUT gctSIZE_T * ReservedHead,
+ OUT gctSIZE_T * ReservedTail
+ );
+
+/* Add a WAIT/LINK pair in the command queue. */
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPOINTER * Wait,
+ OUT gctSIZE_T * WaitBytes
+ );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+#ifdef __QNXNTO__
+ IN gctPOINTER Physical,
+ IN gctBOOL PhysicalAddresses,
+#endif
+ IN gctSIZE_T Bytes
+ );
+
+/* Add an END command in the command queue. */
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a NOP command in the command queue. */
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a WAIT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Wait(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Count,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a PIPESELECT command in the command queue. */
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pipe,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a LINK command in the command queue. */
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctPOINTER FetchAddress,
+ IN gctSIZE_T FetchSize,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add an EVENT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Query the available memory. */
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures1
+ );
+
+/* Query the specifications sof the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipSpecs(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR StreamCount,
+ OUT gctUINT32_PTR RegisterMax,
+ OUT gctUINT32_PTR ThreadCount,
+ OUT gctUINT32_PTR ShaderCoreCount,
+ OUT gctUINT32_PTR VertexCacheSize,
+ OUT gctUINT32_PTR VertexOutputBufferSize
+ );
+
+/* Convert an API format. */
+gceSTATUS
+gckHARDWARE_ConvertFormat(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Align size to tile boundary. */
+gceSTATUS
+gckHARDWARE_AlignToTile(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height,
+ OUT gctBOOL_PTR SuperTiled
+ );
+
+/* Update command queue tail pointer. */
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ );
+
+#ifdef __QNXNTO__
+/* Convert physical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertPhysical(
+ IN gckHARDWARE Hardware,
+ IN gctPHYS_ADDR Physical,
+ OUT gctUINT32 * Address
+ );
+#endif
+
+/* Interrupt manager. */
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL InterruptValid
+ );
+
+/* Program MMU. */
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ );
+
+/* Flush the MMU. */
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ );
+
+/* Get idle register. */
+gceSTATUS
+gckHARDWARE_GetIdle(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ );
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ );
+
+gceSTATUS
+gckHARDWARE_ReadInterrupt(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ );
+
+/* Power management. */
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ );
+
+/* Profile 2D Engine. */
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OUT gcs2D_PROFILE_PTR Profile
+ );
+
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ );
+
+/******************************************************************************\
+***************************** gckINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckINTERRUPT * gckINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+ IN gckKERNEL Kernel
+ );
+
+gceSTATUS
+gckINTERRUPT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckINTERRUPT * Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_Destroy(
+ IN gckINTERRUPT Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_SetHandler(
+ IN gckINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ );
+
+gceSTATUS
+gckINTERRUPT_Notify(
+ IN gckINTERRUPT Interrupt,
+ IN gctBOOL Valid
+ );
+
+/******************************************************************************\
+******************************** gckEVENT Object *******************************
+\******************************************************************************/
+
+typedef struct _gckEVENT * gckEVENT;
+
+/* Construct a new gckEVENT object. */
+gceSTATUS
+gckEVENT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckEVENT * Event
+ );
+
+/* Destroy an gckEVENT object. */
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ );
+
+/* Schedule a FreeNonPagedMemory event. */
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeContiguousMemory event. */
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeVideoMemory event. */
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+ IN gckEVENT Event,
+ IN gcuVIDMEM_NODE_PTR VideoMemory,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a signal event. */
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule an Unlock event. */
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gckEVENT_Submit(
+ IN gckEVENT Event,
+ IN gctBOOL Wait
+ );
+
+struct _gcsQUEUE;
+
+/* Commit an event queue. */
+gceSTATUS
+gckEVENT_Commit(
+ IN gckEVENT Event,
+ IN struct _gcsQUEUE * Queue
+ );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctBOOL IsReset
+ );
+
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ );
+
+/* Try to set idle */
+gceSTATUS
+gckEVENT_TryToSetIdle(
+ 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
+ );
+
+/* Start the command queue. */
+gceSTATUS
+gckCOMMAND_Start(
+ IN gckCOMMAND Command
+ );
+
+/* Stop the command queue. */
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command
+ );
+
+/* Commit a buffer to the command queue. */
+gceSTATUS
+gckCOMMAND_Commit(
+ IN gckCOMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcoCONTEXT Context,
+ IN gctHANDLE Process
+ );
+
+/* Reserve space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctSIZE_T * BufferSize
+ );
+
+/* Release reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Release(
+ IN gckCOMMAND Command
+ );
+
+/* Execute reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequstedBytes
+ );
+
+/* Stall the command queue. */
+gceSTATUS
+gckCOMMAND_Stall(
+ IN gckCOMMAND Command
+ );
+
+/******************************************************************************\
+********************************* gckMMU Object ********************************
+\******************************************************************************/
+
+typedef struct _gckMMU * gckMMU;
+
+/* Construct a new gckMMU object. */
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ );
+
+/* Destroy an gckMMU object. */
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ );
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_InsertNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node);
+
+gceSTATUS
+gckMMU_RemoveNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node);
+#endif
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_FreeHandleMemory(
+ IN gckMMU Mmu,
+ IN gctHANDLE Handle
+ );
+#endif
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gckMMU_Test(
+ IN gckMMU Mmu,
+ IN gctSIZE_T Vectors,
+ IN gctINT MaxSize
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ OUT gcsPROFILER_COUNTERS * Counters
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_base.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_base.h
new file mode 100644
index 0000000..c24f8f7
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_base.h
@@ -0,0 +1,2828 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_base_h_
+#define __gc_hal_base_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+#include "gc_hal_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoHAL * gcoHAL;
+typedef struct _gcoOS * gcoOS;
+typedef struct _gco2D * gco2D;
+typedef struct _gcoVG * gcoVG;
+typedef struct _gco3D * gco3D;
+typedef struct _gcoSURF * gcoSURF;
+typedef struct _gcsSURF_INFO * gcsSURF_INFO_PTR;
+typedef struct _gcsSURF_NODE * gcsSURF_NODE_PTR;
+typedef struct _gcsSURF_FORMAT_INFO * gcsSURF_FORMAT_INFO_PTR;
+typedef struct _gcsPOINT * gcsPOINT_PTR;
+typedef struct _gcsSIZE * gcsSIZE_PTR;
+typedef struct _gcsRECT * gcsRECT_PTR;
+typedef struct _gcsBOUNDARY * gcsBOUNDARY_PTR;
+typedef struct _gcoDUMP * gcoDUMP;
+typedef struct _gcoHARDWARE * gcoHARDWARE;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+/* Video memory pool type. */
+typedef enum _gcePOOL
+{
+ gcvPOOL_UNKNOWN,
+ gcvPOOL_DEFAULT,
+ gcvPOOL_LOCAL,
+ gcvPOOL_LOCAL_INTERNAL,
+ gcvPOOL_LOCAL_EXTERNAL,
+ gcvPOOL_UNIFIED,
+ gcvPOOL_SYSTEM,
+ gcvPOOL_VIRTUAL,
+ gcvPOOL_USER,
+ gcvPOOL_CONTIGUOUS
+}
+gcePOOL;
+
+/* Blending functions. */
+typedef enum _gceBLEND_FUNCTION
+{
+ gcvBLEND_ZERO,
+ gcvBLEND_ONE,
+ gcvBLEND_SOURCE_COLOR,
+ gcvBLEND_INV_SOURCE_COLOR,
+ gcvBLEND_SOURCE_ALPHA,
+ gcvBLEND_INV_SOURCE_ALPHA,
+ gcvBLEND_TARGET_COLOR,
+ gcvBLEND_INV_TARGET_COLOR,
+ gcvBLEND_TARGET_ALPHA,
+ gcvBLEND_INV_TARGET_ALPHA,
+ gcvBLEND_SOURCE_ALPHA_SATURATE,
+ gcvBLEND_CONST_COLOR,
+ gcvBLEND_INV_CONST_COLOR,
+ gcvBLEND_CONST_ALPHA,
+ gcvBLEND_INV_CONST_ALPHA,
+}
+gceBLEND_FUNCTION;
+
+/* Blending modes. */
+typedef enum _gceBLEND_MODE
+{
+ gcvBLEND_ADD,
+ gcvBLEND_SUBTRACT,
+ gcvBLEND_REVERSE_SUBTRACT,
+ gcvBLEND_MIN,
+ gcvBLEND_MAX,
+}
+gceBLEND_MODE;
+
+/* API flags. */
+typedef enum _gceAPI
+{
+ gcvAPI_D3D = 0x1,
+ gcvAPI_OPENGL = 0x2,
+}
+gceAPI;
+
+/* Depth modes. */
+typedef enum _gceDEPTH_MODE
+{
+ gcvDEPTH_NONE,
+ gcvDEPTH_Z,
+ gcvDEPTH_W,
+}
+gceDEPTH_MODE;
+
+typedef enum _gceWHERE
+{
+ gcvWHERE_COMMAND,
+ gcvWHERE_RASTER,
+ gcvWHERE_PIXEL,
+}
+gceWHERE;
+
+typedef enum _gceHOW
+{
+ gcvHOW_SEMAPHORE = 0x1,
+ gcvHOW_STALL = 0x2,
+ gcvHOW_SEMAPHORE_STALL = 0x3,
+}
+gceHOW;
+
+typedef enum _gceSIGNAL_TYPE
+{
+ gcvSIGNAL_NOPE = 0x0,
+ gcvSIGNAL_CONTEXT_GCU = 0x1,
+ gcvSIGNAL_CONTEXT = 0x2,
+ gcvSIGNAL_FENCE_GCU = 0x3,
+ gcvSIGNAL_FENCE = 0x4,
+ gcvSIGNAL_DISPLAY_START = 0x5,
+ gcvSIGNAL_DISPLAY_STOP = 0x6,
+ gcvSIGNAL_WORKER_THREAD = 0x7,
+ gcvSIGNAL_SYNC = 0x8,
+ gcvSIGNAL_SURFACE = 0x9,
+ gcvSIGNAL_TEXTURE = 0x10,
+ gcvSIGNAL_STREAM = 0x11,
+ gcvSIGNAL_INDEX_GROUP = 0x12,
+ gcvSIGNAL_RESERVE_MEM_GROUP = 0x13,
+ gcvSIGNAL_CMD_BUFFER = 0x14,
+ gcvSIGNAL_CONTEXT_BUFFER = 0x15,
+ gcvSIGNAL_INDEX_DYNAMIC = 0x16,
+ gcvSIGNAL_STREAM_DYNAMIC = 0x17,
+ gcvSIGNAL_STALL = 0x18,
+ gcvSIGNAL_RESERVED
+}
+gceSIGNAL_TYPE;
+
+#define gcmSIGNAL_OFFSET 16
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Construct a new gcoHAL object. */
+gceSTATUS
+gcoHAL_Construct(
+ IN gctPOINTER Context,
+ IN gcoOS Os,
+ OUT gcoHAL * Hal
+ );
+
+/* Destroy an gcoHAL object. */
+gceSTATUS
+gcoHAL_Destroy(
+ IN gcoHAL Hal
+ );
+
+/* Get pointer to gco2D object. */
+gceSTATUS
+gcoHAL_Get2DEngine(
+ IN gcoHAL Hal,
+ OUT gco2D * Engine
+ );
+
+/* Get pointer to gcoVG object. */
+gceSTATUS
+gcoHAL_GetVGEngine(
+ IN gcoHAL Hal,
+ OUT gcoVG * Engine
+ );
+
+/* Get pointer to gco3D object. */
+gceSTATUS
+gcoHAL_Get3DEngine(
+ IN gcoHAL Hal,
+ OUT gco3D * Engine
+ );
+
+/* Verify whether the specified feature is available in hardware. */
+gceSTATUS
+gcoHAL_IsFeatureAvailable(
+ IN gcoHAL Hal,
+ IN gceFEATURE Feature
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gcoHAL_QueryChipIdentity(
+ IN gcoHAL Hal,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures
+ );
+
+/* Query the amount of video memory. */
+gceSTATUS
+gcoHAL_QueryVideoMemory(
+ IN gcoHAL Hal,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/* Map video memory. */
+gceSTATUS
+gcoHAL_MapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap video memory. */
+gceSTATUS
+gcoHAL_UnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* Schedule an unmap of a buffer mapped through its physical address. */
+gceSTATUS
+gcoHAL_ScheduleUnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* Schedule an unmap of a user buffer using event mechanism. */
+gceSTATUS
+gcoHAL_ScheduleUnmapUserMemory(
+ IN gcoHAL Hal,
+ IN gctPOINTER Info,
+ IN gctSIZE_T Size,
+ IN gctUINT32 Address,
+ IN gctPOINTER Memory
+ );
+
+/* Commit the current command buffer. */
+gceSTATUS
+gcoHAL_Commit(
+ IN gcoHAL Hal,
+ IN gctBOOL Stall
+ );
+
+/* Query the tile capabilities. */
+gceSTATUS
+gcoHAL_QueryTiled(
+ IN gcoHAL Hal,
+ OUT gctINT32 * TileWidth2D,
+ OUT gctINT32 * TileHeight2D,
+ OUT gctINT32 * TileWidth3D,
+ OUT gctINT32 * TileHeight3D
+ );
+
+gceSTATUS
+gcoHAL_Compact(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_ProfileStart(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_ProfileEnd(
+ IN gcoHAL Hal,
+ IN gctCONST_STRING Title
+ );
+
+/* Power Management */
+gceSTATUS
+gcoHAL_SetPowerManagementState(
+ IN gcoHAL Hal,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gcoHAL_QueryPowerManagementState(
+ IN gcoHAL Hal,
+ OUT gceCHIPPOWERSTATE *State
+ );
+
+/* Set the filter type for filter blit. */
+gceSTATUS
+gcoHAL_SetFilterType(
+ IN gcoHAL Hal,
+ IN gceFILTER_TYPE FilterType
+ );
+
+gceSTATUS
+gcoHAL_GetDump(
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+/* Call the kernel HAL layer. */
+gceSTATUS
+gcoHAL_Call(
+ IN gcoHAL Hal,
+ IN OUT gcsHAL_INTERFACE_PTR Interface
+ );
+
+/* Schedule an event. */
+gceSTATUS
+gcoHAL_ScheduleEvent(
+ IN gcoHAL Hal,
+ IN OUT gcsHAL_INTERFACE_PTR Interface
+ );
+
+/* Destroy a surface. */
+gceSTATUS
+gcoHAL_DestroySurface(
+ IN gcoHAL Hal,
+ IN gcoSURF Surface
+ );
+
+/******************************************************************************\
+********************************** gcoOS Object *********************************
+\******************************************************************************/
+
+/* Construct a new gcoOS object. */
+gceSTATUS
+gcoOS_Construct(
+ IN gctPOINTER Context,
+ OUT gcoOS * Os
+ );
+
+/* Destroy an gcoOS object. */
+gceSTATUS
+gcoOS_Destroy(
+ IN gcoOS Os
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gcoOS_GetBaseAddress(
+ IN gcoOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gcoOS_Allocate(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gcoOS_Free(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoOS_AllocateMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoOS_FreeMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gcoOS_AllocateContiguous(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gcoOS_FreeContiguous(
+ IN gcoOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Map user memory. */
+gceSTATUS
+gcoOS_MapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gcoOS_UnmapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+/* Device I/O Control call to the kernel HAL layer. */
+gceSTATUS
+gcoOS_DeviceControl(
+ IN gcoOS Os,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ IN gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+/* Allocate non paged memory. */
+gceSTATUS gcoOS_AllocateNonPagedMemory(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non paged memory. */
+gceSTATUS gcoOS_FreeNonPagedMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+typedef enum _gceFILE_MODE
+{
+ gcvFILE_CREATE = 0,
+ gcvFILE_APPEND,
+ gcvFILE_READ,
+ gcvFILE_CREATETEXT,
+ gcvFILE_APPENDTEXT,
+ gcvFILE_READTEXT,
+}
+gceFILE_MODE;
+
+/* Open a file. */
+gceSTATUS
+gcoOS_Open(
+ IN gcoOS Os,
+ IN gctCONST_STRING FileName,
+ IN gceFILE_MODE Mode,
+ OUT gctFILE * File
+ );
+
+/* Close a file. */
+gceSTATUS
+gcoOS_Close(
+ IN gcoOS Os,
+ IN gctFILE File
+ );
+
+/* Read data from a file. */
+gceSTATUS
+gcoOS_Read(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctPOINTER Data,
+ OUT gctSIZE_T * ByteRead
+ );
+
+/* Write data to a file. */
+gceSTATUS
+gcoOS_Write(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+typedef enum _gceFILE_WHENCE
+{
+ gcvFILE_SEEK_SET,
+ gcvFILE_SEEK_CUR,
+ gcvFILE_SEEK_END
+}
+gceFILE_WHENCE;
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_Seek(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Offset,
+ IN gceFILE_WHENCE Whence
+ );
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_SetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Position
+ );
+
+/* Get the current position of a file. */
+gceSTATUS
+gcoOS_GetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ OUT gctUINT32 * Position
+ );
+
+/* Perform a memory copy. */
+gceSTATUS
+gcoOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ );
+
+/* Perform a memory fill. */
+gceSTATUS
+gcoOS_MemFill(
+ IN gctPOINTER Destination,
+ IN gctUINT8 Filler,
+ IN gctSIZE_T Bytes
+ );
+
+/* Zero memory. */
+gceSTATUS
+gcoOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Find the last occurance of a character inside a string. */
+gceSTATUS
+gcoOS_StrFindReverse(
+ IN gctCONST_STRING String,
+ IN gctINT8 Character,
+ OUT gctSTRING * Output
+ );
+
+gceSTATUS
+gcoOS_StrLen(
+ IN gctCONST_STRING String,
+ OUT gctSIZE_T * Length
+ );
+
+gceSTATUS
+gcoOS_StrDup(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ OUT gctSTRING * Target
+ );
+
+/* Copy a string. */
+gceSTATUS
+gcoOS_StrCopySafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Append a string. */
+gceSTATUS
+gcoOS_StrCatSafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Compare two strings. */
+gceSTATUS
+gcoOS_StrCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2
+ );
+
+/* Compare characters of two strings. */
+gceSTATUS
+gcoOS_StrNCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2,
+ IN gctSIZE_T Count
+ );
+
+/* Convert string to float. */
+gceSTATUS
+gcoOS_StrToFloat(
+ IN gctCONST_STRING String,
+ OUT gctFLOAT * Float
+ );
+
+/* Convert string to integer. */
+gceSTATUS
+gcoOS_StrToInt(
+ IN gctCONST_STRING String,
+ OUT gctINT * Int
+ );
+
+gceSTATUS
+gcoOS_MemCmp(
+ IN gctCONST_POINTER Memory1,
+ IN gctCONST_POINTER Memory2,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_PrintStrSafe(
+ OUT gctSTRING String,
+ IN gctSIZE_T StringSize,
+ IN OUT gctUINT * Offset,
+ IN gctCONST_STRING Format,
+ ...
+ );
+
+gceSTATUS
+gcoOS_PrintStrVSafe(
+ OUT gctSTRING String,
+ IN gctSIZE_T StringSize,
+ IN OUT gctUINT * Offset,
+ IN gctCONST_STRING Format,
+ IN gctPOINTER Arguments
+ );
+
+gceSTATUS
+gcoOS_LoadLibrary(
+ IN gcoOS Os,
+ IN gctCONST_STRING Library,
+ OUT gctHANDLE * Handle
+ );
+
+gceSTATUS
+gcoOS_FreeLibrary(
+ IN gcoOS Os,
+ IN gctHANDLE Handle
+ );
+
+gceSTATUS
+gcoOS_GetProcAddress(
+ IN gcoOS Os,
+ IN gctHANDLE Handle,
+ IN gctCONST_STRING Name,
+ OUT gctPOINTER * Function
+ );
+
+gceSTATUS
+gcoOS_Compact(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_ProfileStart(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_ProfileEnd(
+ IN gcoOS Os,
+ IN gctCONST_STRING Title
+ );
+
+gceSTATUS
+gcoOS_SetProfileSetting(
+ IN gcoOS Os,
+ IN gctBOOL Enable,
+ IN gctCONST_STRING FileName
+ );
+gctINT32
+gcoOS_GetMilliTime(
+ void
+ );
+
+char* gcoOS_GetProgramName(char* buf, int size);
+
+/* return non-NULL means success. null-terminate guarantee! */
+gctSTRING gcoOS_GetProgramNameWithoutPath(
+ OUT gctSTRING buf,
+ IN const gctSIZE_T size
+ );
+#if MRVL_BENCH
+
+/*
+** Check point for timer.
+** To add new profiling point, modify below two members:
+gceSTATUS
+gcoOS_SetProfileSetting(
+ IN gcoOS Os,
+ IN gctBOOL Enable,
+ IN gctCONST_STRING FileName
+ );
+
+*/
+typedef enum _apiBenchIndex {
+ APIBENCH_INDEX_FRAME,
+ APIBENCH_INDEX_DRAWARRAY,
+ APIBENCH_INDEX_DRAWELEMENTS,
+ APIBENCH_INDEX_BUILDSTREAM,
+ APIBENCH_INDEX_INDEXBUFFER,
+ APIBENCH_INDEX_DRAWARRAY_UPDATESTATE,
+ APIBENCH_INDEX_DRAWARRAY_UPDATESTATE1,
+ APIBENCH_INDEX_UPDATESTATE,
+ APIBENCH_INDEX_UPDATESTATE1,
+ APIBENCH_INDEX_SWAPBUFFERS,
+ APIBENCH_INDEX_DRAWIMAGE,
+ APIBENCH_INDEX_SWTEXTUREUPLOAD,
+ APIBENCH_INDEX_DIRECTTEXTURE,
+ APIBENCH_INDEX_GLEGLIMAGETEXTURE,
+ APIBENCH_INDEX_DRAWTEX,
+ APIBENCH_INDEX_BUFFERDATA,
+ APIBENCH_INDEX_BUFFERSUBDATA,
+ APIBENCH_INDEX_COMPILER_FRONTEND,
+ APIBENCH_INDEX_COMPILER_OPTIMIZING,
+ APIBENCH_INDEX_COMPILER_BACKEND, /* i.e. LINKER */
+ APIBENCH_INDEX_MAX
+}apiBenchIndex;
+
+#define APIBENCHNAME { \
+ "Frame", \
+ "DrawArray", \
+ "DrawElement", \
+ "_buildStream", \
+ "IndexBuffer", \
+ "DrawArray_UpdateState", \
+ "DrawArray_UpdateState1", \
+ "UpdateState", \
+ "UpdateState1", \
+ "eglSwapBuffers", \
+ "DrawImage", \
+ "SWTextureUpload", \
+ "uploadDirectTexture", \
+ "glEGLImageTexture2D", \
+ "glDrawTex", \
+ "glBufferData", \
+ "glBufferSubData", \
+ "_glshCompileShader_frontEnd", \
+ "_glshCompileShader_optimizing",\
+ "_glshLinkShaders", \
+}
+
+/*
+** Check point for state update
+**
+*/
+typedef enum _apiBenchStateIndex {
+ APIBENCH_STATE_INDEX_FRAME,
+ APIBENCH_STATE_INDEX_TEXTURE,
+ APIBENCH_STATE_INDEX_SHADER,
+ APIBENCH_STATE_INDEX_MAX
+}apiBenchStateIndex;
+
+#define APIBENCHSTATENAME { \
+ "Frame", \
+ "Texture", \
+ "Shader", \
+}
+
+ /* Timer structure to store the profile result */
+typedef struct _gcoTIMER
+{
+ gctUINT32 start;
+ gctUINT32 end;
+ gctUINT32 totalTime;
+ gctUINT32 count;
+}gcoTIMER;
+
+ /* global structure for api bench */
+typedef struct _gcoAPIBENCH
+{
+ gctFILE file;
+ /* frame count */
+ gctUINT32 frameCount;
+
+ /* timer object for bench mark */
+ gcoTIMER timer[APIBENCH_INDEX_MAX];
+
+ /* total sent command size */
+ gctUINT32 commandSize;
+
+ /* commit times */
+ gctUINT32 commitNumber;
+
+ /* profile the state update, use same structure of timer */
+ gcoTIMER stateCounter[APIBENCH_STATE_INDEX_MAX];
+
+}gcoAPIBENCH;
+
+ /* Frame count to print */
+#define PROFILE_DRIVER_FRAME_PRINT 10
+
+
+void gcoDUMP_APIBenchStart(
+ IN gcoHAL Hal,
+ IN gctUINT32 timerIndex
+ );
+
+void gcoDUMP_APIBenchEnd(
+ IN gcoHAL Hal,
+ IN gctUINT32 timerIndex
+ );
+
+void gcoDUMP_APIBenchPrint(
+ IN gcoHAL Hal
+ );
+
+void gcoDUMP_APIBenchInit(
+ IN gcoHAL Hal
+ );
+
+void gcoDUMP_APIBenchDestroy(
+ IN gcoHAL Hal
+ );
+
+void gcoDUMP_APIBenchFrame(
+ IN gcoHAL Hal
+ );
+
+void gcoDUMP_APIBenchCommand(
+ IN gcoHAL Hal,
+ IN gctUINT32 size
+ );
+
+void gcoDUMP_APIBenchCommit(
+ IN gcoHAL Hal
+ );
+
+void gcoDUMP_APIBenchStateEnd(
+ IN gcoHAL Hal,
+ IN gctUINT32 stateIndex
+ );
+
+void gcoDUMP_APIBenchStateStart(
+ IN gcoHAL Hal,
+ IN gctUINT32 stateIndex
+ );
+
+#else
+
+
+#endif
+
+/* Query the video memory. */
+gceSTATUS
+gcoOS_QueryVideoMemory(
+ IN gcoOS Os,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Atoms ----------------------------------------------------------------*/
+
+typedef struct gcsATOM * gcsATOM_PTR;
+
+/* Construct an atom. */
+gceSTATUS
+gcoOS_AtomConstruct(
+ IN gcoOS Os,
+ OUT gcsATOM_PTR * Atom
+ );
+
+/* Destroy an atom. */
+gceSTATUS
+gcoOS_AtomDestroy(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom
+ );
+
+/* Increment an atom. */
+gceSTATUS
+gcoOS_AtomIncrement(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+/* Decrement an atom. */
+gceSTATUS
+gcoOS_AtomDecrement(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+gctHANDLE
+gcoOS_GetCurrentProcessID(
+ void
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Time -----------------------------------------------------------------*/
+
+/* Get the number of milliseconds since the system started. */
+gctUINT32
+gcoOS_GetTicks(
+ void
+ );
+
+/* Get time in microseconds. */
+gceSTATUS
+gcoOS_GetTime(
+ gctUINT64_PTR Time
+ );
+
+/* Get CPU usage in microseconds. */
+gceSTATUS
+gcoOS_GetCPUTime(
+ gctUINT64_PTR CPUTime
+ );
+
+/* Get memory usage. */
+gceSTATUS
+gcoOS_GetMemoryUsage(
+ gctUINT32_PTR MaxRSS,
+ gctUINT32_PTR IxRSS,
+ gctUINT32_PTR IdRSS,
+ gctUINT32_PTR IsRSS
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gcoOS_Delay(
+ IN gcoOS Os,
+ IN gctUINT32 Delay
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Mutexes --------------------------------------------------------------*/
+
+/* Create a new mutex. */
+gceSTATUS
+gcoOS_CreateMutex(
+ IN gcoOS Os,
+ OUT gctPOINTER * Mutex
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gcoOS_DeleteMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gcoOS_AcquireMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gcoOS_ReleaseMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Signals --------------------------------------------------------------*/
+
+/* Create a signal. */
+gceSTATUS
+gcoOS_CreateSignal(
+ IN gcoOS Os,
+ IN gctBOOL ManualReset,
+ IN gceSIGNAL_TYPE SignalType,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gcoOS_DestroySignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gcoOS_Signal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gcoOS_WaitSignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+/* Write a register. */
+gceSTATUS
+gcoOS_WriteRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Read a register. */
+gceSTATUS
+gcoOS_ReadRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+gceSTATUS
+gcoOS_CacheFlush(
+ IN gcoOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_CacheInvalidate(
+ IN gcoOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/*******************************************************************************
+** gcoMATH object
+*/
+
+#define gcdPI 3.14159265358979323846f
+
+gctUINT32
+gcoMATH_Log2in5dot5(
+ IN gctINT X
+ );
+
+gctFLOAT
+gcoMATH_Sine(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Cosine(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Floor(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Ceiling(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_SquareRoot(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Log2(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Power(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+gctFLOAT
+gcoMATH_Modulo(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+gctFLOAT
+gcoMATH_Exp(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Absolute(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_ArcCosine(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Tangent(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_UInt2Float(
+ IN gctUINT X
+ );
+
+gctUINT
+gcoMATH_Float2UInt(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Multiply(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+/******************************************************************************\
+**************************** Coordinate Structures *****************************
+\******************************************************************************/
+
+typedef struct _gcsPOINT
+{
+ gctINT32 x;
+ gctINT32 y;
+}
+gcsPOINT;
+
+typedef struct _gcsSIZE
+{
+ gctINT32 width;
+ gctINT32 height;
+}
+gcsSIZE;
+
+typedef struct _gcsRECT
+{
+ gctINT32 left;
+ gctINT32 top;
+ gctINT32 right;
+ gctINT32 bottom;
+}
+gcsRECT;
+
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- gcoSURF Common ------------------------------*/
+
+/* Color format classes. */
+typedef enum _gceFORMAT_CLASS
+{
+ gcvFORMAT_CLASS_RGBA = 4500,
+ gcvFORMAT_CLASS_YUV,
+ gcvFORMAT_CLASS_INDEX,
+ gcvFORMAT_CLASS_LUMINANCE,
+ gcvFORMAT_CLASS_BUMP,
+ gcvFORMAT_CLASS_DEPTH,
+}
+gceFORMAT_CLASS;
+
+/* Special enums for width field in gcsFORMAT_COMPONENT. */
+typedef enum _gceCOMPONENT_CONTROL
+{
+ gcvCOMPONENT_NOTPRESENT = 0x00,
+ gcvCOMPONENT_DONTCARE = 0x80,
+ gcvCOMPONENT_WIDTHMASK = 0x7F,
+ gcvCOMPONENT_ODD = 0x80
+}
+gceCOMPONENT_CONTROL;
+
+/* Color format component parameters. */
+typedef struct _gcsFORMAT_COMPONENT
+{
+ gctUINT8 start;
+ gctUINT8 width;
+}
+gcsFORMAT_COMPONENT;
+
+/* RGBA color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_RGBA
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT red;
+ gcsFORMAT_COMPONENT green;
+ gcsFORMAT_COMPONENT blue;
+}
+gcsFORMAT_CLASS_TYPE_RGBA;
+
+/* YUV color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_YUV
+{
+ gcsFORMAT_COMPONENT y;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT v;
+}
+gcsFORMAT_CLASS_TYPE_YUV;
+
+/* Index color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_INDEX
+{
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_INDEX;
+
+/* Luminance color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_LUMINANCE
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_LUMINANCE;
+
+/* Bump map color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_BUMP
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT l;
+ gcsFORMAT_COMPONENT v;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT q;
+ gcsFORMAT_COMPONENT w;
+}
+gcsFORMAT_CLASS_TYPE_BUMP;
+
+/* Depth and stencil format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
+{
+ gcsFORMAT_COMPONENT depth;
+ gcsFORMAT_COMPONENT stencil;
+}
+gcsFORMAT_CLASS_TYPE_DEPTH;
+
+/* Format parameters. */
+typedef struct _gcsSURF_FORMAT_INFO
+{
+ /* Format code and class. */
+ gceSURF_FORMAT format;
+ gceFORMAT_CLASS fmtClass;
+
+ /* The size of one pixel in bits. */
+ gctUINT8 bitsPerPixel;
+
+ /* Component swizzle. */
+ gceSURF_SWIZZLE swizzle;
+
+ /* Some formats have two neighbour pixels interleaved together. */
+ /* To describe such format, set the flag to 1 and add another */
+ /* like this one describing the odd pixel format. */
+ gctUINT8 interleaved;
+
+ /* Format components. */
+ union
+ {
+ gcsFORMAT_CLASS_TYPE_BUMP bump;
+ gcsFORMAT_CLASS_TYPE_RGBA rgba;
+ gcsFORMAT_CLASS_TYPE_YUV yuv;
+ gcsFORMAT_CLASS_TYPE_LUMINANCE lum;
+ gcsFORMAT_CLASS_TYPE_INDEX index;
+ gcsFORMAT_CLASS_TYPE_DEPTH depth;
+ } u;
+}
+gcsSURF_FORMAT_INFO;
+
+/* Frame buffer information. */
+typedef struct _gcsSURF_FRAMEBUFFER
+{
+ gctPOINTER logical;
+ gctUINT width, height;
+ gctINT stride;
+ gceSURF_FORMAT format;
+}
+gcsSURF_FRAMEBUFFER;
+
+/* Generic pixel component descriptors. */
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_X8XX;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_8XXX;
+
+typedef enum _gceORIENTATION
+{
+ gcvORIENTATION_TOP_BOTTOM,
+ gcvORIENTATION_BOTTOM_TOP,
+}
+gceORIENTATION;
+
+
+/* Construct a new gcoSURF object. */
+gceSTATUS
+gcoSURF_Construct(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+/* Destroy an gcoSURF object. */
+gceSTATUS
+gcoSURF_Destroy(
+ IN gcoSURF Surface
+ );
+
+/* Map user-allocated surface. */
+gceSTATUS
+gcoSURF_MapUserSurface(
+ IN gcoSURF Surface,
+ IN gctUINT Alignment,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* Set the color type of the surface. */
+gceSTATUS
+gcoSURF_SetColorType(
+ IN gcoSURF Surface,
+ IN gceSURF_COLOR_TYPE ColorType
+ );
+
+/* Get the color type of the surface. */
+gceSTATUS
+gcoSURF_GetColorType(
+ IN gcoSURF Surface,
+ OUT gceSURF_COLOR_TYPE *ColorType
+ );
+
+/* Set the surface ration angle. */
+gceSTATUS
+gcoSURF_SetRotation(
+ IN gcoSURF Surface,
+ IN gceSURF_ROTATION Rotation
+ );
+
+/* Verify and return the state of the tile status mechanism. */
+gceSTATUS
+gcoSURF_IsTileStatusSupported(
+ IN gcoSURF Surface
+ );
+
+/* Enable tile status for the specified surface. */
+gceSTATUS
+gcoSURF_EnableTileStatus(
+ IN gcoSURF Surface
+ );
+
+/* Disable tile status for the specified surface. */
+gceSTATUS
+gcoSURF_DisableTileStatus(
+ IN gcoSURF Surface,
+ IN gctBOOL Decompress
+ );
+
+/* Get surface size. */
+gceSTATUS
+gcoSURF_GetSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctUINT * Depth
+ );
+
+/* Get surface aligned sizes. */
+gceSTATUS
+gcoSURF_GetAlignedSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctINT * Stride
+ );
+
+/* Get surface type and format. */
+gceSTATUS
+gcoSURF_GetFormat(
+ IN gcoSURF Surface,
+ OUT gceSURF_TYPE * Type,
+ OUT gceSURF_FORMAT * Format
+ );
+
+/* Lock the surface. */
+gceSTATUS
+gcoSURF_Lock(
+ IN gcoSURF Surface,
+ IN OUT gctUINT32 * Address,
+ IN OUT gctPOINTER * Memory
+ );
+
+/* Unlock the surface. */
+gceSTATUS
+gcoSURF_Unlock(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory
+ );
+
+/* Return pixel format parameters. */
+gceSTATUS
+gcoSURF_QueryFormat(
+ IN gceSURF_FORMAT Format,
+ OUT gcsSURF_FORMAT_INFO_PTR * Info
+ );
+
+/* Compute the color pixel mask. */
+gceSTATUS
+gcoSURF_ComputeColorMask(
+ IN gcsSURF_FORMAT_INFO_PTR Format,
+ OUT gctUINT32_PTR ColorMask
+ );
+
+/* Check the surface is renderable or not. */
+gceSTATUS
+gcoSURF_IsRenderable(
+ IN gcoSURF Surface
+ );
+
+/* Flush the surface. */
+gceSTATUS
+gcoSURF_Flush(
+ IN gcoSURF Surface
+ );
+
+/* Fill surface with a value. */
+gceSTATUS
+gcoSURF_Fill(
+ IN gcoSURF Surface,
+ IN gcsPOINT_PTR Origin,
+ IN gcsSIZE_PTR Size,
+ IN gctUINT32 Value,
+ IN gctUINT32 Mask
+ );
+
+/* Alpha blend two surfaces together. */
+gceSTATUS
+gcoSURF_Blend(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsPOINT_PTR SrcOrig,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsSIZE_PTR Size,
+ IN gceSURF_BLEND_MODE Mode
+ );
+
+/* Create a new gcoSURF wrapper object. */
+gceSTATUS
+gcoSURF_ConstructWrapper(
+ IN gcoHAL Hal,
+ OUT gcoSURF * Surface
+ );
+
+/* Set the underlying buffer for the surface wrapper. */
+gceSTATUS
+gcoSURF_SetBuffer(
+ IN gcoSURF Surface,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Stride,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* Set the size of the surface in pixels and map the underlying buffer. */
+gceSTATUS
+gcoSURF_SetWindow(
+ IN gcoSURF Surface,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height
+ );
+
+/* Increase reference count of the surface. */
+gceSTATUS
+gcoSURF_ReferenceSurface(
+ IN gcoSURF Surface
+ );
+
+/* Decrease reference count of the surface. */
+gceSTATUS
+gcoSURF_DereferenceSurface(
+ 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
+ );
+
+/* Set surface resolve offset */
+gceSTATUS
+gcoSURF_SetFace(
+ IN gcoSURF Surface,
+ IN gctUINT Face
+ );
+
+/* Query surface orientation. */
+gceSTATUS
+gcoSURF_QueryOrientation(
+ IN gcoSURF Surface,
+ OUT gceORIENTATION * Orientation
+ );
+ /* #define DUMP_SURFACE 0 */
+
+/* Dump a buffer to a BMP file */
+int gcoOS_DumpBMP(
+ IN gctPOINTER dumpBase,
+ IN gctINT dumpWidth,
+ IN gctINT dumpHeight,
+ IN gctINT dumpStride,
+ IN gceSURF_FORMAT format,
+ IN gceORIENTATION orientation,
+ IN gctCONST_STRING fileName
+ );
+
+
+/* Dump surface to a BMP file. */
+gceSTATUS
+gcoSURF_DumpSurface(
+ IN gcoSURF Surface,
+ IN gctBOOL bCheckOrientation,
+ IN gctCONST_STRING fileName
+ );
+
+/******************************************************************************\
+********************************* gcoDUMP Object ********************************
+\******************************************************************************/
+
+/* Construct a new gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Construct(
+ IN gcoOS Os,
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+/* Destroy a gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Destroy(
+ IN gcoDUMP Dump
+ );
+
+/* Enable/disable dumping. */
+gceSTATUS
+gcoDUMP_Control(
+ IN gcoDUMP Dump,
+ IN gctSTRING FileName
+ );
+
+gceSTATUS
+gcoDUMP_IsEnabled(
+ IN gcoDUMP Dump,
+ OUT gctBOOL * Enabled
+ );
+
+/* Add surface. */
+gceSTATUS
+gcoDUMP_AddSurface(
+ IN gcoDUMP Dump,
+ IN gctINT32 Width,
+ IN gctINT32 Height,
+ IN gceSURF_FORMAT PixelFormat,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount
+ );
+
+/* Mark the beginning of a frame. */
+gceSTATUS
+gcoDUMP_FrameBegin(
+ IN gcoDUMP Dump
+ );
+
+/* Mark the end of a frame. */
+gceSTATUS
+gcoDUMP_FrameEnd(
+ IN gcoDUMP Dump
+ );
+
+/* Dump data. */
+gceSTATUS
+gcoDUMP_DumpData(
+ IN gcoDUMP Dump,
+ IN gceDUMP_TAG Type,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Delete an address. */
+gceSTATUS
+gcoDUMP_Delete(
+ IN gcoDUMP Dump,
+ IN gctUINT32 Address
+ );
+
+/******************************************************************************\
+******************************* gcsRECT Structure ******************************
+\******************************************************************************/
+
+/* Initialize rectangle structure. */
+gceSTATUS
+gcsRECT_Set(
+ OUT gcsRECT_PTR Rect,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Return the width of the rectangle. */
+gceSTATUS
+gcsRECT_Width(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Width
+ );
+
+/* Return the height of the rectangle. */
+gceSTATUS
+gcsRECT_Height(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Height
+ );
+
+/* Ensure that top left corner is to the left and above the right bottom. */
+gceSTATUS
+gcsRECT_Normalize(
+ IN OUT gcsRECT_PTR Rect
+ );
+
+/* Compare two rectangles. */
+gceSTATUS
+gcsRECT_IsEqual(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * Equal
+ );
+
+/* Compare the sizes of two rectangles. */
+gceSTATUS
+gcsRECT_IsOfEqualSize(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * EqualSize
+ );
+
+
+/******************************************************************************\
+**************************** gcsBOUNDARY Structure *****************************
+\******************************************************************************/
+
+typedef struct _gcsBOUNDARY
+{
+ gctINT x;
+ gctINT y;
+ gctINT width;
+ gctINT height;
+}
+gcsBOUNDARY;
+
+/******************************************************************************\
+********************************* gcoHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gcoHEAP * gcoHEAP;
+
+/* Construct a new gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Construct(
+ IN gcoOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gcoHEAP * Heap
+ );
+
+/* Destroy an gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Destroy(
+ IN gcoHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoHEAP_Allocate(
+ IN gcoHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoHEAP_Free(
+ IN gcoHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+/* Profile the heap. */
+gceSTATUS
+gcoHEAP_ProfileStart(
+ IN gcoHEAP Heap
+ );
+
+gceSTATUS
+gcoHEAP_ProfileEnd(
+ IN gcoHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gcoHEAP_Test(
+ IN gcoHEAP Heap,
+ IN gctSIZE_T Vectors,
+ IN gctSIZE_T MaxSize
+ );
+#endif
+
+/******************************************************************************\
+******************************* Debugging Macros *******************************
+\******************************************************************************/
+
+void
+gcoOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gcoOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gcoOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+/*******************************************************************************
+**
+** gcmFATAL
+**
+** Print a message to the debugger and execute a break point.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcdDEBUG
+# define gcmFATAL gcoOS_DebugFatal
+# define gcmkFATAL gckOS_DebugFatal
+#elif gcdHAS_ELLIPSES
+# define gcmFATAL(...)
+# define gcmkFATAL(...)
+#else
+ gcmINLINE static void
+ __dummy_fatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmFATAL __dummy_fatal
+# define gcmkFATAL __dummy_fatal
+#endif
+
+#define gcmENUM2TEXT(e) case e: return #e
+
+/*******************************************************************************
+**
+** gcmTRACE
+**
+** Print a message to the debugfer if the correct level has been set. In
+** retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** level Level of message.
+** message Message.
+** ... Optional arguments.
+*/
+#define gcvLEVEL_NONE -1
+#define gcvLEVEL_ERROR 0
+#define gcvLEVEL_WARNING 1
+#define gcvLEVEL_INFO 2
+#define gcvLEVEL_VERBOSE 3
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+void
+
+gcoOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcdDEBUG
+# define gcmTRACE gcoOS_DebugTrace
+# define gcmkTRACE gckOS_DebugTrace
+#elif gcdHAS_ELLIPSES
+# define gcmTRACE(...)
+# define gcmkTRACE(...)
+#else
+ gcmINLINE static void
+ __dummy_trace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmTRACE __dummy_trace
+# define gcmkTRACE __dummy_trace
+#endif
+
+/* Debug zones. */
+#define gcvZONE_OS (1 << 0)
+#define gcvZONE_HARDWARE (1 << 1)
+#define gcvZONE_HEAP (1 << 2)
+
+/* Kernel zones. */
+#define gcvZONE_KERNEL (1 << 3)
+#define gcvZONE_VIDMEM (1 << 4)
+#define gcvZONE_COMMAND (1 << 5)
+#define gcvZONE_DRIVER (1 << 6)
+#define gcvZONE_CMODEL (1 << 7)
+#define gcvZONE_MMU (1 << 8)
+#define gcvZONE_EVENT (1 << 9)
+#define gcvZONE_DEVICE (1 << 10)
+
+/* User zones. */
+#define gcvZONE_HAL (1 << 3)
+#define gcvZONE_BUFFER (1 << 4)
+#define gcvZONE_CONTEXT (1 << 5)
+#define gcvZONE_SURFACE (1 << 6)
+#define gcvZONE_INDEX (1 << 7)
+#define gcvZONE_STREAM (1 << 8)
+#define gcvZONE_TEXTURE (1 << 9)
+#define gcvZONE_2D (1 << 10)
+#define gcvZONE_3D (1 << 11)
+#define gcvZONE_COMPILER (1 << 12)
+#define gcvZONE_MEMORY (1 << 13)
+#define gcvZONE_STATE (1 << 14)
+#define gcvZONE_AUX (1 << 15)
+
+/* API definitions. */
+#define gcvZONE_API_HAL (0 << 28)
+#define gcvZONE_API_EGL (1 << 28)
+#define gcvZONE_API_ES11 (2 << 28)
+#define gcvZONE_API_ES20 (3 << 28)
+#define gcvZONE_API_VG11 (4 << 28)
+#define gcvZONE_API_GL (5 << 28)
+#define gcvZONE_API_DFB (6 << 28)
+#define gcvZONE_API_GDI (7 << 28)
+#define gcvZONE_API_D3D (8 << 28)
+
+#define gcmZONE_GET_API(zone) ((zone) >> 28)
+#define gcdZONE_MASK 0x0FFFFFFF
+
+/* Handy zones. */
+#define gcvZONE_NONE 0
+#define gcvZONE_ALL gcdZONE_MASK
+
+/*******************************************************************************
+**
+** gcmTRACE_ZONE
+**
+** Print a message to the debugger if the correct level and zone has been
+** set. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** Level Level of message.
+** Zone Zone of message.
+** Message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcdDEBUG
+# define gcmTRACE_ZONE gcoOS_DebugTraceZone
+# define gcmkTRACE_ZONE gckOS_DebugTraceZone
+#elif gcdHAS_ELLIPSES
+# define gcmTRACE_ZONE(...)
+# define gcmkTRACE_ZONE(...)
+#else
+ gcmINLINE static void
+ __dummy_trace_zone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmTRACE_ZONE __dummy_trace_zone
+# define gcmkTRACE_ZONE __dummy_trace_zone
+#endif
+
+/******************************************************************************\
+******************************** Logging Macros ********************************
+\******************************************************************************/
+
+#define gcdHEADER_LEVEL gcvLEVEL_VERBOSE
+
+#define gcmHEADER() \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmHEADER_ARG(Text, ...) \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_header_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmHEADER_ARG __dummy_header_arg
+#endif
+
+#define gcmFOOTER() \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): status=%d", \
+ __FUNCTION__, __LINE__, status)
+
+#define gcmFOOTER_NO() \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmFOOTER_ARG(Text, ...) \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): " Text, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_footer_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmFOOTER_ARG __dummy_footer_arg
+#endif
+
+#define gcmkHEADER() \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmkHEADER_ARG(Text, ...) \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_kheader_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkHEADER_ARG __dummy_kheader_arg
+#endif
+
+#define gcmkFOOTER() \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): status=%d", \
+ __FUNCTION__, __LINE__, status)
+
+#define gcmkFOOTER_NO() \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmkFOOTER_ARG(Text, ...) \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): " Text, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_kfooter_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkFOOTER_ARG __dummy_kfooter_arg
+#endif
+
+#define gcmOPT_VALUE(ptr) (((ptr) == gcvNULL) ? 0 : *(ptr))
+#define gcmOPT_POINTER(ptr) (((ptr) == gcvNULL) ? gcvNULL : *(ptr))
+
+void
+gcoOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+#define gcmPRINT gcoOS_Print
+#define gcmkPRINT gckOS_Print
+
+/*******************************************************************************
+**
+** gcmDUMP
+**
+** Print a dump message.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+#if gcdDUMP
+ gceSTATUS
+ gcfDump(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ ...
+ );
+# define gcmDUMP gcfDump
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP(...)
+#else
+ gcmINLINE static void
+ __dummy_dump(
+ IN gcoOS Os,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP __dummy_dump
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_DATA
+**
+** Add data to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP
+ gceSTATUS
+ gcfDumpData(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_DATA gcfDumpData
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_DATA(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_data(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_DATA __dummy_dump_data
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_BUFFER
+**
+** Print a buffer to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctUINT32 Physical
+** Physical address of buffer.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctUINT32 Offset
+** Offset into buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP
+gceSTATUS
+gcfDumpBuffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_BUFFER gcfDumpBuffer
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_BUFFER(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_buffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_BUFFER __dummy_dump_buffer
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API
+**
+** Print a dump message for a high level API prefixed by the function name.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+#if gcdDUMP_API
+ gceSTATUS
+ gcfDumpApi(
+ IN gctCONST_STRING String,
+ ...
+ );
+# define gcmDUMP_API gcfDumpApi
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_API(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP_API __dummy_dump_api
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY
+**
+** Print an array of data.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Size.
+*/
+#if gcdDUMP_API
+ gceSTATUS
+ gcfDumpArray(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Size
+ );
+# define gcmDUMP_API_ARRAY gcfDumpArray
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_API_ARRAY(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Size
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY __dummy_dump_api_array
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY_TOKEN
+**
+** Print an array of data terminated by a token.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Termination.
+*/
+#if gcdDUMP_API
+ gceSTATUS
+ gcfDumpArrayToken(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Termination
+ );
+# define gcmDUMP_API_ARRAY_TOKEN gcfDumpArrayToken
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_API_ARRAY_TOKEN(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array_token(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Termination
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY_TOKEN __dummy_dump_api_array_token
+#endif
+
+/*******************************************************************************
+**
+** gcmTRACE_RELEASE
+**
+** Print a message to the shader debugger.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+#define gcmTRACE_RELEASE gcoOS_DebugShaderTrace
+
+void
+gcoOS_DebugShaderTrace(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_SetDebugShaderFiles(
+ IN gctCONST_STRING VSFileName,
+ IN gctCONST_STRING FSFileName
+ );
+
+void
+gcoOS_SetDebugShaderFileType(
+ IN gctUINT32 ShaderType
+ );
+
+/*******************************************************************************
+**
+** gcmBREAK
+**
+** Break into the debugger. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** None.
+*/
+
+void
+gcoOS_DebugBreak(
+ void
+ );
+
+void
+gckOS_DebugBreak(
+ void
+ );
+
+#if gcdDEBUG
+# define gcmBREAK gcoOS_DebugBreak
+# define gcmkBREAK gckOS_DebugBreak
+#else
+# define gcmBREAK()
+# define gcmkBREAK()
+#endif
+
+/*******************************************************************************
+**
+** gcmASSERT
+**
+** Evaluate an expression and break into the debugger if the expression
+** evaluates to false. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcdDEBUG
+# define _gcmASSERT(prefix, exp) \
+ do \
+ { \
+ if (!(exp)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ASSERT at %s(%d) in " __FILE__, \
+ __FUNCTION__, __LINE__); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ "(%s)", #exp); \
+ prefix##BREAK(); \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmASSERT(exp) _gcmASSERT(gcm, exp)
+# define gcmkASSERT(exp) _gcmASSERT(gcmk, exp)
+#else
+# define gcmASSERT(exp)
+# define gcmkASSERT(exp)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY
+**
+** Verify if an expression returns true. If the expression does not
+** evaluates to true, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcdDEBUG
+# define gcmVERIFY(exp) gcmASSERT(exp)
+# define gcmkVERIFY(exp) gcmkASSERT(exp)
+#else
+# define gcmVERIFY(exp) exp
+# define gcmkVERIFY(exp) exp
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_OK
+**
+** Verify a fucntion returns gcvSTATUS_OK. If the function does not return
+** gcvSTATUS_OK, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+
+void
+gcoOS_Verify(
+ IN gceSTATUS Status
+ );
+
+void
+gckOS_Verify(
+ IN gceSTATUS Status
+ );
+
+#if gcdDEBUG
+# define gcmVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ gcoOS_Verify(verifyStatus); \
+ gcmASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+# define gcmkVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ gckOS_Verify(verifyStatus); \
+ gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+#else
+# define gcmVERIFY_OK(func) func
+
+# define gcmkVERIFY_OK(func) func
+#endif
+
+/*******************************************************************************
+**
+** gcmERR_BREAK
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_BREAK(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_BREAK: status=%d @ %s(%d) in " __FILE__, \
+ status, __FUNCTION__, __LINE__); \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_BREAK(func) _gcmERR_BREAK(gcm, func)
+#define gcmkERR_BREAK(func) _gcmERR_BREAK(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmERR_RETURN
+**
+** Executes a return on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d @ %s(%d) in " __FILE__, \
+ status, __FUNCTION__, __LINE__); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_RETURN(func) _gcmERR_RETURN(gcm, func)
+#define gcmkERR_RETURN(func) _gcmERR_RETURN(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmONERROR
+**
+** Jump to the error handler in case there is an error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmONERROR(prefix, func) \
+ do \
+ { \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##LOG(_GFX_LOG_ERROR_, \
+ "[GC_" #prefix "ONERROR\t] %s(%d): status=%d", \
+ __FUNCTION__, __LINE__, status); \
+ goto OnError; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmONERROR(func) _gcmONERROR(gcm, func)
+#define gcmkONERROR(func) _gcmONERROR(gcmk, func)
+
+
+/*******************************************************************************
+**
+** gcmVERIFY_LOCK
+**
+** Verifies whether the surface is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_LOCK(surfaceInfo) \
+ if (!surfaceInfo->node.valid) \
+ { \
+ status = gcvSTATUS_MEMORY_UNLOCKED; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmVERIFY_NODE_LOCK
+**
+** Verifies whether the surface node is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_NODE_LOCK(surfaceNode) \
+ if (!surfaceNode->valid) \
+ { \
+ status = gcvSTATUS_MEMORY_UNLOCKED; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmBADOBJECT_BREAK
+**
+** Executes a break statement on bad object.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#define gcmBADOBJECT_BREAK(obj, t) \
+ if ((obj == gcvNULL) \
+ || (((gcsOBJECT *)(obj))->type != t) \
+ ) \
+ { \
+ status = gcvSTATUS_INVALID_OBJECT; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmCHECK_STATUS
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmCHECK_STATUS(prefix, func) \
+ do \
+ { \
+ last = func; \
+ if (gcmIS_ERROR(last)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "CHECK_STATUS: status=%d @ %s(%d) in " __FILE__, \
+ last, __FUNCTION__, __LINE__); \
+ status = last; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmCHECK_STATUS(func) _gcmCHECK_STATUS(gcm, func)
+#define gcmkCHECK_STATUS(func) _gcmCHECK_STATUS(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_ARGUMENT(prefix, arg) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, #prefix "VERIFY_ARGUMENT failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT); \
+ return gcvSTATUS_INVALID_ARGUMENT; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
+# define gcmkVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcmk, arg)
+#else
+# define gcmVERIFY_ARGUMENT(arg)
+# define gcmkVERIFY_ARGUMENT(arg)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT_RETURN
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_ARGUMENT_RETURN(prefix, arg, value) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "gcmVERIFY_ARGUMENT_RETURN failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("value=%d", value); \
+ return value; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcm, arg, value)
+# define gcmkVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcmk, arg, value)
+#else
+# define gcmVERIFY_ARGUMENT_RETURN(arg, value)
+# define gcmkVERIFY_ARGUMENT_RETURN(arg, value)
+#endif
+void gcoOS_Log(IN unsigned int filter, IN const char* msg,
+ ...
+ );
+
+void gckOS_Log(IN unsigned int filter, IN const char* msg,
+ ...
+ );
+
+void gcoOS_SetLogFilter(IN unsigned int filter);
+
+void gckOS_SetLogFilter(IN unsigned int filter);
+
+#define gcmLOG gcoOS_Log
+#define gcmkLOG gckOS_Log
+
+#define _gcmLOG_STATUS(prefix, tag, filter) \
+ do \
+ { \
+ prefix##LOG(filter, \
+ "[GC_" #tag "\t] %s@%d: status=%d\n", \
+ __FUNCTION__, __LINE__, status); \
+ } \
+ while (gcvFALSE)
+
+#define gcmLOG_WARNING_STATUS() _gcmLOG_STATUS(gcm, WARNING, _GFX_LOG_WARNING_)
+#define gcmLOG_ERROR_STATUS() _gcmLOG_STATUS(gcm, ERR_RETURN, _GFX_LOG_ERROR_)
+
+#define gcmkLOG_WARNING_STATUS() _gcmLOG_STATUS(gcmk, WARNING, _GFX_LOG_WARNING_)
+#define gcmkLOG_ERROR_STATUS() _gcmLOG_STATUS(gcmk, ERR_RETURN, _GFX_LOG_ERROR_)
+
+#if gcdHAS_ELLIPSES
+#define _gcmLOG_ARGS(prefix, tag, filter, TEXT, ...) \
+ do \
+ { \
+ prefix##LOG(filter, \
+ "[GC_" #tag "\t] %s@%d: " TEXT "\n", \
+ __FUNCTION__, __LINE__, ##__VA_ARGS__); \
+ } \
+ while (gcvFALSE)
+
+#define gcmLOG_WARNING_ARGS(TEXT, ...) _gcmLOG_ARGS(gcm, WARNING, _GFX_LOG_WARNING_, TEXT, ##__VA_ARGS__)
+#define gcmLOG_ERROR_ARGS(TEXT, ...) _gcmLOG_ARGS(gcm, ERR_RETURN, _GFX_LOG_ERROR_, TEXT, ##__VA_ARGS__)
+
+#define gcmkLOG_WARNING_ARGS(TEXT, ...) _gcmLOG_ARGS(gcmk, WARNING, _GFX_LOG_WARNING_, TEXT, ##__VA_ARGS__)
+#define gcmkLOG_ERROR_ARGS(TEXT, ...) _gcmLOG_ARGS(gcmk, ERR_RETURN, _GFX_LOG_ERROR_, TEXT, ##__VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_log_args(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+#define gcmLOG_WARNING_ARGS __dummy_log_args
+#define gcmLOG_ERROR_ARGS __dummy_log_args
+#define gcmkLOG_WARNING_ARGS __dummy_log_args
+#define gcmkLOG_ERROR_ARGS __dummy_log_args
+#endif
+
+ /* Logging service */
+#define _GFX_LOG_NONE_ 0x00000000
+#define _GFX_LOG_ERROR_ 0x00000001
+#define _GFX_LOG_WARNING_ 0x00000002
+#define _GFX_LOG_EGL_API_ 0x00000004
+#define _GFX_LOG_NATIVE_API_ 0x00000008
+#define _GFX_LOG_OES_API_ 0x00000010
+#define _GFX_LOG_VG_API_ 0x00000020
+#define _GFX_LOG_CONFIG_ 0x00000040
+#define _GFX_LOG_INFO_ 0x00000080
+#define _GFX_LOG_NOTIFY_ 0x00000100
+#define _GFX_LOG_ALL_ 0xffffffff
+
+
+#if MRVL_ENABLE_EGL_API_LOG
+#define EGL_API_LOG(x) gcoOS_Log x
+#else
+#define EGL_API_LOG(x)
+#endif
+#define EGL_LOG(x) gcoOS_Log x
+
+
+#if MRVL_ENABLE_OES1_API_LOG
+#define OES11_API_LOG(x) gcoOS_Log x
+#else
+#define OES11_API_LOG(x)
+#endif
+#define OES11_LOG(x) gcoOS_Log x
+
+#if MRVL_ENABLE_OES2_API_LOG
+#define OES20_API_LOG(x) gcoOS_Log x
+#else
+#define OES20_API_LOG(x)
+#endif
+#define OES20_LOG(x) gcoOS_Log x
+
+#if MRVL_ENABLE_OVG_API_LOG
+#define OVG_API_LOG(x) gcoOS_Log x
+#else
+#define OVG_API_LOG(x)
+#endif
+#define OVG_LOG(x) gcoOS_Log x
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_base_h_ */
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_compiler.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_compiler.h
new file mode 100644
index 0000000..6bc96b2
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_compiler.h
@@ -0,0 +1,1841 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/*
+** Include file the defines the front- and back-end compilers, as well as the
+** objects they use.
+*/
+
+#ifndef __gc_hal_compiler_h_
+#define __gc_hal_compiler_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_engine.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+|******************************* SHADER LANGUAGE ******************************|
+\******************************************************************************/
+
+/* Possible shader language opcodes. */
+typedef enum _gcSL_OPCODE
+{
+ gcSL_NOP, /* 0x00 */
+ gcSL_MOV, /* 0x01 */
+ gcSL_SAT, /* 0x02 */
+ gcSL_DP3, /* 0x03 */
+ gcSL_DP4, /* 0x04 */
+ gcSL_ABS, /* 0x05 */
+ gcSL_JMP, /* 0x06 */
+ gcSL_ADD, /* 0x07 */
+ gcSL_MUL, /* 0x08 */
+ gcSL_RCP, /* 0x09 */
+ gcSL_SUB, /* 0x0A */
+ gcSL_KILL, /* 0x0B */
+ gcSL_TEXLD, /* 0x0C */
+ gcSL_CALL, /* 0x0D */
+ gcSL_RET, /* 0x0E */
+ gcSL_NORM, /* 0x0F */
+ gcSL_MAX, /* 0x10 */
+ gcSL_MIN, /* 0x11 */
+ gcSL_POW, /* 0x12 */
+ gcSL_RSQ, /* 0x13 */
+ gcSL_LOG, /* 0x14 */
+ gcSL_FRAC, /* 0x15 */
+ gcSL_FLOOR, /* 0x16 */
+ gcSL_CEIL, /* 0x17 */
+ gcSL_CROSS, /* 0x18 */
+ gcSL_TEXLDP, /* 0x19 */
+ gcSL_TEXBIAS, /* 0x1A */
+ gcSL_TEXGRAD, /* 0x1B */
+ gcSL_TEXLOD, /* 0x1C */
+ gcSL_SIN, /* 0x1D */
+ gcSL_COS, /* 0x1E */
+ gcSL_TAN, /* 0x1F */
+ gcSL_EXP, /* 0x20 */
+ gcSL_SIGN, /* 0x21 */
+ gcSL_STEP, /* 0x22 */
+ gcSL_SQRT, /* 0x23 */
+ gcSL_ACOS, /* 0x24 */
+ gcSL_ASIN, /* 0x25 */
+ gcSL_ATAN, /* 0x26 */
+ gcSL_SET, /* 0x27 */
+ gcSL_DSX, /* 0x28 */
+ gcSL_DSY, /* 0x29 */
+ gcSL_FWIDTH, /* 0x2A */
+}
+gcSL_OPCODE;
+
+typedef enum _gcSL_FORMAT
+{
+ gcSL_FLOAT, /* 0 */
+ gcSL_INTEGER, /* 1 */
+ gcSL_BOOLEAN, /* 2 */
+}
+gcSL_FORMAT;
+
+/* Destination write enable bits. */
+typedef enum _gcSL_ENABLE
+{
+ gcSL_ENABLE_X = 0x1,
+ gcSL_ENABLE_Y = 0x2,
+ gcSL_ENABLE_Z = 0x4,
+ gcSL_ENABLE_W = 0x8,
+ /* Combinations. */
+ gcSL_ENABLE_XY = gcSL_ENABLE_X | gcSL_ENABLE_Y,
+ gcSL_ENABLE_XYZ = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z,
+ gcSL_ENABLE_XYZW = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
+ gcSL_ENABLE_XYW = gcSL_ENABLE_X | gcSL_ENABLE_Y | gcSL_ENABLE_W,
+ gcSL_ENABLE_XZ = gcSL_ENABLE_X | gcSL_ENABLE_Z,
+ gcSL_ENABLE_XZW = gcSL_ENABLE_X | gcSL_ENABLE_Z | gcSL_ENABLE_W,
+ gcSL_ENABLE_XW = gcSL_ENABLE_X | gcSL_ENABLE_W,
+ gcSL_ENABLE_YZ = gcSL_ENABLE_Y | gcSL_ENABLE_Z,
+ gcSL_ENABLE_YZW = gcSL_ENABLE_Y | gcSL_ENABLE_Z | gcSL_ENABLE_W,
+ gcSL_ENABLE_YW = gcSL_ENABLE_Y | gcSL_ENABLE_W,
+ gcSL_ENABLE_ZW = gcSL_ENABLE_Z | gcSL_ENABLE_W,
+}
+gcSL_ENABLE;
+
+/* Possible indices. */
+typedef enum _gcSL_INDEXED
+{
+ gcSL_NOT_INDEXED, /* 0 */
+ gcSL_INDEXED_X, /* 1 */
+ gcSL_INDEXED_Y, /* 2 */
+ gcSL_INDEXED_Z, /* 3 */
+ gcSL_INDEXED_W, /* 4 */
+}
+gcSL_INDEXED;
+
+/* Opcode conditions. */
+typedef enum _gcSL_CONDITION
+{
+ gcSL_ALWAYS, /* 0x0 */
+ gcSL_NOT_EQUAL, /* 0x1 */
+ gcSL_LESS_OR_EQUAL, /* 0x2 */
+ gcSL_LESS, /* 0x3 */
+ gcSL_EQUAL, /* 0x4 */
+ gcSL_GREATER, /* 0x5 */
+ gcSL_GREATER_OR_EQUAL, /* 0x6 */
+ gcSL_AND, /* 0x7 */
+ gcSL_OR, /* 0x8 */
+ gcSL_XOR, /* 0x9 */
+}
+gcSL_CONDITION;
+
+/* Possible source operand types. */
+typedef enum _gcSL_TYPE
+{
+ gcSL_NONE, /* 0x0 */
+ gcSL_TEMP, /* 0x1 */
+ gcSL_ATTRIBUTE, /* 0x2 */
+ gcSL_UNIFORM, /* 0x3 */
+ gcSL_SAMPLER, /* 0x4 */
+ gcSL_CONSTANT, /* 0x5 */
+ gcSL_OUTPUT, /* 0x6 */
+ gcSL_PHYSICAL, /* 0x7 */
+}
+gcSL_TYPE;
+
+/* Swizzle generator macro. */
+#define gcmSWIZZLE(Component1, Component2, Component3, Component4) \
+( \
+ (gcSL_SWIZZLE_ ## Component1 << 0) | \
+ (gcSL_SWIZZLE_ ## Component2 << 2) | \
+ (gcSL_SWIZZLE_ ## Component3 << 4) | \
+ (gcSL_SWIZZLE_ ## Component4 << 6) \
+)
+
+/* Possible swizzle values. */
+typedef enum _gcSL_SWIZZLE
+{
+ gcSL_SWIZZLE_X, /* 0x0 */
+ gcSL_SWIZZLE_Y, /* 0x1 */
+ gcSL_SWIZZLE_Z, /* 0x2 */
+ gcSL_SWIZZLE_W, /* 0x3 */
+ /* Combinations. */
+ gcSL_SWIZZLE_XXXX = gcmSWIZZLE(X, X, X, X),
+ gcSL_SWIZZLE_YYYY = gcmSWIZZLE(Y, Y, Y, Y),
+ gcSL_SWIZZLE_ZZZZ = gcmSWIZZLE(Z, Z, Z, Z),
+ gcSL_SWIZZLE_WWWW = gcmSWIZZLE(W, W, W, W),
+ gcSL_SWIZZLE_XYYY = gcmSWIZZLE(X, Y, Y, Y),
+ gcSL_SWIZZLE_XZZZ = gcmSWIZZLE(X, Z, Z, Z),
+ gcSL_SWIZZLE_XWWW = gcmSWIZZLE(X, W, W, W),
+ gcSL_SWIZZLE_YZZZ = gcmSWIZZLE(Y, Z, Z, Z),
+ gcSL_SWIZZLE_YWWW = gcmSWIZZLE(Y, W, W, W),
+ gcSL_SWIZZLE_ZWWW = gcmSWIZZLE(Z, W, W, W),
+ gcSL_SWIZZLE_XYZZ = gcmSWIZZLE(X, Y, Z, Z),
+ gcSL_SWIZZLE_XYWW = gcmSWIZZLE(X, Y, W, W),
+ gcSL_SWIZZLE_XZWW = gcmSWIZZLE(X, Z, W, W),
+ gcSL_SWIZZLE_YZWW = gcmSWIZZLE(Y, Z, W, W),
+ gcSL_SWIZZLE_XXYZ = gcmSWIZZLE(X, X, Y, Z),
+ gcSL_SWIZZLE_XYZW = gcmSWIZZLE(X, Y, Z, W),
+ gcSL_SWIZZLE_XYXY = gcmSWIZZLE(X, Y, X, Y),
+}
+gcSL_SWIZZLE;
+
+
+/******************************************************************************\
+|*********************************** SHADERS **********************************|
+\******************************************************************************/
+
+/* Shader types. */
+#define gcSHADER_TYPE_UNKNOWN 0
+#define gcSHADER_TYPE_VERTEX 1
+#define gcSHADER_TYPE_FRAGMENT 2
+
+/* gcSHADER objects. */
+typedef struct _gcSHADER * gcSHADER;
+typedef struct _gcATTRIBUTE * gcATTRIBUTE;
+typedef struct _gcUNIFORM * gcUNIFORM;
+typedef struct _gcOUTPUT * gcOUTPUT;
+typedef struct _gcsFUNCTION * gcFUNCTION;
+typedef struct _gcsHINT * gcsHINT_PTR;
+typedef struct _gcSHADER_PROFILER * gcSHADER_PROFILER;
+typedef struct _gcVARIABLE * gcVARIABLE;
+
+/* gcSHADER_TYPE enumeration. */
+typedef enum _gcSHADER_TYPE
+{
+ gcSHADER_FLOAT_X1, /* 0x00 */
+ gcSHADER_FLOAT_X2, /* 0x01 */
+ gcSHADER_FLOAT_X3, /* 0x02 */
+ gcSHADER_FLOAT_X4, /* 0x03 */
+ gcSHADER_FLOAT_2X2, /* 0x04 */
+ gcSHADER_FLOAT_3X3, /* 0x05 */
+ gcSHADER_FLOAT_4X4, /* 0x06 */
+ gcSHADER_BOOLEAN_X1, /* 0x07 */
+ gcSHADER_BOOLEAN_X2, /* 0x08 */
+ gcSHADER_BOOLEAN_X3, /* 0x09 */
+ gcSHADER_BOOLEAN_X4, /* 0x0A */
+ gcSHADER_INTEGER_X1, /* 0x0B */
+ gcSHADER_INTEGER_X2, /* 0x0C */
+ gcSHADER_INTEGER_X3, /* 0x0D */
+ gcSHADER_INTEGER_X4, /* 0x0E */
+ gcSHADER_SAMPLER_1D, /* 0x0F */
+ gcSHADER_SAMPLER_2D, /* 0x10 */
+ gcSHADER_SAMPLER_3D, /* 0x11 */
+ gcSHADER_SAMPLER_CUBIC, /* 0x12 */
+ gcSHADER_FIXED_X1, /* 0x13 */
+ gcSHADER_FIXED_X2, /* 0x14 */
+ gcSHADER_FIXED_X3, /* 0x15 */
+ gcSHADER_FIXED_X4, /* 0x16 */
+}
+gcSHADER_TYPE;
+
+/* Shader flags. */
+typedef enum _gceSHADER_FLAGS
+{
+ gcvSHADER_DEAD_CODE = 0x01,
+ gcvSHADER_RESOURCE_USAGE = 0x02,
+ gcvSHADER_OPTIMIZER = 0x04,
+ gcvSHADER_USE_GL_Z = 0x08,
+ gcvSHADER_USE_GL_POSITION = 0x10,
+ gcvSHADER_USE_GL_FACE = 0x20,
+ gcvSHADER_USE_GL_POINT_COORD = 0x40,
+}
+gceSHADER_FLAGS;
+
+/* Function argument qualifier */
+typedef enum _gceINPUT_OUTPUT
+{
+ gcvFUNCTION_INPUT,
+ gcvFUNCTION_OUTPUT,
+ gcvFUNCTION_INOUT
+}
+gceINPUT_OUTPUT;
+
+/*******************************************************************************
+** gcSHADER_Construct
+********************************************************************************
+**
+** Construct a new gcSHADER object.
+**
+** INPUT:
+**
+** gcoOS Hal
+** Pointer to an gcoHAL object.
+**
+** gctINT ShaderType
+** Type of gcSHADER object to cerate. 'ShaderType' can be one of the
+** following:
+**
+** gcSHADER_TYPE_VERTEX Vertex shader.
+** gcSHADER_TYPE_FRAGMENT Fragment shader.
+**
+** OUTPUT:
+**
+** gcSHADER * Shader
+** Pointer to a variable receiving the gcSHADER object pointer.
+*/
+gceSTATUS
+gcSHADER_Construct(
+ IN gcoHAL Hal,
+ IN gctINT ShaderType,
+ OUT gcSHADER * Shader
+ );
+
+/*******************************************************************************
+** gcSHADER_Destroy
+********************************************************************************
+**
+** Destroy a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_Destroy(
+ IN gcSHADER Shader
+ );
+
+/*******************************************************************************
+** gcSHADER_Load
+********************************************************************************
+**
+** Load a gcSHADER object from a binary buffer.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctPOINTER Buffer
+** Pointer to a binary buffer containg the shader data to load.
+**
+** gctSIZE_T BufferSize
+** Number of bytes inside the binary buffer pointed to by 'Buffer'.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_Load(
+ IN gcSHADER Shader,
+ IN gctPOINTER Buffer,
+ IN gctSIZE_T BufferSize
+ );
+
+/*******************************************************************************
+** gcSHADER_Save
+********************************************************************************
+**
+** Save a gcSHADER object to a binary buffer.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctPOINTER Buffer
+** Pointer to a binary buffer to be used as storage for the gcSHADER
+** object. If 'Buffer' is gcvNULL, the gcSHADER object will not be saved,
+** but the number of bytes required to hold the binary output for the
+** gcSHADER object will be returned.
+**
+** gctSIZE_T * BufferSize
+** Pointer to a variable holding the number of bytes allocated in
+** 'Buffer'. Only valid if 'Buffer' is not gcvNULL.
+**
+** OUTPUT:
+**
+** gctSIZE_T * BufferSize
+** Pointer to a variable receiving the number of bytes required to hold
+** the binary form of the gcSHADER object.
+*/
+gceSTATUS
+gcSHADER_Save(
+ IN gcSHADER Shader,
+ IN gctPOINTER Buffer,
+ IN OUT gctSIZE_T * BufferSize
+ );
+
+/*******************************************************************************
+** gcSHADER_AddAttribute
+********************************************************************************
+**
+** Add an attribute to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctCONST_STRING Name
+** Name of the attribute to add.
+**
+** gcSHADER_TYPE Type
+** Type of the attribute to add.
+**
+** gctSIZE_T Length
+** Array length of the attribute to add. 'Length' must be at least 1.
+**
+** gctBOOL IsTexture
+** gcvTRUE if the attribute is used as a texture coordinate, gcvFALSE if not.
+**
+** OUTPUT:
+**
+** gcATTRIBUTE * Attribute
+** Pointer to a variable receiving the gcATTRIBUTE object pointer.
+*/
+gceSTATUS
+gcSHADER_AddAttribute(
+ IN gcSHADER Shader,
+ IN gctCONST_STRING Name,
+ IN gcSHADER_TYPE Type,
+ IN gctSIZE_T Length,
+ IN gctBOOL IsTexture,
+ OUT gcATTRIBUTE * Attribute
+ );
+
+/*******************************************************************************
+** gcSHADER_GetAttributeCount
+********************************************************************************
+**
+** Get the number of attributes for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Count
+** Pointer to a variable receiving the number of attributes.
+*/
+gceSTATUS
+gcSHADER_GetAttributeCount(
+ IN gcSHADER Shader,
+ OUT gctSIZE_T * Count
+ );
+
+/*******************************************************************************
+** gcSHADER_GetAttribute
+********************************************************************************
+**
+** Get the gcATTRIBUTE object poniter for an indexed attribute for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctUINT Index
+** Index of the attribute to retrieve.
+**
+** OUTPUT:
+**
+** gcATTRIBUTE * Attribute
+** Pointer to a variable receiving the gcATTRIBUTE object pointer.
+*/
+gceSTATUS
+gcSHADER_GetAttribute(
+ IN gcSHADER Shader,
+ IN gctUINT Index,
+ OUT gcATTRIBUTE * Attribute
+ );
+
+/*******************************************************************************
+** gcSHADER_GetPositionAttribute
+********************************************************************************
+**
+** Get the gcATTRIBUTE object pointer for the attribute that defines the
+** position.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** OUTPUT:
+**
+** gctUINT * Index
+** Pointer to a variable receiving the index of te gcATTRIBUTE object
+** used as a position.
+**
+** gcATTRIBUTE * Attribute
+** Pointer to a variable receiving the gcATTRIBUTE object pointer.
+*/
+gceSTATUS
+gcSHADER_GetPositionAttribute(
+ IN gcSHADER Shader,
+ OUT gctUINT * Index,
+ OUT gcATTRIBUTE * Attribute
+ );
+
+/*******************************************************************************
+** gcSHADER_AddUniform
+********************************************************************************
+**
+** Add an uniform to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctCONST_STRING Name
+** Name of the uniform to add.
+**
+** gcSHADER_TYPE Type
+** Type of the uniform to add.
+**
+** gctSIZE_T Length
+** Array length of the uniform to add. 'Length' must be at least 1.
+**
+** OUTPUT:
+**
+** gcUNIFORM * Uniform
+** Pointer to a variable receiving the gcUNIFORM object pointer.
+*/
+gceSTATUS
+gcSHADER_AddUniform(
+ IN gcSHADER Shader,
+ IN gctCONST_STRING Name,
+ IN gcSHADER_TYPE Type,
+ IN gctSIZE_T Length,
+ OUT gcUNIFORM * Uniform
+ );
+
+/*******************************************************************************
+** gcSHADER_GetUniformCount
+********************************************************************************
+**
+** Get the number of uniforms for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Count
+** Pointer to a variable receiving the number of uniforms.
+*/
+gceSTATUS
+gcSHADER_GetUniformCount(
+ IN gcSHADER Shader,
+ OUT gctSIZE_T * Count
+ );
+
+/*******************************************************************************
+** gcSHADER_GetUniform
+********************************************************************************
+**
+** Get the gcUNIFORM object pointer for an indexed uniform for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctUINT Index
+** Index of the uniform to retrieve.
+**
+** OUTPUT:
+**
+** gcUNIFORM * Uniform
+** Pointer to a variable receiving the gcUNIFORM object pointer.
+*/
+gceSTATUS
+gcSHADER_GetUniform(
+ IN gcSHADER Shader,
+ IN gctUINT Index,
+ OUT gcUNIFORM * Uniform
+ );
+
+/*******************************************************************************
+** gcSHADER_AddOutput
+********************************************************************************
+**
+** Add an output to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctCONST_STRING Name
+** Name of the output to add.
+**
+** gcSHADER_TYPE Type
+** Type of the output to add.
+**
+** gctSIZE_T Length
+** Array length of the output to add. 'Length' must be at least 1.
+**
+** gctUINT16 TempRegister
+** Temporary register index that holds the output value.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOutput(
+ IN gcSHADER Shader,
+ IN gctCONST_STRING Name,
+ IN gcSHADER_TYPE Type,
+ IN gctSIZE_T Length,
+ IN gctUINT16 TempRegister
+ );
+
+gceSTATUS
+gcSHADER_AddOutputIndexed(
+ IN gcSHADER Shader,
+ IN gctCONST_STRING Name,
+ IN gctSIZE_T Index,
+ IN gctUINT16 TempIndex
+ );
+
+/*******************************************************************************
+** gcSHADER_GetOutputCount
+********************************************************************************
+**
+** Get the number of outputs for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Count
+** Pointer to a variable receiving the number of outputs.
+*/
+gceSTATUS
+gcSHADER_GetOutputCount(
+ IN gcSHADER Shader,
+ OUT gctSIZE_T * Count
+ );
+
+/*******************************************************************************
+** gcSHADER_GetOutput
+********************************************************************************
+**
+** Get the gcOUTPUT object pointer for an indexed output for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctUINT Index
+** Index of output to retrieve.
+**
+** OUTPUT:
+**
+** gcOUTPUT * Output
+** Pointer to a variable receiving the gcOUTPUT object pointer.
+*/
+gceSTATUS
+gcSHADER_GetOutput(
+ IN gcSHADER Shader,
+ IN gctUINT Index,
+ OUT gcOUTPUT * Output
+ );
+
+/*******************************************************************************
+** gcSHADER_AddVariable
+********************************************************************************
+**
+** Add a variable to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctCONST_STRING Name
+** Name of the variable to add.
+**
+** gcSHADER_TYPE Type
+** Type of the variable to add.
+**
+** gctSIZE_T Length
+** Array length of the variable to add. 'Length' must be at least 1.
+**
+** gctUINT16 TempRegister
+** Temporary register index that holds the variable value.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddVariable(
+ IN gcSHADER Shader,
+ IN gctCONST_STRING Name,
+ IN gcSHADER_TYPE Type,
+ IN gctSIZE_T Length,
+ IN gctUINT16 TempRegister
+ );
+
+/*******************************************************************************
+** gcSHADER_GetVariableCount
+********************************************************************************
+**
+** Get the number of variables for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Count
+** Pointer to a variable receiving the number of variables.
+*/
+gceSTATUS
+gcSHADER_GetVariableCount(
+ IN gcSHADER Shader,
+ OUT gctSIZE_T * Count
+ );
+
+/*******************************************************************************
+** gcSHADER_GetVariable
+********************************************************************************
+**
+** Get the gcVARIABLE object pointer for an indexed variable for this shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctUINT Index
+** Index of variable to retrieve.
+**
+** OUTPUT:
+**
+** gcVARIABLE * Variable
+** Pointer to a variable receiving the gcVARIABLE object pointer.
+*/
+gceSTATUS
+gcSHADER_GetVariable(
+ IN gcSHADER Shader,
+ IN gctUINT Index,
+ OUT gcVARIABLE * Variable
+ );
+
+/*******************************************************************************
+** gcSHADER_AddOpcode
+********************************************************************************
+**
+** Add an opcode to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcSL_OPCODE Opcode
+** Opcode to add.
+**
+** gctUINT16 TempRegister
+** Temporary register index that acts as the target of the opcode.
+**
+** gctUINT8 Enable
+** Write enable bits for the temporary register that acts as the target
+** of the opcode.
+**
+** gcSL_FORMAT Format
+** Format of the temporary register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcode(
+ IN gcSHADER Shader,
+ IN gcSL_OPCODE Opcode,
+ IN gctUINT16 TempRegister,
+ IN gctUINT8 Enable,
+ IN gcSL_FORMAT Format
+ );
+
+gceSTATUS
+gcSHADER_AddOpcode2(
+ IN gcSHADER Shader,
+ IN gcSL_OPCODE Opcode,
+ IN gcSL_CONDITION Condition,
+ IN gctUINT16 TempRegister,
+ IN gctUINT8 Enable,
+ IN gcSL_FORMAT Format
+ );
+
+/*******************************************************************************
+** gcSHADER_AddOpcodeIndexed
+********************************************************************************
+**
+** Add an opcode to a gcSHADER object that writes to an dynamically indexed
+** target.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcSL_OPCODE Opcode
+** Opcode to add.
+**
+** gctUINT16 TempRegister
+** Temporary register index that acts as the target of the opcode.
+**
+** gctUINT8 Enable
+** Write enable bits for the temporary register that acts as the
+** target of the opcode.
+**
+** gcSL_INDEXED Mode
+** Location of the dynamic index inside the temporary register. Valid
+** values can be:
+**
+** gcSL_INDEXED_X - Use x component of the temporary register.
+** gcSL_INDEXED_Y - Use y component of the temporary register.
+** gcSL_INDEXED_Z - Use z component of the temporary register.
+** gcSL_INDEXED_W - Use w component of the temporary register.
+**
+** gctUINT16 IndexRegister
+** Temporary register index that holds the dynamic index.
+**
+** gcSL_FORMAT Format
+** Format of the temporary register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcodeIndexed(
+ IN gcSHADER Shader,
+ IN gcSL_OPCODE Opcode,
+ IN gctUINT16 TempRegister,
+ IN gctUINT8 Enable,
+ IN gcSL_INDEXED Mode,
+ IN gctUINT16 IndexRegister,
+ IN gcSL_FORMAT Format
+ );
+
+/*******************************************************************************
+** gcSHADER_AddOpcodeConditional
+********************************************************************************
+**
+** Add an conditional opcode to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcSL_OPCODE Opcode
+** Opcode to add.
+**
+** gcSL_CONDITION Condition
+** Condition that needs to evaluate to gcvTRUE in order for the opcode to
+** execute.
+**
+** gctUINT Label
+** Target label if 'Condition' evaluates to gcvTRUE.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddOpcodeConditional(
+ IN gcSHADER Shader,
+ IN gcSL_OPCODE Opcode,
+ IN gcSL_CONDITION Condition,
+ IN gctUINT Label
+ );
+
+/*******************************************************************************
+** gcSHADER_AddLabel
+********************************************************************************
+**
+** Define a label at the current instruction of a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctUINT Label
+** Label to define.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddLabel(
+ IN gcSHADER Shader,
+ IN gctUINT Label
+ );
+
+/*******************************************************************************
+** gcSHADER_AddSource
+********************************************************************************
+**
+** Add a source operand to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcSL_TYPE Type
+** Type of the source operand.
+**
+** gctUINT16 SourceIndex
+** Index of the source operand.
+**
+** gctUINT8 Swizzle
+** x, y, z, and w swizzle values packed into one 8-bit value.
+**
+** gcSL_FORMAT Format
+** Format of the source operand.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSource(
+ IN gcSHADER Shader,
+ IN gcSL_TYPE Type,
+ IN gctUINT16 SourceIndex,
+ IN gctUINT8 Swizzle,
+ IN gcSL_FORMAT Format
+ );
+
+/*******************************************************************************
+** gcSHADER_AddSourceIndexed
+********************************************************************************
+**
+** Add a dynamically indexed source operand to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcSL_TYPE Type
+** Type of the source operand.
+**
+** gctUINT16 SourceIndex
+** Index of the source operand.
+**
+** gctUINT8 Swizzle
+** x, y, z, and w swizzle values packed into one 8-bit value.
+**
+** gcSL_INDEXED Mode
+** Addressing mode for the index.
+**
+** gctUINT16 IndexRegister
+** Temporary register index that holds the dynamic index.
+**
+** gcSL_FORMAT Format
+** Format of the source operand.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceIndexed(
+ IN gcSHADER Shader,
+ IN gcSL_TYPE Type,
+ IN gctUINT16 SourceIndex,
+ IN gctUINT8 Swizzle,
+ IN gcSL_INDEXED Mode,
+ IN gctUINT16 IndexRegister,
+ IN gcSL_FORMAT Format
+ );
+
+/*******************************************************************************
+** gcSHADER_AddSourceAttribute
+********************************************************************************
+**
+** Add an attribute as a source operand to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcATTRIBUTE Attribute
+** Pointer to a gcATTRIBUTE object.
+**
+** gctUINT8 Swizzle
+** x, y, z, and w swizzle values packed into one 8-bit value.
+**
+** gctINT Index
+** Static index into the attribute in case the attribute is a matrix
+** or array.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceAttribute(
+ IN gcSHADER Shader,
+ IN gcATTRIBUTE Attribute,
+ IN gctUINT8 Swizzle,
+ IN gctINT Index
+ );
+
+/*******************************************************************************
+** gcSHADER_AddSourceAttributeIndexed
+********************************************************************************
+**
+** Add an indexed attribute as a source operand to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcATTRIBUTE Attribute
+** Pointer to a gcATTRIBUTE object.
+**
+** gctUINT8 Swizzle
+** x, y, z, and w swizzle values packed into one 8-bit value.
+**
+** gctINT Index
+** Static index into the attribute in case the attribute is a matrix
+** or array.
+**
+** gcSL_INDEXED Mode
+** Addressing mode of the dynamic index.
+**
+** gctUINT16 IndexRegister
+** Temporary register index that holds the dynamic index.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceAttributeIndexed(
+ IN gcSHADER Shader,
+ IN gcATTRIBUTE Attribute,
+ IN gctUINT8 Swizzle,
+ IN gctINT Index,
+ IN gcSL_INDEXED Mode,
+ IN gctUINT16 IndexRegister
+ );
+
+/*******************************************************************************
+** gcSHADER_AddSourceUniform
+********************************************************************************
+**
+** Add a uniform as a source operand to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** gctUINT8 Swizzle
+** x, y, z, and w swizzle values packed into one 8-bit value.
+**
+** gctINT Index
+** Static index into the uniform in case the uniform is a matrix or
+** array.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceUniform(
+ IN gcSHADER Shader,
+ IN gcUNIFORM Uniform,
+ IN gctUINT8 Swizzle,
+ IN gctINT Index
+ );
+
+/*******************************************************************************
+** gcSHADER_AddSourceUniformIndexed
+********************************************************************************
+**
+** Add an indexed uniform as a source operand to a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** gctUINT8 Swizzle
+** x, y, z, and w swizzle values packed into one 8-bit value.
+**
+** gctINT Index
+** Static index into the uniform in case the uniform is a matrix or
+** array.
+**
+** gcSL_INDEXED Mode
+** Addressing mode of the dynamic index.
+**
+** gctUINT16 IndexRegister
+** Temporary register index that holds the dynamic index.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceUniformIndexed(
+ IN gcSHADER Shader,
+ IN gcUNIFORM Uniform,
+ IN gctUINT8 Swizzle,
+ IN gctINT Index,
+ IN gcSL_INDEXED Mode,
+ IN gctUINT16 IndexRegister
+ );
+
+gceSTATUS
+gcSHADER_AddSourceSamplerIndexed(
+ IN gcSHADER Shader,
+ IN gctUINT8 Swizzle,
+ IN gcSL_INDEXED Mode,
+ IN gctUINT16 IndexRegister
+ );
+
+/*******************************************************************************
+** gcSHADER_AddSourceConstant
+********************************************************************************
+**
+** Add a constant floating pointer value as a source operand to a gcSHADER
+** object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctFLOAT Constant
+** Floating pointer constant.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_AddSourceConstant(
+ IN gcSHADER Shader,
+ IN gctFLOAT Constant
+ );
+
+/*******************************************************************************
+** gcSHADER_Pack
+********************************************************************************
+**
+** Pack a dynamically created gcSHADER object by trimming the allocated arrays
+** and resolving all the labeling.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_Pack(
+ IN gcSHADER Shader
+ );
+
+/*******************************************************************************
+** gcSHADER_SetOptimizationOption
+********************************************************************************
+**
+** Set optimization option of a gcSHADER object.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object.
+**
+** gctUINT OptimizationOption
+** Optimization option. Can be one of the following:
+**
+** 0 - No optimization.
+** 1 - Full optimization.
+** Other value - For optimizer testing.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcSHADER_SetOptimizationOption(
+ IN gcSHADER Shader,
+ IN gctUINT OptimizationOption
+ );
+
+gceSTATUS
+gcSHADER_AddFunction(
+ IN gcSHADER Shader,
+ IN gctCONST_STRING Name,
+ OUT gcFUNCTION * Function
+ );
+
+gceSTATUS
+gcSHADER_BeginFunction(
+ IN gcSHADER Shader,
+ IN gcFUNCTION Function
+ );
+
+gceSTATUS
+gcSHADER_EndFunction(
+ IN gcSHADER Shader,
+ IN gcFUNCTION Function
+ );
+
+/*******************************************************************************
+** gcATTRIBUTE_GetType
+********************************************************************************
+**
+** Get the type and array length of a gcATTRIBUTE object.
+**
+** INPUT:
+**
+** gcATTRIBUTE Attribute
+** Pointer to a gcATTRIBUTE object.
+**
+** OUTPUT:
+**
+** gcSHADER_TYPE * Type
+** Pointer to a variable receiving the type of the attribute. 'Type'
+** can be gcvNULL, in which case no type will be returned.
+**
+** gctSIZE_T * ArrayLength
+** Pointer to a variable receiving the length of the array if the
+** attribute was declared as an array. If the attribute was not
+** declared as an array, the array length will be 1. 'ArrayLength' can
+** be gcvNULL, in which case no array length will be returned.
+*/
+gceSTATUS
+gcATTRIBUTE_GetType(
+ IN gcATTRIBUTE Attribute,
+ OUT gcSHADER_TYPE * Type,
+ OUT gctSIZE_T * ArrayLength
+ );
+
+/*******************************************************************************
+** gcATTRIBUTE_GetName
+********************************************************************************
+**
+** Get the name of a gcATTRIBUTE object.
+**
+** INPUT:
+**
+** gcATTRIBUTE Attribute
+** Pointer to a gcATTRIBUTE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Length
+** Pointer to a variable receiving the length of the attribute name.
+** 'Length' can be gcvNULL, in which case no length will be returned.
+**
+** gctCONST_STRING * Name
+** Pointer to a variable receiving the pointer to the attribute name.
+** 'Name' can be gcvNULL, in which case no name will be returned.
+*/
+gceSTATUS
+gcATTRIBUTE_GetName(
+ IN gcATTRIBUTE Attribute,
+ OUT gctSIZE_T * Length,
+ OUT gctCONST_STRING * Name
+ );
+
+/*******************************************************************************
+** gcATTRIBUTE_IsEnabled
+********************************************************************************
+**
+** Query the enabled state of a gcATTRIBUTE object.
+**
+** INPUT:
+**
+** gcATTRIBUTE Attribute
+** Pointer to a gcATTRIBUTE object.
+**
+** OUTPUT:
+**
+** gctBOOL * Enabled
+** Pointer to a variable receiving the enabled state of the attribute.
+*/
+gceSTATUS
+gcATTRIBUTE_IsEnabled(
+ IN gcATTRIBUTE Attribute,
+ OUT gctBOOL * Enabled
+ );
+
+/*******************************************************************************
+** gcUNIFORM_GetType
+********************************************************************************
+**
+** Get the type and array length of a gcUNIFORM object.
+**
+** INPUT:
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** OUTPUT:
+**
+** gcSHADER_TYPE * Type
+** Pointer to a variable receiving the type of the uniform. 'Type' can
+** be gcvNULL, in which case no type will be returned.
+**
+** gctSIZE_T * ArrayLength
+** Pointer to a variable receiving the length of the array if the
+** uniform was declared as an array. If the uniform was not declared
+** as an array, the array length will be 1. 'ArrayLength' can be gcvNULL,
+** in which case no array length will be returned.
+*/
+gceSTATUS
+gcUNIFORM_GetType(
+ IN gcUNIFORM Uniform,
+ OUT gcSHADER_TYPE * Type,
+ OUT gctSIZE_T * ArrayLength
+ );
+
+/*******************************************************************************
+** gcUNIFORM_GetName
+********************************************************************************
+**
+** Get the name of a gcUNIFORM object.
+**
+** INPUT:
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Length
+** Pointer to a variable receiving the length of the uniform name.
+** 'Length' can be gcvNULL, in which case no length will be returned.
+**
+** gctCONST_STRING * Name
+** Pointer to a variable receiving the pointer to the uniform name.
+** 'Name' can be gcvNULL, in which case no name will be returned.
+*/
+gceSTATUS
+gcUNIFORM_GetName(
+ IN gcUNIFORM Uniform,
+ OUT gctSIZE_T * Length,
+ OUT gctCONST_STRING * Name
+ );
+
+/*******************************************************************************
+** gcUNIFORM_GetSampler
+********************************************************************************
+**
+** Get the physical sampler number for a sampler gcUNIFORM object.
+**
+** INPUT:
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** OUTPUT:
+**
+** gctUINT32 * Sampler
+** Pointer to a variable receiving the physical sampler.
+*/
+gceSTATUS
+gcUNIFORM_GetSampler(
+ IN gcUNIFORM Uniform,
+ OUT gctUINT32 * Sampler
+ );
+
+/*******************************************************************************
+** gcUNIFORM_SetValue
+********************************************************************************
+**
+** Set the value of a uniform in integer.
+**
+** INPUT:
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** gctSIZE_T Count
+** Number of entries to program if the uniform has been declared as an
+** array.
+**
+** const gctINT * Value
+** Pointer to a buffer holding the integer values for the uniform.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcUNIFORM_SetValue(
+ IN gcUNIFORM Uniform,
+ IN gctSIZE_T Count,
+ IN const gctINT * Value
+ );
+
+/*******************************************************************************
+** gcUNIFORM_SetValueX
+********************************************************************************
+**
+** Set the value of a uniform in fixed point.
+**
+** INPUT:
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** gctSIZE_T Count
+** Number of entries to program if the uniform has been declared as an
+** array.
+**
+** const gctFIXED_POINT * Value
+** Pointer to a buffer holding the fixed point values for the uniform.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcUNIFORM_SetValueX(
+ IN gcUNIFORM Uniform,
+ IN gctSIZE_T Count,
+ IN gctFIXED_POINT * Value
+ );
+
+/*******************************************************************************
+** gcUNIFORM_SetValueF
+********************************************************************************
+**
+** Set the value of a uniform in floating point.
+**
+** INPUT:
+**
+** gcUNIFORM Uniform
+** Pointer to a gcUNIFORM object.
+**
+** gctSIZE_T Count
+** Number of entries to program if the uniform has been declared as an
+** array.
+**
+** const gctFLOAT * Value
+** Pointer to a buffer holding the floating point values for the
+** uniform.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gcUNIFORM_SetValueF(
+ IN gcUNIFORM Uniform,
+ IN gctSIZE_T Count,
+ IN const gctFLOAT * Value
+ );
+
+/*******************************************************************************
+** gcOUTPUT_GetType
+********************************************************************************
+**
+** Get the type and array length of a gcOUTPUT object.
+**
+** INPUT:
+**
+** gcOUTPUT Output
+** Pointer to a gcOUTPUT object.
+**
+** OUTPUT:
+**
+** gcSHADER_TYPE * Type
+** Pointer to a variable receiving the type of the output. 'Type' can
+** be gcvNULL, in which case no type will be returned.
+**
+** gctSIZE_T * ArrayLength
+** Pointer to a variable receiving the length of the array if the
+** output was declared as an array. If the output was not declared
+** as an array, the array length will be 1. 'ArrayLength' can be gcvNULL,
+** in which case no array length will be returned.
+*/
+gceSTATUS
+gcOUTPUT_GetType(
+ IN gcOUTPUT Output,
+ OUT gcSHADER_TYPE * Type,
+ OUT gctSIZE_T * ArrayLength
+ );
+
+/*******************************************************************************
+** gcOUTPUT_GetIndex
+********************************************************************************
+**
+** Get the index of a gcOUTPUT object.
+**
+** INPUT:
+**
+** gcOUTPUT Output
+** Pointer to a gcOUTPUT object.
+**
+** OUTPUT:
+**
+** gctUINT * Index
+** Pointer to a variable receiving the temporary register index of the
+** output. 'Index' can be gcvNULL,. in which case no index will be
+** returned.
+*/
+gceSTATUS
+gcOUTPUT_GetIndex(
+ IN gcOUTPUT Output,
+ OUT gctUINT * Index
+ );
+
+/*******************************************************************************
+** gcOUTPUT_GetName
+********************************************************************************
+**
+** Get the name of a gcOUTPUT object.
+**
+** INPUT:
+**
+** gcOUTPUT Output
+** Pointer to a gcOUTPUT object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Length
+** Pointer to a variable receiving the length of the output name.
+** 'Length' can be gcvNULL, in which case no length will be returned.
+**
+** gctCONST_STRING * Name
+** Pointer to a variable receiving the pointer to the output name.
+** 'Name' can be gcvNULL, in which case no name will be returned.
+*/
+gceSTATUS
+gcOUTPUT_GetName(
+ IN gcOUTPUT Output,
+ OUT gctSIZE_T * Length,
+ OUT gctCONST_STRING * Name
+ );
+
+/*******************************************************************************
+*********************************************************** F U N C T I O N S **
+*******************************************************************************/
+
+gceSTATUS
+gcFUNCTION_AddArgument(
+ IN gcFUNCTION Function,
+ IN gctUINT16 TempIndex,
+ IN gctUINT8 Enable,
+ IN gctUINT8 Qualifier
+ );
+
+gceSTATUS
+gcFUNCTION_GetArgument(
+ IN gcFUNCTION Function,
+ IN gctUINT16 Index,
+ OUT gctUINT16_PTR Temp,
+ OUT gctUINT8_PTR Enable,
+ OUT gctUINT8_PTR Swizzle
+ );
+
+gceSTATUS
+gcFUNCTION_GetLabel(
+ IN gcFUNCTION Function,
+ OUT gctUINT_PTR Label
+ );
+
+/*******************************************************************************
+** gcCompileShader
+********************************************************************************
+**
+** Compile a shader.
+**
+** INPUT:
+**
+** gcoOS Hal
+** Pointer to an gcoHAL object.
+**
+** gctINT ShaderType
+** Shader type to compile. Can be one of the following values:
+**
+** gcSHADER_TYPE_VERTEX
+** Compile a vertex shader.
+**
+** gcSHADER_TYPE_FRAGMENT
+** Compile a fragment shader.
+**
+** gctSIZE_T SourceSize
+** Size of the source buffer in bytes.
+**
+** gctCONST_STRING Source
+** Pointer to the buffer containing the shader source code.
+**
+** OUTPUT:
+**
+** gcSHADER * Binary
+** Pointer to a variable receiving the pointer to a gcSHADER object
+** containg the compiled shader code.
+**
+** gctSTRING * Log
+** Pointer to a variable receiving a string pointer containging the
+** compile log.
+*/
+gceSTATUS
+gcCompileShader(
+ IN gcoHAL Hal,
+ IN gctINT ShaderType,
+ IN gctSIZE_T SourceSize,
+ IN gctCONST_STRING Source,
+ OUT gcSHADER * Binary,
+ OUT gctSTRING * Log
+ );
+
+/*******************************************************************************
+** gcOptimizeShader
+********************************************************************************
+**
+** Optimize a shader.
+**
+** INPUT:
+**
+** gcSHADER Shader
+** Pointer to a gcSHADER object holding information about the compiled
+** shader.
+**
+** gctFILE LogFile
+** Pointer to an open FILE object.
+*/
+gceSTATUS
+gcOptimizeShader(
+ IN gcSHADER Shader,
+ IN gctFILE LogFile
+ );
+
+/*******************************************************************************
+** gcLinkShaders
+********************************************************************************
+**
+** Link two shaders and generate a harwdare specific state buffer by compiling
+** the compiler generated code through the resource allocator and code
+** generator.
+**
+** INPUT:
+**
+** gcSHADER VertexShader
+** Pointer to a gcSHADER object holding information about the compiled
+** vertex shader.
+**
+** gcSHADER FragmentShader
+** Pointer to a gcSHADER object holding information about the compiled
+** fragment shader.
+**
+** gceSHADER_FLAGS Flags
+** Compiler flags. Can be any of the following:
+**
+** gcvSHADER_DEAD_CODE - Dead code elimination.
+** gcvSHADER_RESOURCE_USAGE - Resource usage optimizaion.
+** gcvSHADER_OPTIMIZER - Full optimization.
+** gcvSHADER_USE_GL_Z - Use OpenGL ES Z coordinate.
+** gcvSHADER_USE_GL_POSITION - Use OpenGL ES gl_Position.
+** gcvSHADER_USE_GL_FACE - Use OpenGL ES gl_FaceForward.
+**
+** OUTPUT:
+**
+** gctSIZE_T * StateBufferSize
+** Pointer to a variable receicing the number of bytes in the buffer
+** returned in 'StateBuffer'.
+**
+** gctPOINTER * StateBuffer
+** Pointer to a variable receiving a buffer pointer that contains the
+** states required to download the shaders into the hardware.
+**
+** gcsHINT_PTR * Hints
+** Pointer to a variable receiving a gcsHINT structure pointer that
+** contains information required when loading the shader states.
+*/
+gceSTATUS
+gcLinkShaders(
+ IN gcSHADER VertexShader,
+ IN gcSHADER FragmentShader,
+ IN gceSHADER_FLAGS Flags,
+ OUT gctSIZE_T * StateBufferSize,
+ OUT gctPOINTER * StateBuffer,
+ OUT gcsHINT_PTR * Hints
+ );
+
+/*******************************************************************************
+** gcLoadShaders
+********************************************************************************
+**
+** Load a pre-compiled and pre-linked shader program into the hardware.
+**
+** INPUT:
+**
+** gcoHAL Hal
+** Pointer to a gcoHAL object.
+**
+** gctSIZE_T StateBufferSize
+** The number of bytes in the 'StateBuffer'.
+**
+** gctPOINTER StateBuffer
+** Pointer to the states that make up the shader program.
+**
+** gcsHINT_PTR Hints
+** Pointer to a gcsHINT structure that contains information required
+** when loading the shader states.
+**
+** gcePRIMITIVE PrimitiveType
+** Primitive type to be rendered.
+*/
+gceSTATUS
+gcLoadShaders(
+ IN gcoHAL Hal,
+ IN gctSIZE_T StateBufferSize,
+ IN gctPOINTER StateBuffer,
+ IN gcsHINT_PTR Hints,
+ IN gcePRIMITIVE PrimitiveType
+ );
+
+/*******************************************************************************
+** gcSaveProgram
+********************************************************************************
+**
+** Save pre-compiled shaders and pre-linked programs to a binary file.
+**
+** INPUT:
+**
+** gcSHADER VertexShader
+** Pointer to vertex shader object.
+**
+** gcSHADER FragmentShader
+** Pointer to fragment shader object.
+**
+** gctSIZE_T ProgramBufferSize
+** Number of bytes in 'ProgramBuffer'.
+**
+** gctPOINTER ProgramBuffer
+** Pointer to buffer containing the program states.
+**
+** gcsHINT_PTR Hints
+** Pointer to HINTS structure for program states.
+**
+** OUTPUT:
+**
+** gctPOINTER * Binary
+** Pointer to a variable receiving the binary data to be saved.
+**
+** gctSIZE_T * BinarySize
+** Pointer to a variable receiving the number of bytes inside 'Binary'.
+*/
+gceSTATUS
+gcSaveProgram(
+ IN gcSHADER VertexShader,
+ IN gcSHADER FragmentShader,
+ IN gctSIZE_T ProgramBufferSize,
+ IN gctPOINTER ProgramBuffer,
+ IN gcsHINT_PTR Hints,
+ OUT gctPOINTER * Binary,
+ OUT gctSIZE_T * BinarySize
+ );
+
+/*******************************************************************************
+** gcLoadProgram
+********************************************************************************
+**
+** Load pre-compiled shaders and pre-linked programs from a binary file.
+**
+** INPUT:
+**
+** gctPOINTER Binary
+** Pointer to the binary data loaded.
+**
+** gctSIZE_T BinarySize
+** Number of bytes in 'Binary'.
+**
+** OUTPUT:
+**
+** gcSHADER * VertexShader
+** Pointer to a variable receiving the vertex shader object.
+**
+** gcSHADER * FragmentShader
+** Pointer to a variable receiving the fragment shader object.
+**
+** gctSIZE_T * ProgramBufferSize
+** Pointer to a variable receicing the number of bytes in the buffer
+** returned in 'ProgramBuffer'.
+**
+** gctPOINTER * ProgramBuffer
+** Pointer to a variable receiving a buffer pointer that contains the
+** states required to download the shaders into the hardware.
+**
+** gcsHINT_PTR * Hints
+** Pointer to a variable receiving a gcsHINT structure pointer that
+** contains information required when loading the shader states.
+*/
+gceSTATUS
+gcLoadProgram(
+ IN gctPOINTER Binary,
+ IN gctSIZE_T BinarySize,
+ OUT gcSHADER * VertexShader,
+ OUT gcSHADER * FragmentShader,
+ OUT gctSIZE_T * ProgramBufferSize,
+ OUT gctPOINTER * ProgramBuffer,
+ OUT gcsHINT_PTR * Hints
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_compiler_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_driver.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_driver.h
new file mode 100644
index 0000000..bd60d95
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_driver.h
@@ -0,0 +1,640 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_driver_h_
+#define __gc_hal_driver_h_
+
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS "galcore"
+#define IOCTL_GCHAL_INTERFACE 30000
+#define IOCTL_GCHAL_KERNEL_INTERFACE 30001
+#define IOCTL_GCHAL_TERMINATE 30002
+
+/******************************************************************************\
+********************************* Command Codes ********************************
+\******************************************************************************/
+
+typedef enum _gceHAL_COMMAND_CODES
+{
+ /* Generic query. */
+ gcvHAL_QUERY_VIDEO_MEMORY,
+ gcvHAL_QUERY_CHIP_IDENTITY,
+
+ /* Contiguous memory. */
+ gcvHAL_ALLOCATE_NON_PAGED_MEMORY,
+ gcvHAL_FREE_NON_PAGED_MEMORY,
+ gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY,
+ gcvHAL_FREE_CONTIGUOUS_MEMORY,
+
+ /* Video memory allocation. */
+ gcvHAL_ALLOCATE_VIDEO_MEMORY, /* Enforced alignment. */
+ gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY, /* No alignment. */
+ gcvHAL_FREE_VIDEO_MEMORY,
+
+ /* Physical-to-logical mapping. */
+ gcvHAL_MAP_MEMORY,
+ gcvHAL_UNMAP_MEMORY,
+
+ /* Logical-to-physical mapping. */
+ gcvHAL_MAP_USER_MEMORY,
+ gcvHAL_UNMAP_USER_MEMORY,
+
+ /* Surface lock/unlock. */
+ gcvHAL_LOCK_VIDEO_MEMORY,
+ gcvHAL_UNLOCK_VIDEO_MEMORY,
+
+ /* Event queue. */
+ gcvHAL_EVENT_COMMIT,
+
+ gcvHAL_USER_SIGNAL,
+ gcvHAL_SIGNAL,
+ gcvHAL_WRITE_DATA,
+
+ gcvHAL_COMMIT,
+ gcvHAL_STALL,
+
+ gcvHAL_READ_REGISTER,
+ gcvHAL_WRITE_REGISTER,
+
+ gcvHAL_GET_PROFILE_SETTING,
+ gcvHAL_SET_PROFILE_SETTING,
+
+ gcvHAL_READ_ALL_PROFILE_REGISTERS,
+ gcvHAL_PROFILE_REGISTERS_2D,
+
+ /* Power management. */
+ gcvHAL_SET_POWER_MANAGEMENT_STATE,
+ gcvHAL_QUERY_POWER_MANAGEMENT_STATE,
+
+ gcvHAL_GET_BASE_ADDRESS,
+
+ gcvHAL_SET_IDLE, /* reserved */
+
+ /* Queries. */
+ gcvHAL_QUERY_KERNEL_SETTINGS,
+
+ /* Reset. */
+ gcvHAL_RESET,
+
+ /* Map physical address into handle. */
+ gcvHAL_MAP_PHYSICAL,
+
+ /* Debugger stuff. */
+ gcvHAL_DEBUG,
+
+ /* Cache stuff. */
+ gcvHAL_CACHE,
+
+ gcvHAL_GC_OFF,
+ gcvHAL_GC_ON
+}
+gceHAL_COMMAND_CODES;
+
+/******************************************************************************\
+****************************** Interface Structure *****************************
+\******************************************************************************/
+
+#define gcdMAX_PROFILE_FILE_NAME 128
+
+typedef struct _gcsHAL_INTERFACE
+{
+ /* Command code. */
+ gceHAL_COMMAND_CODES command;
+
+ /* Status value. */
+ gceSTATUS status;
+
+ /* Handle to this interface channel. */
+ gctHANDLE handle;
+
+ /* Pid of the client. */
+ gctUINT32 pid;
+
+ /* Union of command structures. */
+ union _u
+ {
+ /* gcvHAL_GET_BASE_ADDRESS */
+ struct _gcsHAL_GET_BASE_ADDRESS
+ {
+ /* Physical memory address of internal memory. */
+ OUT gctUINT32 baseAddress;
+ }
+ GetBaseAddress;
+
+ /* gcvHAL_QUERY_VIDEO_MEMORY */
+ struct _gcsHAL_QUERY_VIDEO_MEMORY
+ {
+ /* Physical memory address of internal memory. */
+ OUT gctPHYS_ADDR internalPhysical;
+
+ /* Size in bytes of internal memory.*/
+ OUT gctSIZE_T internalSize;
+
+ /* Physical memory address of external memory. */
+ OUT gctPHYS_ADDR externalPhysical;
+
+ /* Size in bytes of external memory.*/
+ OUT gctSIZE_T externalSize;
+
+ /* Physical memory address of contiguous memory. */
+ OUT gctPHYS_ADDR contiguousPhysical;
+
+ /* Size in bytes of contiguous memory.*/
+ OUT gctSIZE_T contiguousSize;
+ }
+ QueryVideoMemory;
+
+ /* gcvHAL_QUERY_CHIP_IDENTITY */
+ struct _gcsHAL_QUERY_CHIP_IDENTITY
+ {
+
+ /* Chip model. */
+ OUT gceCHIPMODEL chipModel;
+
+ /* Revision value.*/
+ OUT gctUINT32 chipRevision;
+
+ /* Supported feature fields. */
+ OUT gctUINT32 chipFeatures;
+
+ /* Supported minor feature fields. */
+ OUT gctUINT32 chipMinorFeatures;
+
+ /* Supported minor feature 1 fields. */
+ OUT gctUINT32 chipMinorFeatures1;
+
+ /* Number of streams supported. */
+ OUT gctUINT32 streamCount;
+
+ /* Total number of temporary registers per thread. */
+ OUT gctUINT32 registerMax;
+
+ /* Maximum number of threads. */
+ OUT gctUINT32 threadCount;
+
+ /* Number of shader cores. */
+ OUT gctUINT32 shaderCoreCount;
+
+ /* Size of the vertex cache. */
+ OUT gctUINT32 vertexCacheSize;
+
+ /* Number of entries in the vertex output buffer. */
+ OUT gctUINT32 vertexOutputBufferSize;
+ }
+ QueryChipIdentity;
+
+ /* gcvHAL_MAP_MEMORY */
+ struct _gcsHAL_MAP_MEMORY
+ {
+ /* Physical memory address to map. */
+ IN gctPHYS_ADDR physical;
+
+ /* Number of bytes in physical memory to map. */
+ IN gctSIZE_T bytes;
+
+ /* Address of mapped memory. */
+ OUT gctPOINTER logical;
+ }
+ MapMemory;
+
+ /* gcvHAL_UNMAP_MEMORY */
+ struct _gcsHAL_UNMAP_MEMORY
+ {
+ /* Physical memory address to unmap. */
+ IN gctPHYS_ADDR physical;
+
+ /* Number of bytes in physical memory to unmap. */
+ IN gctSIZE_T bytes;
+
+ /* Address of mapped memory to unmap. */
+ IN gctPOINTER logical;
+ }
+ UnmapMemory;
+
+ /* gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT bytes;
+
+ /* Buffer alignment. */
+ IN gctUINT alignment;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gcuVIDMEM_NODE_PTR node;
+ }
+ AllocateLinearVideoMemory;
+
+ /* gcvHAL_ALLOCATE_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_VIDEO_MEMORY
+ {
+ /* Width of rectangle to allocate. */
+ IN OUT gctUINT width;
+
+ /* Height of rectangle to allocate. */
+ IN OUT gctUINT height;
+
+ /* Depth of rectangle to allocate. */
+ IN gctUINT depth;
+
+ /* Format rectangle to allocate in gceSURF_FORMAT. */
+ IN gceSURF_FORMAT format;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gcuVIDMEM_NODE_PTR node;
+ }
+ AllocateVideoMemory;
+
+ /* gcvHAL_FREE_VIDEO_MEMORY */
+ struct _gcsHAL_FREE_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gcuVIDMEM_NODE_PTR node;
+
+#ifdef __QNXNTO__
+/* TODO: This is part of the unlock - why is it here? */
+ /* Mapped logical address to unmap in user space. */
+ OUT gctPOINTER memory;
+
+ /* Number of bytes to allocated. */
+ OUT gctSIZE_T bytes;
+#endif
+ }
+ FreeVideoMemory;
+
+ /* gcvHAL_LOCK_VIDEO_MEMORY */
+ struct _gcsHAL_LOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gcuVIDMEM_NODE_PTR node;
+
+ /* Hardware specific address. */
+ OUT gctUINT32 address;
+
+ /* Mapped logical address. */
+ OUT gctPOINTER memory;
+ }
+ LockVideoMemory;
+
+ /* gcvHAL_UNLOCK_VIDEO_MEMORY */
+ struct _gcsHAL_UNLOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gcuVIDMEM_NODE_PTR node;
+
+ /* Type of surface. */
+ IN gceSURF_TYPE type;
+
+ /* Flag to unlock surface asynchroneously. */
+ IN OUT gctBOOL asynchroneous;
+ }
+ UnlockVideoMemory;
+
+ /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
+ struct _gcsHAL_ALLOCATE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ OUT gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ OUT gctPOINTER logical;
+ }
+ AllocateNonPagedMemory;
+
+ /* gcvHAL_FREE_NON_PAGED_MEMORY */
+ struct _gcsHAL_FREE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ IN gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ IN gctPOINTER logical;
+ }
+ FreeNonPagedMemory;
+
+ /* gcvHAL_EVENT_COMMIT. */
+ struct _gcsHAL_EVENT_COMMIT
+ {
+ /* Event queue. */
+ IN struct _gcsQUEUE * queue;
+ }
+ Event;
+
+ /* gcvHAL_COMMIT */
+ struct _gcsHAL_COMMIT
+ {
+ /* Command buffer. */
+ IN gcoCMDBUF commandBuffer;
+
+ /* Context buffer. */
+ IN gcoCONTEXT contextBuffer;
+
+ /* Process handle. */
+ IN gctHANDLE process;
+ }
+ Commit;
+
+ /* gcvHAL_MAP_USER_MEMORY */
+ struct _gcsHAL_MAP_USER_MEMORY
+ {
+ /* Base address of user memory to map. */
+ IN gctPOINTER memory;
+
+ /* Size of user memory in bytes to map. */
+ IN gctSIZE_T size;
+
+ /* Info record required by gcvHAL_UNMAP_USER_MEMORY. */
+ OUT gctPOINTER info;
+
+ /* Physical address of mapped memory. */
+ OUT gctUINT32 address;
+ }
+ MapUserMemory;
+
+ /* gcvHAL_UNMAP_USER_MEMORY */
+ struct _gcsHAL_UNMAP_USER_MEMORY
+ {
+ /* Base address of user memory to unmap. */
+ IN gctPOINTER memory;
+
+ /* Size of user memory in bytes to unmap. */
+ IN gctSIZE_T size;
+
+ /* Info record returned by gcvHAL_MAP_USER_MEMORY. */
+ IN gctPOINTER info;
+
+ /* Physical address of mapped memory as returned by
+ gcvHAL_MAP_USER_MEMORY. */
+ IN gctUINT32 address;
+ }
+ UnmapUserMemory;
+
+#if !USE_NEW_LINUX_SIGNAL
+ /* gcsHAL_USER_SIGNAL */
+ struct _gcsHAL_USER_SIGNAL
+ {
+ /* Command. */
+ gceUSER_SIGNAL_COMMAND_CODES command;
+
+ /* Signal ID. */
+ IN OUT gctINT id;
+
+ /* Reset mode. */
+ IN gctBOOL manualReset;
+
+ /* Signal ID. */
+ IN gceSIGNAL_TYPE signalType;
+
+ /* Wait timedout. */
+ IN gctUINT32 wait;
+
+ /* State. */
+ IN gctBOOL state;
+ }
+ UserSignal;
+#endif
+
+ /* gcvHAL_SIGNAL. */
+ struct _gcsHAL_SIGNAL
+ {
+ /* Signal handle to signal. */
+ IN gctSIGNAL signal;
+
+ /* Reserved. */
+ IN gctSIGNAL auxSignal;
+
+ /* Process owning the signal. */
+ IN gctHANDLE process;
+
+#if defined(__QNXNTO__)
+ /* Client pulse side-channel connection ID. Set by client in gcoOS_CreateSignal. */
+ IN gctINT32 coid;
+
+ /* Set by server. */
+ IN gctINT32 rcvid;
+#endif
+ /* Event generated from where of pipeline */
+ IN gceKERNEL_WHERE fromWhere;
+ }
+ Signal;
+
+ /* gcvHAL_WRITE_DATA. */
+ struct _gcsHAL_WRITE_DATA
+ {
+ /* Address to write data to. */
+ IN gctUINT32 address;
+
+ IN gctPOINTER kernelAddress;
+ /* Data to write. */
+ IN gctUINT32 data;
+ }
+ WriteData;
+
+ /* gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_ALLOCATE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ OUT gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ OUT gctPOINTER logical;
+
+ }
+ AllocateContiguousMemory;
+
+ /* gcvHAL_FREE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_FREE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ IN gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ IN gctPOINTER logical;
+ }
+ FreeContiguousMemory;
+
+ /* gcvHAL_READ_REGISTER */
+ struct _gcsHAL_READ_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ OUT gctUINT32 data;
+ }
+ ReadRegisterData;
+
+ /* gcvHAL_WRITE_REGISTER */
+ struct _gcsHAL_WRITE_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ IN gctUINT32 data;
+ }
+ WriteRegisterData;
+
+ /* gcvHAL_GET_PROFILE_SETTING */
+ struct _gcsHAL_GET_PROFILE_SETTING
+ {
+ /* Enable profiling */
+ OUT gctBOOL enable;
+
+ /* The profile file name */
+ OUT gctCHAR fileName[gcdMAX_PROFILE_FILE_NAME];
+ }
+ GetProfileSetting;
+
+ /* gcvHAL_SET_PROFILE_SETTING */
+ struct _gcsHAL_SET_PROFILE_SETTING
+ {
+ /* Enable profiling */
+ IN gctBOOL enable;
+
+ /* The profile file name */
+ IN gctCHAR fileName[gcdMAX_PROFILE_FILE_NAME];
+ }
+ SetProfileSetting;
+
+ /* gcvHAL_READ_ALL_PROFILE_REGISTERS */
+ struct _gcsHAL_READ_ALL_PROFILE_REGISTERS
+ {
+ /* Data read. */
+ OUT gcsPROFILER_COUNTERS counters;
+ }
+ RegisterProfileData;
+
+ /* gcvHAL_PROFILE_REGISTERS_2D */
+ struct _gcsHAL_PROFILE_REGISTERS_2D
+ {
+ /* Data read. */
+ OUT gcs2D_PROFILE_PTR hwProfile2D;
+ }
+ RegisterProfileData2D;
+
+ /* Power management. */
+ /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_SET_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ IN gceCHIPPOWERSTATE state;
+ }
+ SetPowerManagement;
+
+ /* gcvHAL_QUERY_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_QUERY_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ OUT gceCHIPPOWERSTATE state;
+
+ /* Idle query. */
+ OUT gctBOOL isIdle;
+ }
+ QueryPowerManagement;
+
+ /* gcvHAL_QUERY_KERNEL_SETTINGS */
+ struct _gcsHAL_QUERY_KERNEL_SETTINGS
+ {
+ /* Settings.*/
+ OUT gcsKERNEL_SETTINGS settings;
+ }
+ QueryKernelSettings;
+
+ /* gcvHAL_MAP_PHYSICAL */
+ struct _gcsHAL_MAP_PHYSICAL
+ {
+ /* gcvTRUE to map, gcvFALSE to unmap. */
+ IN gctBOOL map;
+
+ /* Physical address. */
+ IN OUT gctPHYS_ADDR physical;
+ }
+ MapPhysical;
+
+ /* gcvHAL_DEBUG */
+ struct _gcsHAL_DEBUG
+ {
+ /* If gcvTRUE, set the debug information. */
+ IN gctBOOL set;
+ IN gctUINT32 level;
+ IN gctUINT32 zones;
+ IN gctBOOL enable;
+
+ /* Message to print if not empty. */
+ IN gctCHAR message[80];
+ }
+ Debug;
+
+ struct _gcsHAL_CACHE
+ {
+ IN gctBOOL invalidate;
+ IN gctHANDLE process;
+ IN gctPOINTER logical;
+ IN gctSIZE_T bytes;
+ }
+ Cache;
+ }
+ u;
+}
+gcsHAL_INTERFACE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_dump.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_dump.h
new file mode 100644
index 0000000..2264b60
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_dump.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_dump_h_
+#define __gc_hal_dump_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** FILE LAYOUT:
+**
+** gcsDUMP_FILE structure
+**
+** gcsDUMP_DATA frame
+** gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
+** gctUINT8 data[length]
+*/
+
+#define gcvDUMP_FILE_SIGNATURE gcmCC('g','c','D','B')
+
+typedef struct _gcsDUMP_FILE
+{
+ gctUINT32 signature; /* File signature */
+ gctSIZE_T length; /* Length of file */
+ gctUINT32 frames; /* Number of frames in file */
+}
+gcsDUMP_FILE;
+
+typedef enum _gceDUMP_TAG
+{
+ gcvTAG_SURFACE = gcmCC('s','u','r','f'),
+ gcvTAG_FRAME = gcmCC('f','r','m',' '),
+ gcvTAG_COMMAND = gcmCC('c','m','d',' '),
+ gcvTAG_INDEX = gcmCC('i','n','d','x'),
+ gcvTAG_STREAM = gcmCC('s','t','r','m'),
+ gcvTAG_TEXTURE = gcmCC('t','e','x','t'),
+ gcvTAG_RENDER_TARGET = gcmCC('r','n','d','r'),
+ gcvTAG_DEPTH = gcmCC('z','b','u','f'),
+ gcvTAG_RESOLVE = gcmCC('r','s','l','v'),
+ gcvTAG_DELETE = gcmCC('d','e','l',' '),
+}
+gceDUMP_TAG;
+
+typedef struct _gcsDUMP_SURFACE
+{
+ gceDUMP_TAG type; /* Type of record. */
+ gctUINT32 address; /* Address of the surface. */
+ gctINT16 width; /* Width of surface. */
+ gctINT16 height; /* Height of surface. */
+ gceSURF_FORMAT format; /* Surface pixel format. */
+ gctSIZE_T length; /* Number of bytes inside the surface. */
+}
+gcsDUMP_SURFACE;
+
+typedef struct _gcsDUMP_DATA
+{
+ gceDUMP_TAG type; /* Type of record. */
+ gctSIZE_T length; /* Number of bytes of data. */
+ gctUINT32 address; /* Address for the data. */
+}
+gcsDUMP_DATA;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_dump_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_engine.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_engine.h
new file mode 100644
index 0000000..3fc88f7
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_engine.h
@@ -0,0 +1,1673 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_engine_h_
+#define __gc_hal_engine_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoSTREAM * gcoSTREAM;
+typedef struct _gcoVERTEX * gcoVERTEX;
+typedef struct _gcoTEXTURE * gcoTEXTURE;
+typedef struct _gcoINDEX * gcoINDEX;
+typedef struct _gcsVERTEX_ATTRIBUTES * gcsVERTEX_ATTRIBUTES_PTR;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+/* Shading format. */
+typedef enum _gceSHADING
+{
+ gcvSHADING_SMOOTH,
+ gcvSHADING_FLAT_D3D,
+ gcvSHADING_FLAT_OPENGL,
+}
+gceSHADING;
+
+/* Culling modes. */
+typedef enum _gceCULL
+{
+ gcvCULL_NONE,
+ gcvCULL_CCW,
+ gcvCULL_CW,
+}
+gceCULL;
+
+/* Fill modes. */
+typedef enum _gceFILL
+{
+ gcvFILL_POINT,
+ gcvFILL_WIRE_FRAME,
+ gcvFILL_SOLID,
+}
+gceFILL;
+
+/* Compare modes. */
+typedef enum _gceCOMPARE
+{
+ gcvCOMPARE_NEVER,
+ gcvCOMPARE_NOT_EQUAL,
+ gcvCOMPARE_LESS,
+ gcvCOMPARE_LESS_OR_EQUAL,
+ gcvCOMPARE_EQUAL,
+ gcvCOMPARE_GREATER,
+ gcvCOMPARE_GREATER_OR_EQUAL,
+ gcvCOMPARE_ALWAYS,
+}
+gceCOMPARE;
+
+/* Stencil modes. */
+typedef enum _gceSTENCIL_MODE
+{
+ gcvSTENCIL_NONE,
+ gcvSTENCIL_SINGLE_SIDED,
+ gcvSTENCIL_DOUBLE_SIDED,
+}
+gceSTENCIL_MODE;
+
+/* Stencil operations. */
+typedef enum _gceSTENCIL_OPERATION
+{
+ gcvSTENCIL_KEEP,
+ gcvSTENCIL_REPLACE,
+ gcvSTENCIL_ZERO,
+ gcvSTENCIL_INVERT,
+ gcvSTENCIL_INCREMENT,
+ gcvSTENCIL_DECREMENT,
+ gcvSTENCIL_INCREMENT_SATURATE,
+ gcvSTENCIL_DECREMENT_SATURATE,
+}
+gceSTENCIL_OPERATION;
+
+/* Stencil selection. */
+typedef enum _gceSTENCIL_WHERE
+{
+ gcvSTENCIL_FRONT,
+ gcvSTENCIL_BACK,
+}
+gceSTENCIL_WHERE;
+
+/* Texture addressing selection. */
+typedef enum _gceTEXTURE_WHICH
+{
+ gcvTEXTURE_S,
+ gcvTEXTURE_T,
+ gcvTEXTURE_R,
+}
+gceTEXTURE_WHICH;
+
+/* Texture addressing modes. */
+typedef enum _gceTEXTURE_ADDRESSING
+{
+ gcvTEXTURE_WRAP,
+ gcvTEXTURE_CLAMP,
+ gcvTEXTURE_BORDER,
+ gcvTEXTURE_MIRROR,
+ gcvTEXTURE_MIRROR_ONCE,
+}
+gceTEXTURE_ADDRESSING;
+
+/* Texture filters. */
+typedef enum _gceTEXTURE_FILTER
+{
+ gcvTEXTURE_NONE,
+ gcvTEXTURE_POINT,
+ gcvTEXTURE_LINEAR,
+ gcvTEXTURE_ANISOTROPIC,
+}
+gceTEXTURE_FILTER;
+
+/* Primitive types. */
+typedef enum _gcePRIMITIVE
+{
+ gcvPRIMITIVE_POINT_LIST,
+ gcvPRIMITIVE_LINE_LIST,
+ gcvPRIMITIVE_LINE_STRIP,
+ gcvPRIMITIVE_LINE_LOOP,
+ gcvPRIMITIVE_TRIANGLE_LIST,
+ gcvPRIMITIVE_TRIANGLE_STRIP,
+ gcvPRIMITIVE_TRIANGLE_FAN,
+}
+gcePRIMITIVE;
+
+/* Index types. */
+typedef enum _gceINDEX_TYPE
+{
+ gcvINDEX_8,
+ gcvINDEX_16,
+ gcvINDEX_32,
+}
+gceINDEX_TYPE;
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Query the target capabilities. */
+gceSTATUS
+gcoHAL_QueryTargetCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MultiTargetCount,
+ OUT gctUINT * MaxSamples
+ );
+
+gceSTATUS
+gcoHAL_SetDepthOnly(
+ IN gcoHAL Hal,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoHAL_QueryShaderCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * VertexUniforms,
+ OUT gctUINT * FragmentUniforms,
+ OUT gctUINT * Varyings
+ );
+
+gceSTATUS
+gcoHAL_QueryTextureCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoHAL_QueryStreamCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT32 * MaxAttributes,
+ OUT gctUINT32 * MaxStreamSize,
+ OUT gctUINT32 * NumberOfStreams,
+ OUT gctUINT32 * Alignment
+ );
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*--------------------------------- gcoSURF 3D --------------------------------*/
+
+/* Copy surface. */
+gceSTATUS
+gcoSURF_Copy(
+ IN gcoSURF Surface,
+ IN gcoSURF Source
+ );
+
+/* Clear surface. */
+gceSTATUS
+gcoSURF_Clear(
+ IN gcoSURF Surface,
+ IN gctUINT Flags
+ );
+
+/* Set number of samples for a gcoSURF object. */
+gceSTATUS
+gcoSURF_SetSamples(
+ IN gcoSURF Surface,
+ IN gctUINT Samples
+ );
+
+/* Get the number of samples per pixel. */
+gceSTATUS
+gcoSURF_GetSamples(
+ IN gcoSURF Surface,
+ OUT gctUINT_PTR Samples
+ );
+
+/* Clear rectangular surface. */
+gceSTATUS
+gcoSURF_ClearRect(
+ IN gcoSURF Surface,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctUINT Flags
+ );
+
+/* TO BE REMOVED */
+#if 1
+ gceSTATUS
+ depr_gcoSURF_Resolve(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 DestAddress,
+ IN gctPOINTER DestBits,
+ IN gctINT DestStride,
+ IN gceSURF_TYPE DestType,
+ IN gceSURF_FORMAT DestFormat,
+ IN gctUINT DestWidth,
+ IN gctUINT DestHeight
+ );
+
+ gceSTATUS
+ depr_gcoSURF_ResolveRect(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 DestAddress,
+ IN gctPOINTER DestBits,
+ IN gctINT DestStride,
+ IN gceSURF_TYPE DestType,
+ IN gceSURF_FORMAT DestFormat,
+ IN gctUINT DestWidth,
+ IN gctUINT DestHeight,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+#endif
+
+/* Resample surface. */
+gceSTATUS
+gcoSURF_Resample(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface
+ );
+
+/* Resolve surface. */
+gceSTATUS
+gcoSURF_Resolve(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface
+ );
+
+/* Resolve rectangular area of a surface. */
+gceSTATUS
+gcoSURF_ResolveRect(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+
+/* Set surface resolvability. */
+gceSTATUS
+gcoSURF_SetResolvability(
+ IN gcoSURF Surface,
+ IN gctBOOL Resolvable
+ );
+
+/******************************************************************************\
+******************************** gcoINDEX Object *******************************
+\******************************************************************************/
+
+/* Construct a new gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoINDEX * Index
+ );
+
+/* Destroy a gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Destroy(
+ IN gcoINDEX Index
+ );
+
+/* Lock index in memory. */
+gceSTATUS
+gcoINDEX_Lock(
+ IN gcoINDEX Index,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Unlock index that was previously locked with gcoINDEX_Lock. */
+gceSTATUS
+gcoINDEX_Unlock(
+ IN gcoINDEX Index
+ );
+
+/* Upload index data into the memory. */
+gceSTATUS
+gcoINDEX_Load(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE IndexType,
+ IN gctUINT32 IndexCount,
+ IN gctPOINTER IndexBuffer
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_Bind(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_BindOffset(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset
+ );
+
+/* Free existing index buffer. */
+gceSTATUS
+gcoINDEX_Free(
+ IN gcoINDEX Index
+ );
+
+/* Upload data into an index buffer. */
+gceSTATUS
+gcoINDEX_Upload(
+ IN gcoINDEX Index,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/* Upload data into an index buffer starting at an offset. */
+gceSTATUS
+gcoINDEX_UploadOffset(
+ IN gcoINDEX Index,
+ IN gctUINT32 Offset,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/* Query the index capabilities. */
+gceSTATUS
+gcoINDEX_QueryCaps(
+ OUT gctBOOL * Index8,
+ OUT gctBOOL * Index16,
+ OUT gctBOOL * Index32,
+ OUT gctUINT * MaxIndex
+ );
+
+gceSTATUS
+gcoIndex_CopyFakeIndex(
+ IN gcoINDEX index,
+ IN gctUINT8_PTR logic,
+ IN gctUINT32 physical,
+ IN gctUINT32 offset,
+ IN gctUINT32 size);
+
+/* 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
+ );
+/* Convert Index32 to Index16*/
+gceSTATUS
+gcoINDEX_CovertFrom32To16(
+ IN gcoINDEX Index,
+ OUT gcoINDEX* Index16
+ );
+/* Convert Index32 to Index16*/
+gceSTATUS
+gcoINDEX_CovertFrom32To16(
+ IN gcoINDEX Index,
+ OUT gcoINDEX* Index16
+ );
+
+/* Dynamic buffer management. */
+gceSTATUS
+gcoINDEX_SetDynamic(
+ IN gcoINDEX Index,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Buffers
+ );
+
+gceSTATUS
+gcoINDEX_UploadDynamic(
+ IN gcoINDEX Index,
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Bytes
+ );
+
+/******************************************************************************\
+********************************** gco3D Object *********************************
+\******************************************************************************/
+
+/* Clear flags. */
+typedef enum _gceCLEAR
+{
+ gcvCLEAR_COLOR = 0x1,
+ gcvCLEAR_DEPTH = 0x2,
+ gcvCLEAR_STENCIL = 0x4,
+ gcvCLEAR_HZ = 0x8,
+ gcvCLEAR_HAS_VAA = 0x10,
+}
+gceCLEAR;
+
+/* Blending targets. */
+typedef enum _gceBLEND_UNIT
+{
+ gcvBLEND_SOURCE,
+ gcvBLEND_TARGET,
+}
+gceBLEND_UNIT;
+
+/* Construct a new gco3D object. */
+gceSTATUS
+gco3D_Construct(
+ IN gcoHAL Hal,
+ OUT gco3D * Engine
+ );
+
+/* Destroy an gco3D object. */
+gceSTATUS
+gco3D_Destroy(
+ IN gco3D Engine
+ );
+
+/* Set 3D API type. */
+gceSTATUS
+gco3D_SetAPI(
+ IN gco3D Engine,
+ IN gceAPI ApiType
+ );
+
+/* Set render target. */
+gceSTATUS
+gco3D_SetTarget(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Unset render target. */
+gceSTATUS
+gco3D_UnsetTarget(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Set depth buffer. */
+gceSTATUS
+gco3D_SetDepth(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Unset depth buffer. */
+gceSTATUS
+gco3D_UnsetDepth(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Set viewport. */
+gceSTATUS
+gco3D_SetViewport(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set scissors. */
+gceSTATUS
+gco3D_SetScissors(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set clear color. */
+gceSTATUS
+gco3D_SetClearColor(
+ IN gco3D Engine,
+ IN gctUINT8 Red,
+ IN gctUINT8 Green,
+ IN gctUINT8 Blue,
+ IN gctUINT8 Alpha
+ );
+
+/* Set fixed point clear color. */
+gceSTATUS
+gco3D_SetClearColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point clear color. */
+gceSTATUS
+gco3D_SetClearColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set fixed point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Depth
+ );
+
+/* Set floating point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthF(
+ IN gco3D Engine,
+ IN gctFLOAT Depth
+ );
+
+/* Set clear stencil. */
+gceSTATUS
+gco3D_SetClearStencil(
+ IN gco3D Engine,
+ IN gctUINT32 Stencil
+ );
+
+/* Clear a Rect sub-surface. */
+gceSTATUS
+gco3D_ClearRect(
+ IN gco3D Engine,
+ IN gctUINT32 Address,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom,
+ IN gctUINT32 Width,
+ IN gctUINT32 Height,
+ IN gctUINT32 Flags
+ );
+
+/* Clear surface. */
+gceSTATUS
+gco3D_Clear(
+ IN gco3D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 Width,
+ IN gctUINT32 Height,
+ IN gctUINT32 Flags
+ );
+
+
+/* Clear tile status. */
+gceSTATUS
+gco3D_ClearTileStatus(
+ IN gco3D Engine,
+ IN gcsSURF_INFO_PTR Surface,
+ IN gctUINT32 TileStatusAddress,
+ IN gctUINT32 Flags
+ );
+
+/* Set shading mode. */
+gceSTATUS
+gco3D_SetShading(
+ IN gco3D Engine,
+ IN gceSHADING Shading
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_EnableBlending(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set blending function. */
+gceSTATUS
+gco3D_SetBlendFunction(
+ IN gco3D Engine,
+ IN gceBLEND_UNIT Unit,
+ IN gceBLEND_FUNCTION FunctionRGB,
+ IN gceBLEND_FUNCTION FunctionAlpha
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_SetBlendMode(
+ IN gco3D Engine,
+ IN gceBLEND_MODE ModeRGB,
+ IN gceBLEND_MODE ModeAlpha
+ );
+
+/* Set blending color. */
+gceSTATUS
+gco3D_SetBlendColor(
+ IN gco3D Engine,
+ IN gctUINT Red,
+ IN gctUINT Green,
+ IN gctUINT Blue,
+ IN gctUINT Alpha
+ );
+
+/* Set fixed point blending color. */
+gceSTATUS
+gco3D_SetBlendColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point blending color. */
+gceSTATUS
+gco3D_SetBlendColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set culling mode. */
+gceSTATUS
+gco3D_SetCulling(
+ IN gco3D Engine,
+ IN gceCULL Mode
+ );
+
+/* Enable point size */
+gceSTATUS
+gco3D_SetPointSizeEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set point sprite */
+gceSTATUS
+gco3D_SetPointSprite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set fill mode. */
+gceSTATUS
+gco3D_SetFill(
+ IN gco3D Engine,
+ IN gceFILL Mode
+ );
+
+/* Set depth compare mode. */
+gceSTATUS
+gco3D_SetDepthCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Enable depth writing. */
+gceSTATUS
+gco3D_EnableDepthWrite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth mode. */
+gceSTATUS
+gco3D_SetDepthMode(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeX(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFIXED_POINT Near,
+ IN gctFIXED_POINT Far
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeF(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFLOAT Near,
+ IN gctFLOAT Far
+ );
+
+/* Set last pixel enable */
+gceSTATUS
+gco3D_SetLastPixelEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth Bias and Scale */
+gceSTATUS
+gco3D_SetDepthScaleBiasX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT DepthScale,
+ IN gctFIXED_POINT DepthBias
+ );
+
+gceSTATUS
+gco3D_SetDepthScaleBiasF(
+ IN gco3D Engine,
+ IN gctFLOAT DepthScale,
+ IN gctFLOAT DepthBias
+ );
+
+/* Enable or disable dithering. */
+gceSTATUS
+gco3D_EnableDither(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set color write enable bits. */
+gceSTATUS
+gco3D_SetColorWrite(
+ IN gco3D Engine,
+ IN gctUINT8 Enable
+ );
+
+/* Enable or disable early depth. */
+gceSTATUS
+gco3D_SetEarlyDepth(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Enable or disable depth-only mode. */
+gceSTATUS
+gco3D_SetDepthOnly(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set stencil mode. */
+gceSTATUS
+gco3D_SetStencilMode(
+ IN gco3D Engine,
+ IN gceSTENCIL_MODE Mode
+ );
+
+/* Set stencil mask. */
+gceSTATUS
+gco3D_SetStencilMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil write mask. */
+gceSTATUS
+gco3D_SetStencilWriteMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil reference. */
+gceSTATUS
+gco3D_SetStencilReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference
+ );
+
+/* Set stencil compare. */
+gceSTATUS
+gco3D_SetStencilCompare(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceCOMPARE Compare
+ );
+
+/* Set stencil operation on pass. */
+gceSTATUS
+gco3D_SetStencilPass(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on fail. */
+gceSTATUS
+gco3D_SetStencilFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on depth fail. */
+gceSTATUS
+gco3D_SetStencilDepthFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Enable or disable alpha test. */
+gceSTATUS
+gco3D_SetAlphaTest(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set alpha test compare. */
+gceSTATUS
+gco3D_SetAlphaCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Set alpha test reference in unsigned integer. */
+gceSTATUS
+gco3D_SetAlphaReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference
+ );
+
+/* Set alpha test reference in fixed point. */
+gceSTATUS
+gco3D_SetAlphaReferenceX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Reference
+ );
+
+/* Set alpha test reference in floating point. */
+gceSTATUS
+gco3D_SetAlphaReferenceF(
+ IN gco3D Engine,
+ IN gctFLOAT Reference
+ );
+
+/* Enable/Disable anti-alias line. */
+gceSTATUS
+gco3D_SetAntiAliasLine(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set texture slot for anti-alias line. */
+gceSTATUS
+gco3D_SetAALineTexSlot(
+ IN gco3D Engine,
+ IN gctUINT TexSlot
+ );
+
+/* Set anti-alias line width scale. */
+gceSTATUS
+gco3D_SetAALineWidth(
+ IN gco3D Engine,
+ IN gctFLOAT Width
+ );
+
+/* Draw a number of primitives. */
+gceSTATUS
+gco3D_DrawPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT StartVertex,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of primitives using offsets. */
+gceSTATUS
+gco3D_DrawPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of indexed primitives. */
+gceSTATUS
+gco3D_DrawIndexedPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT BaseVertex,
+ IN gctINT StartIndex,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of indexed primitives using offsets. */
+gceSTATUS
+gco3D_DrawIndexedPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 BaseOffset,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Enable or disable anti-aliasing. */
+gceSTATUS
+gco3D_SetAntiAlias(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Write data into the command buffer. */
+gceSTATUS
+gco3D_WriteBuffer(
+ IN gco3D Engine,
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Aligned
+ );
+
+/*Send sempahore and stall until sempahore is signalled.*/
+gceSTATUS
+gco3D_Semaphore(
+ IN gco3D Engine,
+ IN gceWHERE From,
+ IN gceWHERE To,
+ IN gceHOW How);
+
+/*Set the subpixels center .*/
+gceSTATUS
+gco3D_SetCentroids(
+ IN gco3D Engine,
+ IN gctUINT32 Index,
+ IN gctPOINTER Centroids
+ );
+
+/*Get 3D engine status*/
+gceSTATUS
+gco3D_Get3DStatus(
+ IN gco3D Engine,
+ OUT gctBOOL_PTR* Idle,
+ OUT gctINT_PTR Count,
+ OUT gctINT_PTR CurrentCmdIndex
+ );
+/*----------------------------------------------------------------------------*/
+/*-------------------------- gco3D Fragment Processor ------------------------*/
+
+/* Set the fragment processor configuration. */
+gceSTATUS
+gco3D_SetFragmentConfiguration(
+ IN gco3D Engine,
+ IN gctBOOL ColorFromStream,
+ IN gctBOOL EnableFog,
+ IN gctBOOL EnableSmoothPoint,
+ IN gctUINT32 ClipPlanes
+ );
+
+/* Enable/disable texture stage operation. */
+gceSTATUS
+gco3D_EnableTextureStage(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL Enable
+ );
+
+/* Program the channel enable masks for the color texture function. */
+gceSTATUS
+gco3D_SetTextureColorMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the channel enable masks for the alpha texture function. */
+gceSTATUS
+gco3D_SetTextureAlphaMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the constant fragment color. */
+gceSTATUS
+gco3D_SetFragmentColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFragmentColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant fog color. */
+gceSTATUS
+gco3D_SetFogColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFogColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant texture color. */
+gceSTATUS
+gco3D_SetTetxureColorX(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetTetxureColorF(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Configure color texture function. */
+gceSTATUS
+gco3D_SetColorTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+/* Configure alpha texture function. */
+gceSTATUS
+gco3D_SetAlphaTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+
+/******************************************************************************\
+******************************* gcoTEXTURE Object *******************************
+\******************************************************************************/
+
+/* Cube faces. */
+typedef enum _gceTEXTURE_FACE
+{
+ gcvFACE_NONE,
+ gcvFACE_POSITIVE_X,
+ gcvFACE_NEGATIVE_X,
+ gcvFACE_POSITIVE_Y,
+ gcvFACE_NEGATIVE_Y,
+ gcvFACE_POSITIVE_Z,
+ gcvFACE_NEGATIVE_Z,
+}
+gceTEXTURE_FACE;
+
+/* Construct a new gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Construct(
+ IN gcoHAL Hal,
+ OUT gcoTEXTURE * Texture
+ );
+
+/* Construct a new sized gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_ConstructSized(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT Faces,
+ IN gctUINT MipMapCount,
+ IN gcePOOL Pool,
+ OUT gcoTEXTURE * Texture
+ );
+
+/* Destroy an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Destroy(
+ IN gcoTEXTURE Texture
+ );
+
+/*Destroy a texture level*/
+gceSTATUS
+gcoTEXTURE_DestroyLevel(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level
+ );
+
+/*check texture surface can be reuse*/
+gctBOOL gcoTEXTURE_BConsistent(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gctSIZE_T Width,
+ IN gctSIZE_T Height,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Upload(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctINT Stride,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Upload_Linear(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctINT Stride,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadSub(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctINT Stride,
+ IN gceSURF_FORMAT Format
+ );
+
+gceSTATUS
+gcoTEXTURE_UploadSub_Linear(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctINT Stride,
+ IN gceSURF_FORMAT Format
+ );
+
+
+/* Upload compressed data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadCompressed(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get gcoSURF object for a mipmap level. */
+gceSTATUS
+gcoTEXTURE_GetMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ OUT gcoSURF * Surface
+ );
+
+/* Get gcoSURF object for a mipmap level and face offset. */
+gceSTATUS
+gcoTEXTURE_GetMipMapFace(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ OUT gcoSURF * Surface,
+ OUT gctUINT32_PTR Offset
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT Faces,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromClient(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromSurface(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_SetEndianHint(
+ IN gcoTEXTURE Texture,
+ IN gceENDIAN_HINT EndianHint
+ );
+
+gceSTATUS
+gcoTEXTURE_SetAddressingMode(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_WHICH Which,
+ IN gceTEXTURE_ADDRESSING Mode
+ );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColor(
+ IN gcoTEXTURE Texture,
+ IN gctUINT Red,
+ IN gctUINT Green,
+ IN gctUINT Blue,
+ IN gctUINT Alpha
+ );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColorX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColorF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+gctBOOL
+gcoTEXTURE_IsSupportMipMap(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_SetMinFilter(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FILTER Filter
+ );
+
+gceSTATUS
+gcoTEXTURE_SetMagFilter(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FILTER Filter
+ );
+
+gceSTATUS
+gcoTEXTURE_SetMipFilter(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FILTER Filter
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODBiasX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT Bias
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODBiasF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT Bias
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMinX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMinF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMaxX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMaxF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_Bind(
+ IN gcoTEXTURE Texture,
+ IN gctINT Sampler,
+ IN gctUINT Param
+ );
+
+gceSTATUS
+gcoTEXTURE_Disable(
+ IN gcoHAL Hal,
+ IN gctINT Sampler
+ );
+
+gceSTATUS
+gcoTEXTURE_Flush(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_QueryCaps(
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoTEXTURE_GetClosestFormat(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT InFormat,
+ OUT gceSURF_FORMAT* OutFormat
+ );
+
+gceSTATUS
+gcoTEXTURE_RenderIntoMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_IsRenderable(
+ IN gcoTEXTURE Texture,
+ IN gctUINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_IsComplete(
+ IN gcoTEXTURE Texture,
+ IN gctINT MaxLevel
+ );
+
+/******************************************************************************\
+******************************* gcoSTREAM Object ******************************
+\******************************************************************************/
+
+typedef enum _gceVERTEX_FORMAT
+{
+ gcvVERTEX_BYTE,
+ gcvVERTEX_UNSIGNED_BYTE,
+ gcvVERTEX_SHORT,
+ gcvVERTEX_UNSIGNED_SHORT,
+ gcvVERTEX_INT,
+ gcvVERTEX_UNSIGNED_INT,
+ gcvVERTEX_FIXED,
+ gcvVERTEX_HALF,
+ gcvVERTEX_FLOAT,
+}
+gceVERTEX_FORMAT;
+
+gceSTATUS
+gcoSTREAM_Construct(
+ IN gcoHAL Hal,
+ OUT gcoSTREAM * Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Destroy(
+ IN gcoSTREAM Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Upload(
+ IN gcoSTREAM Stream,
+ IN gctCONST_POINTER Buffer,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Dynamic
+ );
+
+gceSTATUS
+gcoSTREAM_SetStride(
+ IN gcoSTREAM Stream,
+ IN gctUINT32 Stride
+ );
+
+gceSTATUS
+gcoSTREAM_Lock(
+ IN gcoSTREAM Stream,
+ OUT gctPOINTER * Logical,
+ OUT gctUINT32 * Physical
+ );
+
+gceSTATUS
+gcoSTREAM_Unlock(
+ IN gcoSTREAM Stream);
+
+gceSTATUS
+gcoSTREAM_Reserve(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL bSystemCache
+ );
+
+gceSTATUS
+gcoSTREAM_GetSystemCache(
+ IN gcoSTREAM Stream,
+ OUT gctPOINTER* pSystemCache);
+
+gceSTATUS
+gcoSTREAM_GetStreamSize(
+ IN gcoSTREAM Stream,
+ OUT gctUINT32* pSize);
+
+gceSTATUS
+gcoSTREAM_ConstructReserveMemory(
+ IN gcoHAL Hal);
+
+gceSTATUS
+gcoSTREAM_DestroyReserveMemory(
+ IN gcoHAL Hal);
+
+gceSTATUS
+gcoSTREAM_GetReserveMemIndexOffset(
+ IN gcoHAL Hal,
+ OUT gctUINT32 * reserveMemoryIndex,
+ OUT gctUINT32 * reserveMemoryOffset);
+
+gceSTATUS
+gcoSTREAM_GetReserveMemory(
+ IN gcoHAL Hal,
+ IN gctUINT32 requestSize,
+ IN gcoSTREAM stream,
+ IN gcoINDEX index
+ );
+
+gctBOOL
+gcoSTREAM_SignalReserveMemory(
+ IN gcoHAL Hal);
+
+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;
+ gctUINT offset;
+ gcoSTREAM stream;
+}
+gcsSTREAM_INFO, * gcsSTREAM_INFO_PTR;
+
+gceSTATUS
+gcoSTREAM_UploadDynamic(
+ IN gcoSTREAM Stream,
+ IN gctUINT VertexCount,
+ IN gctUINT InfoCount,
+ IN gcsSTREAM_INFO_PTR Info,
+ IN gcoVERTEX Vertex
+ );
+
+/******************************************************************************\
+******************************** gcoVERTEX Object ******************************
+\******************************************************************************/
+
+typedef struct _gcsVERTEX_ATTRIBUTES
+{
+ gceVERTEX_FORMAT format;
+ gctBOOL normalized;
+ gctUINT32 components;
+ gctSIZE_T size;
+ gctUINT32 stream;
+ gctUINT32 offset;
+ gctUINT32 stride;
+}
+gcsVERTEX_ATTRIBUTES;
+
+gceSTATUS
+gcoVERTEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVERTEX * Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Destroy(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Reset(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_EnableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index,
+ IN gceVERTEX_FORMAT Format,
+ IN gctBOOL Normalized,
+ IN gctUINT32 Components,
+ IN gcoSTREAM Stream,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Stride
+ );
+
+gceSTATUS
+gcoVERTEX_DisableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index
+ );
+
+gceSTATUS
+gcoVERTEX_Bind_fast(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 attributeCount
+ );
+
+gceSTATUS
+gcoVERTEX_Bind(
+ IN gcoVERTEX Vertex
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_engine_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_enum.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_enum.h
new file mode 100644
index 0000000..d0361af
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_enum.h
@@ -0,0 +1,565 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_enum_h_
+#define __gc_hal_enum_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Chip models. */
+typedef enum _gceCHIPMODEL
+{
+ gcv300 = 0x0300,
+ gcv400 = 0x0400,
+ gcv410 = 0x0410,
+ gcv450 = 0x0450,
+ gcv500 = 0x0500,
+ gcv530 = 0x0530,
+ gcv600 = 0x0600,
+ gcv700 = 0x0700,
+ gcv800 = 0x0800,
+ gcv860 = 0x0860,
+ gcv1000 = 0x1000,
+}
+gceCHIPMODEL;
+
+/* Chip features. */
+typedef enum _gceFEATURE
+{
+ gcvFEATURE_PIPE_2D,
+ gcvFEATURE_PIPE_3D,
+ gcvFEATURE_PIPE_VG,
+ gcvFEATURE_DC,
+ gcvFEATURE_HIGH_DYNAMIC_RANGE,
+ gcvFEATURE_MODULE_CG,
+ gcvFEATURE_MIN_AREA,
+ gcvFEATURE_BUFFER_INTERLEAVING,
+ gcvFEATURE_BYTE_WRITE_2D,
+ gcvFEATURE_ENDIANNESS_CONFIG,
+ gcvFEATURE_DUAL_RETURN_BUS,
+ gcvFEATURE_DEBUG_MODE,
+ gcvFEATURE_YUY2_RENDER_TARGET,
+ gcvFEATURE_FRAGMENT_PROCESSOR,
+ gcvFEATURE_2DPE20,
+ gcvFEATURE_FAST_CLEAR,
+ gcvFEATURE_YUV420_TILER,
+ gcvFEATURE_YUY2_AVERAGING,
+ gcvFEATURE_FLIP_Y,
+ gcvFEATURE_EARLY_Z,
+ gcvFEATURE_Z_COMPRESSION,
+ gcvFEATURE_MSAA,
+ gcvFEATURE_SPECIAL_ANTI_ALIASING,
+ gcvFEATURE_SPECIAL_MSAA_LOD,
+ gcvFEATURE_422_TEXTURE_COMPRESSION,
+ gcvFEATURE_DXT_TEXTURE_COMPRESSION,
+ gcvFEATURE_ETC1_TEXTURE_COMPRESSION,
+ gcvFEATURE_CORRECT_TEXTURE_CONVERTER,
+ gcvFEATURE_TEXTURE_8K,
+ gcvFEATURE_SCALER,
+ gcvFEATURE_YUV420_SCALER,
+ gcvFEATURE_SHADER_HAS_W,
+ gcvFEATURE_SHADER_HAS_SIGN,
+ gcvFEATURE_SHADER_HAS_FLOOR,
+ gcvFEATURE_SHADER_HAS_CEIL,
+ gcvFEATURE_SHADER_HAS_SQRT,
+ gcvFEATURE_SHADER_HAS_TRIG,
+ gcvFEATURE_VAA,
+ gcvFEATURE_HZ,
+ gcvFEATURE_CORRECT_STENCIL,
+ gcvFEATURE_VG20,
+ gcvFEATURE_VG_FILTER,
+ gcvFEATURE_VG21,
+ gcvFEATURE_VG_DOUBLE_BUFFER,
+ gcvFEATURE_MC20,
+ gcvFEATURE_SUPER_TILED,
+}
+gceFEATURE;
+
+/* Chip Power Status. */
+typedef enum _gceCHIPPOWERSTATE
+{
+ gcvPOWER_ON,
+ gcvPOWER_OFF,
+ gcvPOWER_IDLE,
+ gcvPOWER_SUSPEND,
+ gcvPOWER_SUSPEND_ATPOWERON,
+ gcvPOWER_OFF_ATPOWERON,
+ gcvPOWER_IDLE_BROADCAST,
+ gcvPOWER_SUSPEND_BROADCAST,
+ gcvPOWER_OFF_BROADCAST,
+ gcvPOWER_OFF_RECOVERY,
+}
+gceCHIPPOWERSTATE;
+
+/* Surface types. */
+typedef enum _gceSURF_TYPE
+{
+ gcvSURF_TYPE_UNKNOWN,
+ gcvSURF_INDEX,
+ gcvSURF_VERTEX,
+ gcvSURF_TEXTURE,
+ gcvSURF_RENDER_TARGET,
+ gcvSURF_DEPTH,
+ gcvSURF_BITMAP,
+ gcvSURF_TILE_STATUS,
+ gcvSURF_MASK,
+ gcvSURF_SCISSOR,
+ gcvSURF_HIERARCHICAL_DEPTH,
+ gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
+
+ /* Combinations. */
+ gcvSURF_NO_TILE_STATUS = 0x100,
+ gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
+ | gcvSURF_NO_TILE_STATUS,
+ gcvSURF_DEPTH_NO_TILE_STATUS = gcvSURF_DEPTH
+ | gcvSURF_NO_TILE_STATUS,
+}
+gceSURF_TYPE;
+
+typedef enum _gceSURF_COLOR_TYPE
+{
+ gcvSURF_COLOR_UNKNOWN,
+ gcvSURF_COLOR_LINEAR = 0x01,
+ gcvSURF_COLOR_ALPHA_PRE = 0x02,
+}
+gceSURF_COLOR_TYPE;
+
+/* Rotation. */
+typedef enum _gceSURF_ROTATION
+{
+ gcvSURF_0_DEGREE,
+ gcvSURF_90_DEGREE,
+ gcvSURF_180_DEGREE,
+ gcvSURF_270_DEGREE
+}
+gceSURF_ROTATION;
+
+/* Surface formats. */
+typedef enum _gceSURF_FORMAT
+{
+ /* Unknown format. */
+ gcvSURF_UNKNOWN,
+
+ /* Palettized formats. */
+ gcvSURF_INDEX1 = 100,
+ gcvSURF_INDEX4,
+ gcvSURF_INDEX8,
+
+ /* RGB formats. */
+ gcvSURF_A2R2G2B2 = 200,
+ gcvSURF_R3G3B2,
+ gcvSURF_A8R3G3B2,
+ gcvSURF_X4R4G4B4,
+ gcvSURF_A4R4G4B4,
+ gcvSURF_R4G4B4A4,
+ gcvSURF_X1R5G5B5,
+ gcvSURF_A1R5G5B5,
+ gcvSURF_R5G5B5A1,
+ gcvSURF_R5G6B5,
+ gcvSURF_R8G8B8,
+ gcvSURF_X8R8G8B8,
+ gcvSURF_A8R8G8B8,
+ gcvSURF_R8G8B8A8,
+ gcvSURF_G8R8G8B8,
+ gcvSURF_R8G8B8G8,
+ gcvSURF_X2R10G10B10,
+ gcvSURF_A2R10G10B10,
+ gcvSURF_X12R12G12B12,
+ gcvSURF_A12R12G12B12,
+ gcvSURF_X16R16G16B16,
+ gcvSURF_A16R16G16B16,
+ gcvSURF_R8G8B8X8,
+ gcvSURF_R5G5B5X1,
+ gcvSURF_R4G4B4X4,
+
+ /* BGR formats. */
+ gcvSURF_A4B4G4R4 = 300,
+ gcvSURF_A1B5G5R5,
+ gcvSURF_B5G6R5,
+ gcvSURF_B8G8R8,
+ gcvSURF_X8B8G8R8,
+ gcvSURF_A8B8G8R8,
+ gcvSURF_A2B10G10R10,
+ gcvSURF_A16B16G16R16,
+ gcvSURF_G16R16,
+ gcvSURF_B4G4R4A4,
+ gcvSURF_B5G5R5A1,
+ gcvSURF_B8G8R8X8,
+ gcvSURF_B8G8R8A8,
+ gcvSURF_X4B4G4R4,
+ gcvSURF_X1B5G5R5,
+ gcvSURF_B4G4R4X4,
+ gcvSURF_B5G5R5X1,
+
+ /* Compressed formats. */
+ gcvSURF_DXT1 = 400,
+ gcvSURF_DXT2,
+ gcvSURF_DXT3,
+ gcvSURF_DXT4,
+ gcvSURF_DXT5,
+ gcvSURF_CXV8U8,
+ gcvSURF_ETC1,
+
+ /* YUV formats. */
+ gcvSURF_YUY2 = 500,
+ gcvSURF_UYVY,
+ gcvSURF_YV12,
+ gcvSURF_I420,
+ gcvSURF_NV12,
+ gcvSURF_NV21,
+ gcvSURF_NV16,
+ gcvSURF_NV61,
+ gcvSURF_YVYU,
+ gcvSURF_VYUY,
+
+ /* Depth formats. */
+ gcvSURF_D16 = 600,
+ gcvSURF_D24S8,
+ gcvSURF_D32,
+ gcvSURF_D24X8,
+
+ /* Alpha formats. */
+ gcvSURF_A4 = 700,
+ gcvSURF_A8,
+ gcvSURF_A12,
+ gcvSURF_A16,
+ gcvSURF_A32,
+ gcvSURF_A1,
+
+ /* Luminance formats. */
+ gcvSURF_L4 = 800,
+ gcvSURF_L8,
+ gcvSURF_L12,
+ gcvSURF_L16,
+ gcvSURF_L32,
+ gcvSURF_L1,
+
+ /* Alpha/Luminance formats. */
+ gcvSURF_A4L4 = 900,
+ gcvSURF_A2L6,
+ gcvSURF_A8L8,
+ gcvSURF_A4L12,
+ gcvSURF_A12L12,
+ gcvSURF_A16L16,
+
+ /* Bump formats. */
+ gcvSURF_L6V5U5 = 1000,
+ gcvSURF_V8U8,
+ gcvSURF_X8L8V8U8,
+ gcvSURF_Q8W8V8U8,
+ gcvSURF_A2W10V10U10,
+ gcvSURF_V16U16,
+ gcvSURF_Q16W16V16U16,
+
+ /* Floating point formats. */
+ gcvSURF_R16F = 1100,
+ gcvSURF_G16R16F,
+ gcvSURF_A16B16G16R16F,
+ gcvSURF_R32F,
+ gcvSURF_G32R32F,
+ gcvSURF_A32B32G32R32F,
+
+#if 0
+ /* FIXME: remove HDR support for now. */
+ /* HDR formats. */
+ gcvSURF_HDR7E3 = 1200,
+ gcvSURF_HDR6E4,
+ gcvSURF_HDR5E5,
+ gcvSURF_HDR6E5,
+#endif
+}
+gceSURF_FORMAT;
+
+/* Pixel swizzle modes. */
+typedef enum _gceSURF_SWIZZLE
+{
+ gcvSURF_NOSWIZZLE,
+ gcvSURF_ARGB,
+ gcvSURF_ABGR,
+ gcvSURF_RGBA,
+ gcvSURF_BGRA
+}
+gceSURF_SWIZZLE;
+
+/* Transparency modes. */
+typedef enum _gceSURF_TRANSPARENCY
+{
+ /* Valid only for PE 1.0 */
+ gcvSURF_OPAQUE,
+ gcvSURF_SOURCE_MATCH,
+ gcvSURF_SOURCE_MASK,
+ gcvSURF_PATTERN_MASK,
+}
+gceSURF_TRANSPARENCY;
+
+/* Transparency modes. */
+typedef enum _gce2D_TRANSPARENCY
+{
+ /* Valid only for PE 2.0 */
+ gcv2D_OPAQUE,
+ gcv2D_KEYED,
+ gcv2D_MASKED
+}
+gce2D_TRANSPARENCY;
+
+/* Mono packing modes. */
+typedef enum _gceSURF_MONOPACK
+{
+ gcvSURF_PACKED8,
+ gcvSURF_PACKED16,
+ gcvSURF_PACKED32,
+ gcvSURF_UNPACKED,
+}
+gceSURF_MONOPACK;
+
+/* Blending modes. */
+typedef enum _gceSURF_BLEND_MODE
+{
+ /* Porter-Duff blending modes. */
+ /* Fsrc Fdst */
+ gcvBLEND_CLEAR, /* 0 0 */
+ gcvBLEND_SRC, /* 1 0 */
+ gcvBLEND_DST, /* 0 1 */
+ gcvBLEND_SRC_OVER_DST, /* 1 1 - Asrc */
+ gcvBLEND_DST_OVER_SRC, /* 1 - Adst 1 */
+ gcvBLEND_SRC_IN_DST, /* Adst 0 */
+ gcvBLEND_DST_IN_SRC, /* 0 Asrc */
+ gcvBLEND_SRC_OUT_DST, /* 1 - Adst 0 */
+ gcvBLEND_DST_OUT_SRC, /* 0 1 - Asrc */
+ gcvBLEND_SRC_ATOP_DST, /* Adst 1 - Asrc */
+ gcvBLEND_DST_ATOP_SRC, /* 1 - Adst Asrc */
+ gcvBLEND_SRC_XOR_DST, /* 1 - Adst 1 - Asrc */
+
+ /* Special blending modes. */
+ gcvBLEND_SET, /* DST = 1 */
+ gcvBLEND_SUB /* DST = DST * (1 - SRC) */
+}
+gceSURF_BLEND_MODE;
+
+/* Per-pixel alpha modes. */
+typedef enum _gceSURF_PIXEL_ALPHA_MODE
+{
+ gcvSURF_PIXEL_ALPHA_STRAIGHT,
+ gcvSURF_PIXEL_ALPHA_INVERSED
+}
+gceSURF_PIXEL_ALPHA_MODE;
+
+/* Global alpha modes. */
+typedef enum _gceSURF_GLOBAL_ALPHA_MODE
+{
+ gcvSURF_GLOBAL_ALPHA_OFF,
+ gcvSURF_GLOBAL_ALPHA_ON,
+ gcvSURF_GLOBAL_ALPHA_SCALE
+}
+gceSURF_GLOBAL_ALPHA_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gceSURF_PIXEL_COLOR_MODE
+{
+ gcvSURF_COLOR_STRAIGHT,
+ gcvSURF_COLOR_MULTIPLY
+}
+gceSURF_PIXEL_COLOR_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_COLOR_MULTIPLY_DISABLE,
+ gcv2D_COLOR_MULTIPLY_ENABLE
+}
+gce2D_PIXEL_COLOR_MULTIPLY_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_GLOBAL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_GLOBAL_COLOR_MULTIPLY_DISABLE,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_COLOR
+}
+gce2D_GLOBAL_COLOR_MULTIPLY_MODE;
+
+/* Alpha blending factor modes. */
+typedef enum _gceSURF_BLEND_FACTOR_MODE
+{
+ gcvSURF_BLEND_ZERO,
+ gcvSURF_BLEND_ONE,
+ gcvSURF_BLEND_STRAIGHT,
+ gcvSURF_BLEND_INVERSED,
+ gcvSURF_BLEND_COLOR,
+ gcvSURF_BLEND_COLOR_INVERSED,
+ gcvSURF_BLEND_SRC_ALPHA_SATURATED
+}
+gceSURF_BLEND_FACTOR_MODE;
+
+/* Alpha blending porter duff rules. */
+typedef enum _gce2D_PORTER_DUFF_RULE
+{
+ gcvPD_CLEAR,
+ gcvPD_SRC,
+ gcvPD_SRC_OVER,
+ gcvPD_DST_OVER,
+ gcvPD_SRC_IN,
+ gcvPD_DST_IN,
+ gcvPD_SRC_OUT,
+ gcvPD_DST_OUT,
+ gcvPD_SRC_ATOP,
+ gcvPD_DST_ATOP,
+ gcvPD_ADD,
+ gcvPD_XOR,
+ gcvPD_DST
+}
+gce2D_PORTER_DUFF_RULE;
+
+/* Alpha blending factor modes. */
+typedef enum _gce2D_YUV_COLOR_MODE
+{
+ gcv2D_YUV_601,
+ gcv2D_YUV_709
+}
+gce2D_YUV_COLOR_MODE;
+
+/* 2D Rotation and flipping. */
+typedef enum _gce2D_ORIENTATION
+{
+ gcv2D_0_DEGREE,
+ gcv2D_90_DEGREE,
+ gcv2D_180_DEGREE,
+ gcv2D_270_DEGREE,
+ gcv2D_X_FLIP,
+ gcv2D_Y_FLIP
+}
+gce2D_ORIENTATION;
+
+typedef enum _gce2D_COMMAND
+{
+ gcv2D_CLEAR,
+ gcv2D_LINE,
+ gcv2D_BLT,
+ gcv2D_STRETCH,
+ gcv2D_HOR_FILTER,
+ gcv2D_VER_FILTER,
+}
+gce2D_COMMAND;
+
+/* Texture functions. */
+typedef enum _gceTEXTURE_FUNCTION
+{
+ gcvTEXTURE_DUMMY = 0,
+ gcvTEXTURE_REPLACE = 0,
+ gcvTEXTURE_MODULATE,
+ gcvTEXTURE_ADD,
+ gcvTEXTURE_ADD_SIGNED,
+ gcvTEXTURE_INTERPOLATE,
+ gcvTEXTURE_SUBTRACT,
+ gcvTEXTURE_DOT3
+}
+gceTEXTURE_FUNCTION;
+
+/* Texture sources. */
+typedef enum _gceTEXTURE_SOURCE
+{
+ gcvCOLOR_FROM_TEXTURE,
+ gcvCOLOR_FROM_CONSTANT_COLOR,
+ gcvCOLOR_FROM_PRIMARY_COLOR,
+ gcvCOLOR_FROM_PREVIOUS_COLOR
+}
+gceTEXTURE_SOURCE;
+
+/* Texture source channels. */
+typedef enum _gceTEXTURE_CHANNEL
+{
+ gcvFROM_COLOR,
+ gcvFROM_ONE_MINUS_COLOR,
+ gcvFROM_ALPHA,
+ gcvFROM_ONE_MINUS_ALPHA
+}
+gceTEXTURE_CHANNEL;
+
+/* Filter types. */
+typedef enum _gceFILTER_TYPE
+{
+ gcvFILTER_SYNC,
+ gcvFILTER_BLUR,
+ gcvFILTER_USER
+}
+gceFILTER_TYPE;
+
+/* Filter pass types. */
+typedef enum _gceFILTER_PASS_TYPE
+{
+ gcvFILTER_HOR_PASS,
+ gcvFILTER_VER_PASS
+}
+gceFILTER_PASS_TYPE;
+
+/* Endian hints. */
+typedef enum _gceENDIAN_HINT
+{
+ gcvENDIAN_NO_SWAP = 0,
+ gcvENDIAN_SWAP_WORD,
+ gcvENDIAN_SWAP_DWORD
+}
+gceENDIAN_HINT;
+
+/* Endian hints. */
+typedef enum _gceTILING
+{
+ gcvLINEAR,
+ gcvTILED,
+ gcvSUPERTILED
+}
+gceTILING;
+
+typedef enum _gceSAMPLERDIRTY
+{
+ gcvSAMPLER_MIN_FILTER_DIRTY,
+ gcvSAMPLER_MAG_FILTER_DIRTY,
+ gcvSAMPLER_WRAPR_DIRTY_DIRTY,
+ gcvSAMPLER_WRAPS_DIRTY_DIRTY,
+ gcvSAMPLER_WRAPT_DIRTY_DIRTY,
+ gcvSAMPLER_LODMINX_DIRTY,
+ gcvSAMPLER_LODBIASX_DIRTY,
+ gcvSAMPLER_BORDERCOLOR_DIRTY,
+ gcvSAMPLER_MIPMAP_DIRTY,
+ gcvSAMPLER_ALL_DIRTY
+}
+gceSAMPLERDIRTY;
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoCONTEXT * gcoCONTEXT;
+typedef struct _gcoCTXBUF * gcoCTXBUF;
+typedef struct _gcoCMDBUF * gcoCMDBUF;
+typedef struct _gcoQUEUE * gcoQUEUE;
+typedef struct _gcsHAL_INTERFACE * gcsHAL_INTERFACE_PTR;
+typedef struct gcs2D_PROFILE * gcs2D_PROFILE_PTR;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_enum_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_mem.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_mem.h
new file mode 100644
index 0000000..e3c4433
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_mem.h
@@ -0,0 +1,472 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/*
+** Include file for the local memory management.
+*/
+
+#ifndef __gc_hal_mem_h_
+#define __gc_hal_mem_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+*******************************************************************************
+** 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);
+
+*******************************************************************************
+#endif
+
+/*******************************************************************************
+** To switch back to use gcoOS_Allocate and gcoOS_Free, add
+** #define USE_LOCAL_MEMORY_POOL 0
+** before including this file.
+*******************************************************************************/
+#ifndef USE_LOCAL_MEMORY_POOL
+/*
+ USE_LOCAL_MEMORY_POOL
+
+ This define enables the local memory management to improve performance.
+*/
+#define USE_LOCAL_MEMORY_POOL 1
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Structures
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+ typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
+ typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
+ typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
+#else
+ typedef gcoOS gcsMEM_FS_MEM_POOL;
+ typedef gcoOS gcsMEM_VS_MEM_POOL;
+ typedef gcoOS gcsMEM_AFS_MEM_POOL;
+#endif
+
+/*******************************************************************************
+** Memory Pool Macros
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName##List( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * FirstPointer, \
+ Type * LastPointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer)); \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ return(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+ Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size)); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ return(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+}
+
+#else
+
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ return(gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcoOS_Free(MemPool, Pointer)); \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ return(gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size)); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcoOS_Free(MemPool, Pointer)); \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ return(gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcoOS_Free(MemPool, Pointer)); \
+}
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Functions
+*******************************************************************************/
+gceSTATUS
+gcfMEM_InitFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolGetANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeAList(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER FirstNode,
+ IN gctPOINTER LastNode
+ );
+
+gceSTATUS
+gcfMEM_InitVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT BlockSize,
+ IN gctBOOL RecycleFreeNode
+ );
+
+gceSTATUS
+gcfMEM_FreeVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolGetANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolFreeANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_InitAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolGetANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctUINT Count,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolFreeANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_mem_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_options.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_options.h
new file mode 100644
index 0000000..b9749f4
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_options.h
@@ -0,0 +1,532 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_options_h_
+#define __gc_hal_options_h_
+
+/*
+ USE_NEW_LINUX_SIGNAL
+
+ This define enables the Linux kernel signaling between kernel and user.
+*/
+#ifndef USE_NEW_LINUX_SIGNAL
+# define USE_NEW_LINUX_SIGNAL 0
+#endif
+
+/*
+ NO_USER_DIRECT_ACCESS_FROM_KERNEL
+
+ This define enables the Linux kernel behavior accessing user memory.
+*/
+#ifndef NO_USER_DIRECT_ACCESS_FROM_KERNEL
+# define NO_USER_DIRECT_ACCESS_FROM_KERNEL 0
+#endif
+
+/*
+ VIVANTE_PROFILER
+
+ This define enables the profiler.
+*/
+#ifndef VIVANTE_PROFILER
+# define VIVANTE_PROFILER 0
+#endif
+
+/*
+ gcdUSE_VG
+
+ Enable VG HAL layer (only for GC350).
+*/
+#ifndef gcdUSE_VG
+# define gcdUSE_VG 0
+#endif
+
+/*
+ USE_SW_FB
+
+ Set to 1 if the frame buffer memory cannot be accessed by the GPU.
+*/
+#ifndef USE_SW_FB
+#define USE_SW_FB 0
+#endif
+
+/*
+ USE_SHADER_SYMBOL_TABLE
+
+ This define enables the symbol table in shader object.
+*/
+#define USE_SHADER_SYMBOL_TABLE 1
+
+/*
+ USE_SUPER_SAMPLING
+
+ This define enables super-sampling support.
+*/
+#define USE_SUPER_SAMPLING 0
+
+/*
+ PROFILE_HAL_COUNTERS
+
+ This define enables HAL counter profiling support.
+ HW and SHADER Counter profiling depends on this.
+*/
+#define PROFILE_HAL_COUNTERS 1
+
+/*
+ PROFILE_HW_COUNTERS
+
+ This define enables HW counter profiling support.
+*/
+#define PROFILE_HW_COUNTERS 1
+
+/*
+ PROFILE_SHADER_COUNTERS
+
+ This define enables SHADER counter profiling support.
+*/
+#define PROFILE_SHADER_COUNTERS 1
+
+/*
+ COMMAND_PROCESSOR_VERSION
+
+ The version of the command buffer and task manager.
+*/
+#define COMMAND_PROCESSOR_VERSION 1
+
+/*
+ gcdDUMP
+
+ When set to 1, a dump of all states and memory uploads, as well as other
+ hardware related execution will be printed to the debug console. This
+ data can be used for playing back applications.
+*/
+#define gcdDUMP 0
+
+/*
+ gcdDUMP_API
+
+ When set to 1, a high level dump of the EGL and GL/VG APs's are
+ captured.
+*/
+#define gcdDUMP_API 0
+
+/*
+ gcdDUMP_IN_KERNEL
+
+ When set to 1, all dumps will happen in the kernel. This is handy if
+ you want the kernel to dump its command buffers as well and the data
+ needs to be in sync.
+*/
+#define gcdDUMP_IN_KERNEL 0
+
+/*
+ gcdDUMP_COMMAND
+
+ When set to non-zero, the command queue will dump all incoming command
+ and context buffers as well as all other modifications to the command
+ queue.
+*/
+#define gcdDUMP_COMMAND 0
+
+/*
+ gcdNULL_DRIVER
+*/
+#define gcdNULL_DRIVER 0
+
+/*
+ gcdENABLE_TIMEOUT_DETECTION
+
+ Enable timeout detection.
+*/
+#define gcdENABLE_TIMEOUT_DETECTION 0
+
+/*
+ gcdCMD_BUFFERS
+
+ Number of command buffers to use per client. Each command buffer is 32kB in
+ size.
+*/
+#define gcdCMD_BUFFERS 2
+
+/*
+ gcdPOWER_CONTROL_DELAY
+
+ The delay in milliseconds required to wait until the GPU has woke up from a
+ suspend or power-down state. This is system dependent because the bus clock
+ also needs to be stabalize.
+*/
+#define gcdPOWER_CONTROL_DELAY 1
+
+/*
+ gcdMMU_SIZE
+
+ Size of the MMU page table in bytes. Each 4 bytes can hold 4kB worth of
+ virtual data.
+*/
+#define gcdMMU_SIZE (128 << 10)
+
+/*
+ gcdSECURE_USER
+
+ Use logical addresses instead of physical addresses in user land. In this
+ case a hint table is created for both command buffers and context buffers,
+ and that hint table will be used to patch up those buffers in the kernel
+ when they are ready to submit.
+*/
+#define gcdSECURE_USER 0
+
+/*
+ gcdSECURE_CACHE_SLOTS
+
+ Number of slots in the logical to DMA address cache table. Each time a
+ logical address needs to be translated into a DMA address for the GPU, this
+ cache will be walked. The replacement scheme is LRU.
+*/
+#define gcdSECURE_CACHE_SLOTS 64
+
+/*
+ gcdREGISTER_ACCESS_FROM_USER
+
+ Set to 1 to allow IOCTL calls to get through from user land. This should
+ only be in debug or development drops.
+*/
+#ifndef gcdREGISTER_ACCESS_FROM_USER
+# define gcdREGISTER_ACCESS_FROM_USER 1
+#endif
+
+/*
+ gcdHEAP_SIZE
+
+ Set the allocation size for the internal heaps. Each time a heap is full,
+ a new heap will be allocated with this minmimum amount of bytes. The bigger
+ this size, the fewer heaps there are to allocate, the better the
+ performance. However, heaps won't be freed until they are completely free,
+ so there might be some more memory waste if the size is too big.
+*/
+#define gcdHEAP_SIZE (64 << 10)
+/*
+ MRVL_TAVOR_PV2_DISABLE_YFLIP
+*/
+#define MRVL_TAVOR_PV2_DISABLE_YFLIP 0
+
+/*
+ gcdNO_POWER_MANAGEMENT
+
+ This define disables the power management code.
+*/
+#ifndef gcdNO_POWER_MANAGEMENT
+# define gcdNO_POWER_MANAGEMENT 0
+#endif
+
+/*
+ VIVANTE_POWER_MANAGE
+
+ This define enable the vivante power management code.
+*/
+#ifndef VIVANTE_POWER_MANAGE
+# define VIVANTE_POWER_MANAGE 1
+#endif
+/*
+ gcdFPGA_BUILD
+
+ This define enables work arounds for FPGA images.
+*/
+#if !defined(gcdFPGA_BUILD)
+# define gcdFPGA_BUILD 0
+#endif
+
+/*
+ gcdGPU_TIMEOUT
+
+ This define specified the number of milliseconds the system will wait before
+ it broadcasts the GPU is stuck. In other words, it will define the timeout
+ of any operation that needs to wait for the GPU.
+
+ If the value is 0, no timeout will be checked for.
+*/
+#if !defined(gcdGPU_TIMEOUT)
+# define gcdGPU_TIMEOUT 0
+#endif
+
+/*
+ * MACRO definition of MRVL
+ */
+#ifdef CONFIG_CPU_PXA910
+#define MRVL_PLATFORM_TD 1
+#else
+#define MRVL_PLATFORM_TD 0
+#endif
+
+#ifdef CONFIG_PXA95x
+#define MRVL_PLATFORM_MG1 1
+#else
+#define MRVL_PLATFORM_MG1 0
+#endif
+
+#ifdef CONFIG_CPU_MMP2
+#define MRVL_PLATFORM_MMP2 1
+#else
+#define MRVL_PLATFORM_MMP2 0
+#endif
+
+#if (defined CONFIG_DVFM) && (defined CONFIG_DVFM_PXA910)
+#define MRVL_CONFIG_DVFM_TD 1
+#else
+#define MRVL_CONFIG_DVFM_TD 0
+#endif
+
+#ifdef CONFIG_PXA95x
+#define MRVL_CONFIG_DVFM_MG1 1
+#else
+#define MRVL_CONFIG_DVFM_MG1 0
+#endif
+
+#if (defined CONFIG_DVFM) && (defined CONFIG_DVFM_MMP2)
+#define MRVL_CONFIG_DVFM_MMP2 1
+#else
+#define MRVL_CONFIG_DVFM_MMP2 0
+#endif
+
+/*
+ MRVL_LOW_POWER_MODE_DEBUG
+*/
+#define MRVL_LOW_POWER_MODE_DEBUG 0
+
+/*
+ MRVL Utility Options
+*/
+#define MRVL_FORCE_MSAA_ON 0
+
+/*
+ MRVL_SWAP_BUFFER_IN_EVERY_DRAW
+
+ This define force swapbuffer after every drawElement/drawArray.
+*/
+#define MRVL_SWAP_BUFFER_IN_EVERY_DRAW 0
+
+#ifndef MRVL_BENCH
+# define MRVL_BENCH 0
+#endif
+
+#define MRVL_EANBLE_COMPRESSION_DXT 0
+
+/* Texture coordinate generation */
+#define MRVL_TEXGEN 1
+
+/* Tex gen code from Vivante */
+#define VIVANTE_TEXGEN 0
+
+/* Swap buffer optimization */
+#define MRVL_OPTI_SWAP_BUFFER 1
+
+/* Disable swap worker thread */
+#define MRVL_DISABLE_SWAP_THREAD 1
+
+/* API log enable */
+#define MRVL_ENABLE_ERROR_LOG 1
+#define MRVL_ENABLE_API_LOG 0
+#define MRVL_ENABLE_EGL_API_LOG 0
+#define MRVL_ENABLE_OES1_API_LOG 0
+#define MRVL_ENABLE_OES2_API_LOG 0
+#define MRVL_ENABLE_OVG_API_LOG 0
+
+/* enable it can dump logs to file
+ * for android can stop dump by "setprop marvell.graphics.dump_log 0"
+*/
+#define MRVL_DUMP_LOG_TO_FILE 0
+
+/* Optimization for Eclair UI */
+#define MRVL_OPTI_ANDROID_IMAGE 1
+
+/* if pmem is enabled and cacheable, enable it */
+#define MRVL_CACHEABLE_PMEM 1
+
+#define MRVL_DISABLE_FASTCLEAR 0
+
+#define MRVL_OPTI_COMPOSITOR 1
+#define MRVL_OPTI_COMPOSITOR_DEBUG 0
+#define MRVL_READ_PIXEL_2D 1
+#define MRVL_2D_SKIP_CONTEXT 0
+#define MRVL_2D_FORCE_FILTER_UPLOAD 1
+
+
+#define MRVL_OPTI_STREAM_FAST_PATH 1
+#define MRVL_OPTI_USE_RESERVE_MEMORY 1
+
+/* Enable user mode heap allocation
+ * if enable, all internal structure should be allocated from pre-allocated heap
+ * if disable, all internal structure should be allocated by malloc directly
+ */
+#define MRVL_ENABLE_USERMODE_HEAP_ALLOCATION 0
+
+
+/* Enable a timer thread to check the status of GC periodically */
+#define MRVL_TIMER 0
+
+/* Enable a idle profiling thread to turn off GC when idle */
+#if (MRVL_PLATFORM_TD || MRVL_PLATFORM_MG1 || MRVL_PLATFORM_MMP2) && (defined ANDROID)
+#define MRVL_PROFILE_THREAD 1
+#else
+#define MRVL_PROFILE_THREAD 0
+#endif
+
+/* Enable a guard thread to check the status of GC */
+#if (MRVL_PLATFORM_TD || MRVL_PLATFORM_MG1) && (defined ANDROID)
+#define MRVL_GUARD_THREAD 1
+#define MRVL_PRINT_CMD_BUFFER 1
+#else
+#define MRVL_GUARD_THREAD 0
+#define MRVL_PRINT_CMD_BUFFER 0
+#endif
+
+/* Power -- Enable clock gating */
+#define MRVL_ENABLE_CLOCK_GATING 1
+
+/* Power -- Enable frequency scaling */
+#define MRVL_ENABLE_FREQ_SCALING 1
+
+/* Enable dvfm control for certain platform */
+#if MRVL_CONFIG_DVFM_MG1 || MRVL_CONFIG_DVFM_MMP2
+#define MRVL_CONFIG_ENABLE_DVFM 1
+#else
+#define MRVL_CONFIG_ENABLE_DVFM 0
+#endif
+
+/* Separate GC clk and power on/off */
+#if (MRVL_PLATFORM_TD || MRVL_PLATFORM_MG1)
+#define SEPARATE_CLOCK_AND_POWER 1
+#define KEEP_POWER_ON 0
+#else
+#define SEPARATE_CLOCK_AND_POWER 0
+#endif
+
+/* Enable control of AXI bus clock */
+#if MRVL_PLATFORM_MG1
+#define MRVL_CONFIG_AXICLK_CONTROL 1
+#else
+#define MRVL_CONFIG_AXICLK_CONTROL 0
+#endif
+
+/* Enable early-suspend related functions */
+#if (defined CONFIG_HAS_EARLYSUSPEND) && (defined CONFIG_EARLYSUSPEND)
+#define MRVL_CONFIG_ENABLE_EARLYSUSPEND 1
+#else
+#define MRVL_CONFIG_ENABLE_EARLYSUSPEND 0
+#endif
+
+/* Enable BSP runtime or idle profile */
+#if (defined CONFIG_PXA910_DVFM_STATS)
+#define ENABLE_BSP_IDLE_PROFILE 1
+#else
+#define ENABLE_BSP_IDLE_PROFILE 0
+#endif
+
+/* Force surface format RGBA8888*/
+#define MRVL_FORCE_8888 0
+
+
+/* Preserve cmd buffer space to avoid unneeded split(then context switch */
+#define MRVL_PRESERVE_CMD_BUFFER 1
+
+/*
+ Record texture in command buffer for it idle or not
+*/
+#define MRVL_TEXTURE_USED_LIST 0
+
+/*
+ simple wait vsync
+*/
+#define MRVL_SIMPLE_WAIT_VSYNC 0
+
+/*
+ * to decrese mov instruction
+ */
+#define MRVL_OPTIMIZE_LIGHT_MOV 0
+
+/*
+ * for eglSwapInterval in Android
+ */
+#define MRVL_ANDROID_VSYNC_INTERVAL 1
+
+/* for speed up texture lookup
+ *
+ */
+#define MRVL_OPT_TEXTURE_LOOKUP 1
+
+/*
+ * skip unnecessary texture attribute validate
+ */
+#define MRVL_TEXTURE_VALIDATE_OPT 1
+
+/*
+ * New Back Copy Propagation Optimization
+ */
+#define MRVL_NEW_BCP_OPT 1
+
+/*
+ * VBO dirty patch Optimization
+ */
+#define MRVL_VBO_DIRTY_PATCH 1
+
+/*
+ * Pre-allocated context buffers and reuse them
+ */
+#define MRVL_PRE_ALLOCATE_CTX_BUFFER 1
+
+#if MRVL_PRE_ALLOCATE_CTX_BUFFER
+/* Minimal number of context buffers.
+* Can't be less than 2, or it can't get the signal when wait.
+*/
+#define gcdCTXBUF_SIZE_MIN 2
+/*
+* Number of context buffers to use per client by default.
+*/
+#define gcdCTXBUF_SIZE_DEFAULT 10
+#endif
+
+/*
+ * Remove image texture surface to save video memory on 2d path.
+ */
+#define MRVL_MEM_OPT 1
+
+/*
+ Definitions for vendor, renderer and version strings
+*/
+
+#define _VENDOR_STRING_ "Marvell Technology Group Ltd"
+
+#define _EGL_VERSION_STRING_ "EGL 1.3";
+
+#if defined(COMMON_LITE)
+#define _OES11_VERSION_STRING_ "OpenGL ES-CL 1.1";
+#else
+#define _OES11_VERSION_STRING_ "OpenGL ES-CM 1.1";
+#endif
+
+#define _OES20_VERSION_STRING_ "OpenGL ES 2.0";
+#define _GLSL_ES_VERSION_STRING_ "OpenGL ES GLSL ES 1.00"
+
+#define _OPENVG_VERSION_STRING_ "OpenVG 1.1"
+
+#define _GC_VERSION_STRING_ "GC Ver0.8.0.3184-1"
+
+#endif /* __gc_hal_options_h_ */
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_profiler.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_profiler.h
new file mode 100644
index 0000000..4373215
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_profiler.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_profiler_h_
+#define __gc_hal_profiler_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GLVERTEX_OBJECT 10
+#define GLVERTEX_OBJECT_BYTES 11
+
+#define GLINDEX_OBJECT 20
+#define GLINDEX_OBJECT_BYTES 21
+
+#define GLTEXTURE_OBJECT 30
+#define GLTEXTURE_OBJECT_BYTES 31
+
+#if VIVANTE_PROFILER
+#define gcmPROFILE_GC(Hal, Enum, Value) gcoPROFILER_Count(Hal, Enum, Value)
+#else
+#define gcmPROFILE_GC(Hal, Enum, Value) do { } while (gcvFALSE)
+#endif
+
+/* HW profile information. */
+typedef struct _gcsPROFILER_COUNTERS
+{
+ /* HW static counters. */
+ gctUINT32 gpuClock;
+ gctUINT32 axiClock;
+ gctUINT32 shaderClock;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuClockStart;
+ gctUINT32 gpuClockEnd;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuCyclesCounter;
+ gctUINT32 gpuTotalRead64BytesPerFrame;
+ gctUINT32 gpuTotalWrite64BytesPerFrame;
+
+ /* PE */
+ gctUINT32 pe_pixel_count_killed_by_color_pipe;
+ gctUINT32 pe_pixel_count_killed_by_depth_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_color_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_depth_pipe;
+
+ /* SH */
+ gctUINT32 ps_inst_counter;
+ gctUINT32 rendered_pixel_counter;
+ gctUINT32 vs_inst_counter;
+ gctUINT32 rendered_vertice_counter;
+ gctUINT32 vtx_branch_inst_counter;
+ gctUINT32 vtx_texld_inst_counter;
+ gctUINT32 pxl_branch_inst_counter;
+ gctUINT32 pxl_texld_inst_counter;
+
+ /* PA */
+ gctUINT32 pa_input_vtx_counter;
+ gctUINT32 pa_input_prim_counter;
+ gctUINT32 pa_output_prim_counter;
+ gctUINT32 pa_depth_clipped_counter;
+ gctUINT32 pa_trivial_rejected_counter;
+ gctUINT32 pa_culled_counter;
+
+ /* SE */
+ gctUINT32 se_culled_triangle_count;
+ gctUINT32 se_culled_lines_count;
+
+ /* RA */
+ gctUINT32 ra_valid_pixel_count;
+ gctUINT32 ra_total_quad_count;
+ gctUINT32 ra_valid_quad_count_after_early_z;
+ gctUINT32 ra_total_primitive_count;
+ gctUINT32 ra_pipe_cache_miss_counter;
+ gctUINT32 ra_prefetch_cache_miss_counter;
+ gctUINT32 ra_eez_culled_counter;
+
+ /* TX */
+ gctUINT32 tx_total_bilinear_requests;
+ gctUINT32 tx_total_trilinear_requests;
+ gctUINT32 tx_total_discarded_texture_requests;
+ gctUINT32 tx_total_texture_requests;
+ gctUINT32 tx_mem_read_count;
+ gctUINT32 tx_mem_read_in_8B_count;
+ gctUINT32 tx_cache_miss_count;
+ gctUINT32 tx_cache_hit_texel_count;
+ gctUINT32 tx_cache_miss_texel_count;
+
+ /* MC */
+ gctUINT32 mc_total_read_req_8B_from_pipeline;
+ gctUINT32 mc_total_read_req_8B_from_IP;
+ gctUINT32 mc_total_write_req_8B_from_pipeline;
+
+ /* HI */
+ gctUINT32 hi_axi_cycles_read_request_stalled;
+ gctUINT32 hi_axi_cycles_write_request_stalled;
+ gctUINT32 hi_axi_cycles_write_data_stalled;
+}
+gcsPROFILER_COUNTERS;
+
+/* HAL profile information. */
+typedef struct _gcsPROFILER
+{
+ gctFILE file;
+
+ /* Aggregate Information */
+
+ /* Clock Info */
+ gctUINT64 frameStart;
+
+ /* Current frame information */
+ gctUINT32 frameNumber;
+ gctUINT64 frameStartTimeusec;
+
+#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;
+
+#endif
+}
+gcsPROFILER;
+
+/* Memory profile information. */
+struct _gcsMemProfile
+{
+ /* Memory Usage */
+ gctUINT32 videoMemUsed;
+ gctUINT32 systemMemUsed;
+ gctUINT32 commitBufferSize;
+ gctUINT32 contextBufferCopyBytes;
+};
+
+/* Shader profile information. */
+struct _gcsSHADER_PROFILER
+{
+ gctUINT32 shaderLength;
+ gctUINT32 shaderALUCycles;
+ gctUINT32 shaderTexLoadCycles;
+ gctUINT32 shaderTempRegCount;
+ gctUINT32 shaderSamplerRegCount;
+ gctUINT32 shaderInputRegCount;
+ gctUINT32 shaderOutputRegCount;
+};
+
+/* Initialize the gcsProfiler. */
+gceSTATUS
+gcoPROFILER_Initialize(
+ IN gcoHAL Hal,
+ IN gctFILE File
+ );
+
+/* Destroy the gcProfiler. */
+gceSTATUS
+gcoPROFILER_Destroy(
+ IN gcoHAL Hal
+ );
+
+/* Call to signal end of frame. */
+gceSTATUS
+gcoPROFILER_EndFrame(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoPROFILER_Count(
+ IN gcoHAL Hal,
+ IN gctUINT32 Enum,
+ IN gctINT Value
+ );
+
+/* Profile input vertex shader. */
+gceSTATUS
+gcoPROFILER_ShaderVS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Vs
+ );
+
+/* Profile input fragment shader. */
+gceSTATUS
+gcoPROFILER_ShaderFS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Fs
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_profiler_h_ */
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_raster.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_raster.h
new file mode 100644
index 0000000..23485a2
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_raster.h
@@ -0,0 +1,807 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_raster_h_
+#define __gc_hal_raster_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoBRUSH * gcoBRUSH;
+typedef struct _gcoBRUSH_CACHE * gcoBRUSH_CACHE;
+
+/******************************************************************************\
+******************************** gcoBRUSH Object *******************************
+\******************************************************************************/
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructSingleColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructMonochrome(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Destroy an gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_Destroy(
+ IN gcoBRUSH Brush
+ );
+
+/******************************************************************************\
+******************************** gcoSURF Object *******************************
+\******************************************************************************/
+
+/* Set cipping rectangle. */
+gceSTATUS
+gcoSURF_SetClipping(
+ IN gcoSURF Surface
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gcoSURF_Clear2D(
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 LoColor,
+ IN gctUINT32 HiColor
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gcoSURF_Line(
+ IN gcoSURF Surface,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+/* Generic rectangular blit. */
+gceSTATUS
+gcoSURF_Blit(
+ IN OPTIONAL gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN OPTIONAL gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN OPTIONAL gceSURF_TRANSPARENCY Transparency,
+ IN OPTIONAL gctUINT32 TransparencyColor,
+ IN OPTIONAL gctPOINTER Mask,
+ IN OPTIONAL gceSURF_MONOPACK MaskPack
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gcoSURF_MonoBlit(
+ IN gcoSURF DestSurface,
+ IN gctPOINTER Source,
+ IN gceSURF_MONOPACK SourcePack,
+ IN gcsPOINT_PTR SourceSize,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Filter blit. */
+gceSTATUS
+gcoSURF_FilterBlit(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gcoSURF_EnableAlphaBlend(
+ IN gcoSURF Surface,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gcoSURF_DisableAlphaBlend(
+ IN gcoSURF Surface
+ );
+
+/* Copy a rectangular area with format conversion. */
+gceSTATUS
+gcoSURF_CopyPixels(
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctINT SourceX,
+ IN gctINT SourceY,
+ IN gctINT TargetX,
+ IN gctINT TargetY,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+/* Read surface pixel. */
+gceSTATUS
+gcoSURF_ReadPixel(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gceSURF_FORMAT Format,
+ OUT gctPOINTER PixelValue
+ );
+
+/* Write surface pixel. */
+gceSTATUS
+gcoSURF_WritePixel(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gceSURF_FORMAT Format,
+ IN gctPOINTER PixelValue
+ );
+
+/******************************************************************************\
+********************************** gco2D Object *********************************
+\******************************************************************************/
+
+/* Construct a new gco2D object. */
+gceSTATUS
+gco2D_Construct(
+ IN gcoHAL Hal,
+ OUT gco2D * Hardware
+ );
+
+/* Destroy an gco2D object. */
+gceSTATUS
+gco2D_Destroy(
+ IN gco2D Hardware
+ );
+
+
+/* Start and end of gco2D draws */
+gceSTATUS
+gco2D_Begin(
+ IN gco2D Engine,
+ IN gctUINT cmdSize
+ );
+
+gceSTATUS
+gco2D_End(
+ IN gco2D Engine
+ );
+
+
+
+/* Sets the maximum number of brushes in the brush cache. */
+gceSTATUS
+gco2D_SetBrushLimit(
+ IN gco2D Hardware,
+ IN gctUINT MaxCount
+ );
+
+/* Flush the brush. */
+gceSTATUS
+gco2D_FlushBrush(
+ IN gco2D Engine,
+ IN gcoBRUSH Brush,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Program the specified solid color brush. */
+gceSTATUS
+gco2D_LoadSolidBrush(
+ IN gco2D Engine,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask
+ );
+
+/* Configure monochrome source. */
+gceSTATUS
+gco2D_SetMonochromeSource(
+ IN gco2D Engine,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_MONOPACK DataPack,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source extension for full rotation. */
+gceSTATUS
+gco2D_SetColorSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSourceAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative
+ );
+
+/* Configure masked color source. */
+gceSTATUS
+gco2D_SetMaskedSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack
+ );
+
+/* Configure masked color source extension for full rotation. */
+gceSTATUS
+gco2D_SetMaskedSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Setup the source rectangle. */
+gceSTATUS
+gco2D_SetSource(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect
+ );
+
+/* Set clipping rectangle. */
+gceSTATUS
+gco2D_SetClipping(
+ IN gco2D Engine,
+ IN gcsRECT_PTR Rect
+ );
+
+/* Configure destination. */
+gceSTATUS
+gco2D_SetTarget(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth
+ );
+
+/* Configure destination extension for full rotation. */
+gceSTATUS
+gco2D_SetTargetEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Calculate and program the stretch factors. */
+gceSTATUS
+gco2D_SetStretchFactors(
+ IN gco2D Engine,
+ IN gctUINT32 HorFactor,
+ IN gctUINT32 VerFactor
+ );
+
+/* Calculate and program the stretch factors based on the rectangles. */
+gceSTATUS
+gco2D_SetStretchRectFactors(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect
+ );
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructSingleColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructMonochromeBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gco2D_Clear(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+gceSTATUS
+gco2D_ClearEx(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gco2D_Line(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines based on the 32-bit color. */
+gceSTATUS
+gco2D_ColorLine(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Generic blit. */
+gceSTATUS
+gco2D_Blit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Batch blit. */
+gceSTATUS
+gco2D_BatchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Stretch blit. */
+gceSTATUS
+gco2D_StretchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gco2D_MonoBlit(
+ IN gco2D Engine,
+ IN gctPOINTER StreamBits,
+ IN gcsPOINT_PTR StreamSize,
+ IN gcsRECT_PTR StreamRect,
+ IN gceSURF_MONOPACK SrcStreamPack,
+ IN gceSURF_MONOPACK DestStreamPack,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 FgRop,
+ IN gctUINT32 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Set kernel size. */
+gceSTATUS
+gco2D_SetKernelSize(
+ IN gco2D Engine,
+ IN gctUINT8 HorKernelSize,
+ IN gctUINT8 VerKernelSize
+ );
+
+/* Set filter type. */
+gceSTATUS
+gco2D_SetFilterType(
+ IN gco2D Engine,
+ IN gceFILTER_TYPE FilterType
+ );
+
+/* Set the filter kernel by user. */
+gceSTATUS
+gco2D_SetUserFilterKernel(
+ IN gco2D Engine,
+ IN gceFILTER_PASS_TYPE PassType,
+ IN gctUINT16_PTR KernelArray
+ );
+
+/* Select the pass(es) to be done for user defined filter. */
+gceSTATUS
+gco2D_EnableUserFilterPasses(
+ IN gco2D Engine,
+ IN gctBOOL HorPass,
+ IN gctBOOL VerPass
+ );
+
+/* Frees the temporary buffer allocated by filter blit operation. */
+gceSTATUS
+gco2D_FreeFilterBuffer(
+ IN gco2D Engine
+ );
+
+/* Filter blit. */
+gceSTATUS
+gco2D_FilterBlit(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Filter blit extension for full rotation. */
+gceSTATUS
+gco2D_FilterBlitEx(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gctUINT32 SrcSurfaceHeight,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gctUINT32 DestSurfaceHeight,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gco2D_EnableAlphaBlend(
+ IN gco2D Engine,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Enable alpha blending engine in the hardware. */
+gceSTATUS
+gco2D_EnableAlphaBlendAdvanced(
+ IN gco2D Engine,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode
+ );
+
+/* Enable alpha blending engine with Porter Duff rule. */
+gceSTATUS
+gco2D_SetPorterDuffBlending(
+ IN gco2D Engine,
+ IN gce2D_PORTER_DUFF_RULE Rule
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gco2D_DisableAlphaBlend(
+ IN gco2D Engine
+ );
+
+/* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
+gctUINT32
+gco2D_GetMaximumDataCount(
+ void
+ );
+
+/* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
+gctUINT32
+gco2D_GetMaximumRectCount(
+ void
+ );
+
+/* Returns the pixel alignment of the surface. */
+gceSTATUS
+gco2D_GetPixelAlignment(
+ gceSURF_FORMAT Format,
+ gcsPOINT_PTR Alignment
+ );
+
+/* Retrieve monochrome stream pack size. */
+gceSTATUS
+gco2D_GetPackSize(
+ IN gceSURF_MONOPACK StreamPack,
+ OUT gctUINT32 * PackWidth,
+ OUT gctUINT32 * PackHeight
+ );
+
+/* Flush the 2D pipeline. */
+gceSTATUS
+gco2D_Flush(
+ IN gco2D Engine
+ );
+
+/* Load 256-entry color table for INDEX8 source surfaces. */
+gceSTATUS
+gco2D_LoadPalette(
+ IN gco2D Engine,
+ IN gctUINT FirstIndex,
+ IN gctUINT IndexCount,
+ IN gctPOINTER ColorTable,
+ IN gctBOOL ColorConvert
+ );
+
+/* Enable/disable 2D BitBlt mirrorring. */
+gceSTATUS
+gco2D_SetBitBlitMirror(
+ IN gco2D Engine,
+ IN gctBOOL HorizontalMirror,
+ IN gctBOOL VerticalMirror
+ );
+
+/* Set the transparency for source, destination and pattern. */
+gceSTATUS
+gco2D_SetTransparencyAdvanced(
+ IN gco2D Engine,
+ IN gce2D_TRANSPARENCY SrcTransparency,
+ IN gce2D_TRANSPARENCY DstTransparency,
+ IN gce2D_TRANSPARENCY PatTransparency
+ );
+
+/* Set the source color key. */
+gceSTATUS
+gco2D_SetSourceColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the source color key range. */
+gceSTATUS
+gco2D_SetSourceColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the target color key. */
+gceSTATUS
+gco2D_SetTargetColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the target color key range. */
+gceSTATUS
+gco2D_SetTargetColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the YUV color space mode. */
+gceSTATUS
+gco2D_SetYUVColorMode(
+ IN gco2D Engine,
+ IN gce2D_YUV_COLOR_MODE Mode
+ );
+
+/* Setup the source global color value in ARGB8 format. */
+gceSTATUS gco2D_SetSourceGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the target global color value in ARGB8 format. */
+gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the source and target pixel multiply modes. */
+gceSTATUS
+gco2D_SetPixelMultiplyModeAdvanced(
+ IN gco2D Engine,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE SrcPremultiplySrcAlpha,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstPremultiplyDstAlpha,
+ IN gce2D_GLOBAL_COLOR_MULTIPLY_MODE SrcPremultiplyGlobalMode,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstDemultiplyDstAlpha
+ );
+
+/* Set the GPU clock cycles after which the idle engine will keep auto-flushing. */
+gceSTATUS
+gco2D_SetAutoFlushCycles(
+ IN gco2D Engine,
+ IN gctUINT32 Cycles
+ );
+
+/* Read the profile registers available in the 2D engine and sets them in the profile.
+ The function will also reset the pixelsRendered counter every time.
+*/
+gceSTATUS
+gco2D_ProfileEngine(
+ IN gco2D Engine,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_raster_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_types.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_types.h
new file mode 100644
index 0000000..34d126a
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/inc/gc_hal_types.h
@@ -0,0 +1,601 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_types_h_
+#define __gc_hal_types_h_
+
+#include "gc_hal_options.h"
+
+#ifdef _WIN32
+#pragma warning(disable:4127) /* Conditional expression is constant (do { }
+ ** while(0)). */
+#pragma warning(disable:4100) /* Unreferenced formal parameter. */
+#pragma warning(disable:4204) /* Non-constant aggregate initializer (C99). */
+#pragma warning(disable:4131) /* Uses old-style declarator (for Bison and
+ ** Flex generated files). */
+#pragma warning(disable:4206) /* Translation unit is empty. */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+** Platform macros.
+*/
+
+#if defined(__GNUC__)
+# define gcdHAS_ELLIPSES 1 /* GCC always has it. */
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define gcdHAS_ELLIPSES 1 /* C99 has it. */
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
+# define gcdHAS_ELLIPSES 1 /* MSVC 2007+ has it. */
+#elif defined(UNDER_CE)
+# define gcdHAS_ELLIPSES 0 /* Windows CE doesn't have it. */
+#else
+# error "gcdHAS_ELLIPSES: Platform could not be determined"
+#endif
+
+/******************************************************************************\
+************************************ Keyword ***********************************
+\******************************************************************************/
+
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
+# define gcmINLINE inline /* C99 keyword. */
+#elif defined(__GNUC__)
+# define gcmINLINE __inline__ /* GNU keyword. */
+#elif defined(_MSC_VER) || defined(UNDER_CE)
+# define gcmINLINE __inline /* Internal keyword. */
+#else
+# error "gcmINLINE: Platform could not be determined"
+#endif
+
+#ifndef gcdDEBUG
+# if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
+# define gcdDEBUG 1
+# else
+# define gcdDEBUG 0
+# endif
+#endif
+
+#ifdef _USRDLL
+# ifdef _MSC_VER
+# ifdef HAL_EXPORTS
+# define HALAPI __declspec(dllexport)
+# else
+# define HALAPI __declspec(dllimport)
+# endif
+# define HALDECL __cdecl
+# else
+# ifdef HAL_EXPORTS
+# define HALAPI
+# else
+# define HALAPI extern
+# endif
+# endif
+#else
+# define HALAPI
+# define HALDECL
+#endif
+
+/******************************************************************************\
+********************************** Common Types ********************************
+\******************************************************************************/
+
+#define gcvFALSE 0
+#define gcvTRUE 1
+
+#define gcvINFINITE ((gctUINT32) ~0U)
+
+typedef int gctBOOL;
+typedef gctBOOL * gctBOOL_PTR;
+
+typedef int gctINT;
+typedef signed char gctINT8;
+typedef signed short gctINT16;
+typedef signed int gctINT32;
+typedef signed long long gctINT64;
+
+typedef gctINT * gctINT_PTR;
+typedef gctINT8 * gctINT8_PTR;
+typedef gctINT16 * gctINT16_PTR;
+typedef gctINT32 * gctINT32_PTR;
+typedef gctINT64 * gctINT64_PTR;
+
+typedef unsigned int gctUINT;
+typedef unsigned char gctUINT8;
+typedef unsigned short gctUINT16;
+typedef unsigned int gctUINT32;
+typedef unsigned long long gctUINT64;
+
+typedef gctUINT * gctUINT_PTR;
+typedef gctUINT8 * gctUINT8_PTR;
+typedef gctUINT16 * gctUINT16_PTR;
+typedef gctUINT32 * gctUINT32_PTR;
+typedef gctUINT64 * gctUINT64_PTR;
+
+typedef unsigned long gctSIZE_T;
+typedef gctSIZE_T * gctSIZE_T_PTR;
+
+#ifdef __cplusplus
+# define gcvNULL 0
+#else
+# define gcvNULL ((void *) 0)
+#endif
+
+typedef float gctFLOAT;
+typedef signed int gctFIXED_POINT;
+typedef float * gctFLOAT_PTR;
+
+typedef void * gctPHYS_ADDR;
+typedef void * gctHANDLE;
+typedef void * gctFILE;
+typedef void * gctSIGNAL;
+typedef void * gctWINDOW;
+typedef void * gctIMAGE;
+
+typedef void * gctPOINTER;
+typedef const void * gctCONST_POINTER;
+
+typedef char gctCHAR;
+typedef char * gctSTRING;
+typedef const char * gctCONST_STRING;
+
+typedef struct _gcsCOUNT_STRING
+{
+ gctSIZE_T Length;
+ gctCONST_STRING String;
+}
+gcsCOUNT_STRING;
+
+/* Fixed point constants. */
+#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
+
+/******************************************************************************\
+******************************* Fixed Point Math *******************************
+\******************************************************************************/
+
+#define gcmXMultiply(x1, x2) \
+ (gctFIXED_POINT) (((gctINT64) (x1) * (x2)) >> 16)
+
+#define gcmXDivide(x1, x2) \
+ (gctFIXED_POINT) ((((gctINT64) (x1)) << 16) / (x2))
+
+#define gcmXMultiplyDivide(x1, x2, x3) \
+ (gctFIXED_POINT) ((gctINT64) (x1) * (x2) / (x3))
+
+/* 2D Engine profile. */
+struct gcs2D_PROFILE
+{
+ /* Cycle count.
+ 32bit counter incremented every 2D clock cycle.
+ Wraps back to 0 when the counter overflows.
+ */
+ gctUINT32 cycleCount;
+
+ /* Pixels rendered by the 2D engine.
+ Resets to 0 every time it is read. */
+ gctUINT32 pixelsRendered;
+};
+
+
+/* Macro to combine four characters into a Charcater Code. */
+#define gcmCC(c1, c2, c3, c4) \
+( \
+ (char) (c1) \
+ | \
+ ((char) (c2) << 8) \
+ | \
+ ((char) (c3) << 16) \
+ | \
+ ((char) (c4) << 24) \
+)
+
+#define gcmPRINTABLE(c) ((((c) >= ' ') && ((c) <= '}')) ? (c) : ' ')
+
+#define gcmCC_PRINT(cc) \
+ gcmPRINTABLE((char) ( (cc) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 8) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 16) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 24) & 0xFF))
+
+/******************************************************************************\
+****************************** Function Parameters *****************************
+\******************************************************************************/
+
+#define IN
+#define OUT
+#define OPTIONAL
+
+/******************************************************************************\
+********************************* Status Codes *********************************
+\******************************************************************************/
+
+typedef enum _gceSTATUS
+{
+ gcvSTATUS_OK = 0,
+ gcvSTATUS_FALSE = 0,
+ gcvSTATUS_TRUE = 1,
+ gcvSTATUS_NO_MORE_DATA = 2,
+ gcvSTATUS_CACHED = 3,
+ gcvSTATUS_MIPMAP_TOO_LARGE = 4,
+ gcvSTATUS_NAME_NOT_FOUND = 5,
+ gcvSTATUS_NOT_OUR_INTERRUPT = 6,
+ gcvSTATUS_MISMATCH = 7,
+ gcvSTATUS_MIPMAP_TOO_SMALL = 8,
+ gcvSTATUS_LARGER = 9,
+ gcvSTATUS_SMALLER = 10,
+ gcvSTATUS_CHIP_NOT_READY = 11,
+ gcvSTATUS_NEED_CONVERSION = 12,
+ gcvSTATUS_SKIP = 13,
+ gcvSTATUS_DATA_TOO_LARGE = 14,
+ gcvSTATUS_INVALID_CONFIG = 15,
+ gcvSTATUS_CHANGED = 16,
+
+ gcvSTATUS_INVALID_ARGUMENT = -1,
+ gcvSTATUS_INVALID_OBJECT = -2,
+ gcvSTATUS_OUT_OF_MEMORY = -3,
+ gcvSTATUS_MEMORY_LOCKED = -4,
+ gcvSTATUS_MEMORY_UNLOCKED = -5,
+ gcvSTATUS_HEAP_CORRUPTED = -6,
+ gcvSTATUS_GENERIC_IO = -7,
+ gcvSTATUS_INVALID_ADDRESS = -8,
+ gcvSTATUS_CONTEXT_LOSSED = -9,
+ gcvSTATUS_TOO_COMPLEX = -10,
+ gcvSTATUS_BUFFER_TOO_SMALL = -11,
+ gcvSTATUS_INTERFACE_ERROR = -12,
+ gcvSTATUS_NOT_SUPPORTED = -13,
+ gcvSTATUS_MORE_DATA = -14,
+ gcvSTATUS_TIMEOUT = -15,
+ gcvSTATUS_OUT_OF_RESOURCES = -16,
+ gcvSTATUS_INVALID_DATA = -17,
+ gcvSTATUS_INVALID_MIPMAP = -18,
+ gcvSTATUS_NOT_FOUND = -19,
+ gcvSTATUS_NOT_ALIGNED = -20,
+ gcvSTATUS_INVALID_REQUEST = -21,
+ gcvSTATUS_GPU_NOT_RESPONDING = -22,
+
+ /* Linker errors. */
+ gcvSTATUS_GLOBAL_TYPE_MISMATCH = -1000,
+ gcvSTATUS_TOO_MANY_ATTRIBUTES = -1001,
+ gcvSTATUS_TOO_MANY_UNIFORMS = -1002,
+ gcvSTATUS_TOO_MANY_VARYINGS = -1003,
+ gcvSTATUS_UNDECLARED_VARYING = -1004,
+ gcvSTATUS_VARYING_TYPE_MISMATCH = -1005,
+ gcvSTATUS_MISSING_MAIN = -1006,
+ gcvSTATUS_NAME_MISMATCH = -1007,
+ gcvSTATUS_INVALID_INDEX = -1008,
+}
+gceSTATUS;
+
+/******************************************************************************\
+********************************* Status Macros ********************************
+\******************************************************************************/
+
+#define gcmIS_ERROR(status) (status < 0)
+#define gcmNO_ERROR(status) (status >= 0)
+#define gcmIS_SUCCESS(status) (status == gcvSTATUS_OK)
+
+/******************************************************************************\
+********************************* Field Macros *********************************
+\******************************************************************************/
+
+#define __gcmSTART(reg_field) \
+ (0 ? reg_field)
+
+#define __gcmEND(reg_field) \
+ (1 ? reg_field)
+
+#define __gcmGETSIZE(reg_field) \
+ (__gcmEND(reg_field) - __gcmSTART(reg_field) + 1)
+
+#define __gcmALIGN(data, reg_field) \
+ (((gctUINT32) (data)) << __gcmSTART(reg_field))
+
+#define __gcmMASK(reg_field) \
+ ((gctUINT32) ((__gcmGETSIZE(reg_field) == 32) \
+ ? ~0 \
+ : (~(~0 << __gcmGETSIZE(reg_field)))))
+
+/*******************************************************************************
+**
+** gcmFIELDMASK
+**
+** Get aligned field mask.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmFIELDMASK(reg, field) \
+( \
+ __gcmALIGN(__gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmGETFIELD
+**
+** Extract the value of a field from specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmGETFIELD(data, reg, field) \
+( \
+ ((((gctUINT32) (data)) >> __gcmSTART(reg##_##field)) \
+ & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELD
+**
+** Set the value of a field within specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETFIELD(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN((gctUINT32) (value) \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELDVALUE
+**
+** Set the value of a field within specified data with a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmSETFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN(reg##_##field##_##value \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmSETMASKEDFIELD
+**
+** Set the value of a masked field with specified data.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETMASKEDFIELD(reg, field, value) \
+( \
+ gcmSETFIELD(~0, reg, field, value) & \
+ gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+** gcmVERIFYFIELDVALUE
+**
+** Verify if the value of a field within specified data equals a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmVERIFYFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) >> __gcmSTART(reg##_##field) & \
+ __gcmMASK(reg##_##field)) \
+ == \
+ (reg##_##field##_##value & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+** Bit field macros.
+*/
+
+#define __gcmSTARTBIT(Field) \
+ ( 1 ? Field )
+
+#define __gcmBITSIZE(Field) \
+ ( 0 ? Field )
+
+#define __gcmBITMASK(Field) \
+( \
+ (1 << __gcmBITSIZE(Field)) - 1 \
+)
+
+#define gcmGETBITS(Value, Type, Field) \
+( \
+ ( ((Type) (Value)) >> __gcmSTARTBIT(Field) ) \
+ & \
+ __gcmBITMASK(Field) \
+)
+
+#define gcmSETBITS(Value, Type, Field, NewValue) \
+( \
+ ( ((Type) (Value)) \
+ & ~(__gcmBITMASK(Field) << __gcmSTARTBIT(Field)) \
+ ) \
+ | \
+ ( ( ((Type) (NewValue)) \
+ & __gcmBITMASK(Field) \
+ ) << __gcmSTARTBIT(Field) \
+ ) \
+)
+
+/******************************************************************************\
+******************************** Min/Max Macros ********************************
+\******************************************************************************/
+
+#define gcmMIN(x, y) (((x) <= (y)) ? (x) : (y))
+#define gcmMAX(x, y) (((x) >= (y)) ? (x) : (y))
+#define gcmCLAMP(x, min, max) (((x) < (min)) ? (min) : \
+ ((x) > (max)) ? (max) : (x))
+#define gcmABS(x) (((x) < 0) ? -(x) : (x))
+#define gcmNEG(x) (((x) < 0) ? (x) : -(x))
+
+
+#define gcmUNALIGNMENT(X) ((gctUINT32)(X) & (sizeof (gctUINT32) - 1))
+
+#define gcmMEMCPY_BYTE(dst,src,size) \
+ {\
+ gctUINT32 i = 0; \
+ for(i = 0; i < size; i++)\
+ {\
+ *((gctUINT8 *)dst+i) = *((gctUINT8*)src+i);\
+ }\
+ }
+
+/* Optimize memory copy.
+ For 4,8,12,16 bytes copy, use unsigned int assignment instead of calling memcopy.
+ ATTENTION: no break in switch branch.
+*/
+#define gcmMEMCPY_DWORD(dst,src,size) \
+ switch(size) \
+ {\
+ case 16:\
+ *((gctUINT32 *)dst + 3) = *((gctUINT32 *)src + 3);\
+ case 12:\
+ *((gctUINT32 *)dst + 2) = *((gctUINT32 *)src + 2);\
+ case 8:\
+ *((gctUINT32 *)dst + 1) = *((gctUINT32 *)src + 1);\
+ case 4:\
+ *((gctUINT32 *)dst) = *((gctUINT32 *)src);\
+ break;\
+ default:\
+ gcmMEMCPY_BYTE(dst,src,size);\
+ break;\
+ }
+
+/*
+ * gcmMEMCPY.
+ *
+ * gcmMEMCPY is for normal size(> 16 bytes) memory copy
+ * gcmMEMCPY_DWORD is for size <=16 bytes
+ * Note: if you do not know the size, just use gcmMEMCPY
+*/
+#define gcmMEMCPY(dst,src,size) \
+ { \
+ gctUINT32 *pDst = (gctUINT32 *)dst; \
+ gctUINT32 *pSrc = (gctUINT32 *)src; \
+ gctUINT32 Size = size; \
+ while(Size >= gcmSIZEOF(gctUINT32) * 4) \
+ { \
+ pDst[0] = pSrc[0]; \
+ pDst[1] = pSrc[1]; \
+ pDst[2] = pSrc[2]; \
+ pDst[3] = pSrc[3]; \
+ pDst += 4; \
+ pSrc += 4; \
+ Size -= (gcmSIZEOF(gctUINT32) * 4); \
+ } \
+ gcmMEMCPY_DWORD(pDst,pSrc,Size) \
+ }
+/*******************************************************************************
+**
+** gcmPTR2INT
+**
+** Convert a pointer to an integer value.
+**
+** ARGUMENTS:
+**
+** p Pointer value.
+*/
+#if defined(_WIN32) || (defined(__LP64__) && __LP64__)
+# define gcmPTR2INT(p) \
+ ( \
+ (gctUINT32) (gctUINT64) (p) \
+ )
+#else
+# define gcmPTR2INT(p) \
+ ( \
+ (gctUINT32) (p) \
+ )
+#endif
+
+/*******************************************************************************
+**
+** gcmINT2PTR
+**
+** Convert an integer value into a pointer.
+**
+** ARGUMENTS:
+**
+** v Integer value.
+*/
+#define gcmINT2PTR(i) \
+( \
+ (gctPOINTER) (i) \
+)
+
+/*******************************************************************************
+**
+** gcmOFFSETOF
+**
+** Compute the byte offset of a field inside a structure.
+**
+** ARGUMENTS:
+**
+** s Structure name.
+** field Field name.
+*/
+#define gcmOFFSETOF(s, field) \
+( \
+ gcmPTR2INT(& (((struct s *) 0)->field)) \
+)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_types_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.c
new file mode 100644
index 0000000..b9fd49a
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.c
@@ -0,0 +1,1288 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_Construct
+**
+** Construct a new gckKERNEL object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN gctPOINTER Context
+** Pointer to a driver defined context.
+**
+** OUTPUT:
+**
+** gckKERNEL * Kernel
+** Pointer to a variable that will hold the pointer to the gckKERNEL
+** object.
+*/
+
+#ifdef ANDROID
+#define DEFAULT_PROFILE_FILE_NAME "/sdcard/vprofiler.xml"
+#else
+#define DEFAULT_PROFILE_FILE_NAME "vprofiler.xml"
+#endif
+
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ OUT gckKERNEL * Kernel
+ )
+{
+ gckKERNEL kernel = gcvNULL;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+
+ /* Allocate the gckKERNEL object. */
+ gcmkONERROR(
+ gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckKERNEL),
+ (gctPOINTER *) &kernel));
+#if MRVL_LOW_POWER_MODE_DEBUG
+ gcmERR_RETURN(
+ gckOS_Allocate(Os, 0x1000000, (gctPOINTER *) &kernel->kernelMSG));
+
+ kernel->msgLen = 0;
+#endif
+
+ /* Zero the object pointers. */
+ kernel->hardware = gcvNULL;
+ kernel->command = gcvNULL;
+ kernel->event = gcvNULL;
+ kernel->mmu = gcvNULL;
+
+ /* Initialize the gckKERNEL object. */
+ kernel->object.type = gcvOBJ_KERNEL;
+ kernel->os = Os;
+
+ /* Save context. */
+ kernel->context = Context;
+
+ /* Construct atom holding number of clients. */
+ kernel->atomClients = gcvNULL;
+ gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
+#if gcdSECURE_USER
+ kernel->cacheSlots = 0;
+ kernel->cacheTimeStamp = 0;
+#endif
+
+ /* Construct the gckHARDWARE object. */
+ gcmkONERROR(
+ gckHARDWARE_Construct(Os, &kernel->hardware));
+
+ /* Set pointer to gckKERNEL object in gckHARDWARE object. */
+ kernel->hardware->kernel = kernel;
+
+ /* Initialize the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_InitializeHardware(kernel->hardware));
+
+ /* Construct the gckCOMMAND object. */
+ gcmkONERROR(
+ gckCOMMAND_Construct(kernel, &kernel->command));
+
+ /* Construct the gckEVENT object. */
+ gcmkONERROR(
+ gckEVENT_Construct(kernel, &kernel->event));
+
+ /* Construct the gckMMU object. */
+ gcmkONERROR(
+ gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
+ kernel->notifyIdle = gcvTRUE; /* gcvFALSE; */
+
+#if VIVANTE_PROFILER
+ /* Initialize profile setting */
+#if defined ANDROID
+ kernel->profileEnable = gcvFALSE;
+#else
+ kernel->profileEnable = gcvTRUE;
+#endif
+
+ gcmkVERIFY_OK(
+ gckOS_MemCopy(kernel->profileFileName,
+ DEFAULT_PROFILE_FILE_NAME,
+ gcmSIZEOF(DEFAULT_PROFILE_FILE_NAME) + 1));
+#endif
+
+ /* Return pointer to the gckKERNEL object. */
+ *Kernel = kernel;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (kernel != gcvNULL)
+ {
+ if (kernel->event != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_Destroy(kernel->event));
+ kernel->event = gcvNULL;
+ }
+
+ if (kernel->command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel->command));
+ kernel->command = gcvNULL;
+ }
+
+ if (kernel->hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel->hardware));
+ kernel->hardware = gcvNULL;
+ }
+
+ if (kernel->atomClients != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
+ kernel->atomClients = gcvNULL;
+ }
+
+ kernel->version = _GC_VERSION_STRING_;
+
+#if MRVL_LOW_POWER_MODE_DEBUG
+ gcmkVERIFY_OK(
+ gckOS_Free(Os, kernel->kernelMSG));
+ kernel->kernelMSG = gcvNULL;
+#endif
+ gcmkVERIFY_OK(gckOS_Free(Os, kernel));
+ kernel = gcvNULL;
+ }
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Destroy
+**
+** Destroy an gckKERNEL object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ )
+{
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+
+
+ /* Destroy the gckMMU object. */
+ if(Kernel->mmu != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
+ Kernel->mmu = gcvNULL;
+ }
+
+ /* Destroy the gckEVENT object. */
+ if(Kernel->event != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->event));
+ Kernel->event = gcvNULL;
+ }
+
+ /* Destroy the gckCOMMNAND object. */
+ if(Kernel->command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
+ Kernel->command = gcvNULL;
+ }
+
+ /* Destroy the gckHARDWARE object. */
+ if(Kernel->hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
+ Kernel->hardware = gcvNULL;
+ }
+
+ /* Detsroy the client atom. */
+ if(Kernel->atomClients != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
+ Kernel->atomClients = gcvNULL;
+ }
+ /* Mark the gckKERNEL object as unknown. */
+ Kernel->object.type = gcvOBJ_UNKNOWN;
+
+#if MRVL_LOW_POWER_MODE_DEBUG
+ gcmkVERIFY_OK(
+ gckOS_Free(Kernel->os, Kernel->kernelMSG));
+ Kernel->kernelMSG = gcvNULL;
+#endif
+ /* Free the gckKERNEL object. */
+ gcmkVERIFY_OK(gckOS_Free(Kernel->os, Kernel));
+ Kernel = gcvNULL;
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** _AllocateMemory
+**
+** Private function to walk all required memory pools to allocate the requested
+** amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+static gceSTATUS
+_AllocateMemory(
+ IN gckKERNEL Kernel,
+ IN OUT gcePOOL * Pool,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gcePOOL pool;
+ gceSTATUS status;
+ gckVIDMEM videoMemory;
+
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+
+ /* Get initial pool. */
+ switch (pool = *Pool)
+ {
+ case gcvPOOL_DEFAULT:
+ case gcvPOOL_LOCAL:
+ pool = gcvPOOL_LOCAL_INTERNAL;
+ break;
+
+ case gcvPOOL_UNIFIED:
+ pool = gcvPOOL_SYSTEM;
+ break;
+
+ default:
+ break;
+ }
+
+ do
+ {
+ /* Verify the number of bytes to allocate. */
+ if (Bytes == 0)
+ {
+ gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (pool == gcvPOOL_VIRTUAL)
+ {
+ /* Create a gcuVIDMEM_NODE for virtual memory. */
+#ifdef __QNXNTO__
+ gcmkERR_BREAK(
+ gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Handle, Node));
+#else
+ gcmkERR_BREAK(
+ gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
+#endif
+
+ /* Success. */
+ break;
+ }
+ else if (pool == gcvPOOL_CONTIGUOUS)
+ {
+ /* Create a gcuVIDMEM_NODE for contiguous memory. */
+#ifdef __QNXNTO__
+ status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Handle, Node);
+#else
+ status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Node);
+#endif
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Memory allocated. */
+ break;
+ }
+ }
+ else
+ {
+ /* Get pointer to gckVIDMEM object for pool. */
+ status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Allocate memory. */
+ status = gckVIDMEM_AllocateLinear(videoMemory,
+ Bytes,
+ Alignment,
+ Type,
+#ifdef __QNXNTO__
+ Handle,
+#endif
+ Node);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Memory allocated. */
+ (*Node)->VidMem.pool = pool;
+ break;
+ }
+ }
+ }
+
+ if (pool == gcvPOOL_LOCAL_INTERNAL)
+ {
+ /* Advance to external memory. */
+ pool = gcvPOOL_LOCAL_EXTERNAL;
+ }
+ else
+ if (pool == gcvPOOL_LOCAL_EXTERNAL)
+ {
+ /* Advance to contiguous system memory. */
+ pool = gcvPOOL_SYSTEM;
+ }
+ else
+ if (pool == gcvPOOL_SYSTEM)
+ {
+ /* Advance to contiguous memory. */
+ pool = gcvPOOL_CONTIGUOUS;
+ }
+ else
+ if ((pool == gcvPOOL_CONTIGUOUS)
+ && (Type != gcvSURF_TILE_STATUS)
+ )
+ {
+ static int count= 1;
+ /* Advance to virtual memory. */
+ if (count == 1)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Try to allocate virtual memory!\n");
+ count = 0;
+ }
+ pool = gcvPOOL_VIRTUAL;
+ }
+ else
+ {
+ /* Out of pools. */
+ break;
+ }
+ }
+ /* Loop only for multiple selection pools. */
+ while ((*Pool == gcvPOOL_DEFAULT)
+ || (*Pool == gcvPOOL_LOCAL)
+ || (*Pool == gcvPOOL_UNIFIED)
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Return pool used for allocation. */
+ *Pool = pool;
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Dispatch
+**
+** Dispatch a command received from the user HAL layer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL FromUser
+** whether the call is from the user space.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gctUINT32 bitsPerPixel;
+ gctSIZE_T bytes;
+ gcuVIDMEM_NODE_PTR node;
+ gctBOOL locked = gcvFALSE;
+ gctPHYS_ADDR physical;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
+ Kernel, FromUser, Interface);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Dispatching command %d", Interface->command);
+
+ /* Dispatch on command. */
+ switch (Interface->command)
+ {
+ case gcvHAL_GET_BASE_ADDRESS:
+ /* Get base address. */
+ gcmkONERROR(
+ gckOS_GetBaseAddress(Kernel->os,
+ &Interface->u.GetBaseAddress.baseAddress));
+ break;
+
+ case gcvHAL_QUERY_VIDEO_MEMORY:
+ /* Query video memory size. */
+ gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
+ break;
+
+ case gcvHAL_QUERY_CHIP_IDENTITY:
+ /* Query chip identity. */
+ gcmkONERROR(
+ gckHARDWARE_QueryChipIdentity(
+ Kernel->hardware,
+ &Interface->u.QueryChipIdentity.chipModel,
+ &Interface->u.QueryChipIdentity.chipRevision,
+ &Interface->u.QueryChipIdentity.chipFeatures,
+ &Interface->u.QueryChipIdentity.chipMinorFeatures,
+ &Interface->u.QueryChipIdentity.chipMinorFeatures1));
+
+ /* Query chip specifications. */
+ gcmkONERROR(
+ gckHARDWARE_QueryChipSpecs(
+ Kernel->hardware,
+ &Interface->u.QueryChipIdentity.streamCount,
+ &Interface->u.QueryChipIdentity.registerMax,
+ &Interface->u.QueryChipIdentity.threadCount,
+ &Interface->u.QueryChipIdentity.shaderCoreCount,
+ &Interface->u.QueryChipIdentity.vertexCacheSize,
+ &Interface->u.QueryChipIdentity.vertexOutputBufferSize));
+ break;
+
+ case gcvHAL_MAP_MEMORY:
+ physical = Interface->u.MapMemory.physical;
+
+ /* Map memory. */
+ gcmkONERROR(
+ gckKERNEL_MapMemory(Kernel,
+ physical,
+ Interface->u.MapMemory.bytes,
+ &Interface->u.MapMemory.logical));
+ break;
+
+ case gcvHAL_UNMAP_MEMORY:
+ physical = Interface->u.UnmapMemory.physical;
+
+ /* Unmap memory. */
+ gcmkONERROR(
+ gckKERNEL_UnmapMemory(Kernel,
+ physical,
+ Interface->u.UnmapMemory.bytes,
+ Interface->u.UnmapMemory.logical));
+ break;
+
+ case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+ /* Allocate non-paged memory. */
+#ifdef __QNXNTO__
+ if (FromUser)
+ {
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemoryShmPool(
+ Kernel->os,
+ FromUser,
+ Interface->pid,
+ Interface->handle,
+ &Interface->u.AllocateNonPagedMemory.bytes,
+ &Interface->u.AllocateNonPagedMemory.physical,
+ &Interface->u.AllocateNonPagedMemory.logical));
+ break;
+ }
+#endif
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemory(
+ Kernel->os,
+ FromUser,
+ &Interface->u.AllocateNonPagedMemory.bytes,
+ &Interface->u.AllocateNonPagedMemory.physical,
+ &Interface->u.AllocateNonPagedMemory.logical));
+ break;
+
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ physical = Interface->u.FreeNonPagedMemory.physical;
+
+ /* Free non-paged memory. */
+ gcmkONERROR(
+ gckOS_FreeNonPagedMemory(Kernel->os,
+ Interface->u.FreeNonPagedMemory.bytes,
+ physical,
+ Interface->u.FreeNonPagedMemory.logical));
+ break;
+
+ case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+ /* Allocate contiguous memory. */
+#ifdef __QNXNTO__
+ if (FromUser)
+ {
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemoryShmPool(
+ Kernel->os,
+ FromUser,
+ Interface->pid,
+ Interface->handle,
+ &Interface->u.AllocateNonPagedMemory.bytes,
+ &Interface->u.AllocateNonPagedMemory.physical,
+ &Interface->u.AllocateNonPagedMemory.logical));
+ break;
+ }
+#endif
+ gcmkONERROR(
+ gckOS_AllocateContiguous(
+ Kernel->os,
+ FromUser,
+ &Interface->u.AllocateContiguousMemory.bytes,
+ &Interface->u.AllocateContiguousMemory.physical,
+ &Interface->u.AllocateContiguousMemory.logical));
+
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ physical = Interface->u.FreeContiguousMemory.physical;
+
+ /* Free contiguous memory. */
+ gcmkONERROR(
+ gckOS_FreeContiguous(Kernel->os,
+ physical,
+ Interface->u.FreeContiguousMemory.logical,
+ Interface->u.FreeContiguousMemory.bytes));
+ break;
+
+ case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+ /* Align width and height to tiles. */
+ gcmkONERROR(
+ gckHARDWARE_AlignToTile(Kernel->hardware,
+ Interface->u.AllocateVideoMemory.type,
+ &Interface->u.AllocateVideoMemory.width,
+ &Interface->u.AllocateVideoMemory.height,
+ gcvNULL));
+
+ /* Convert format into bytes per pixel and bytes per tile. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertFormat(Kernel->hardware,
+ Interface->u.AllocateVideoMemory.format,
+ &bitsPerPixel,
+ gcvNULL));
+
+ /* Compute number of bytes for the allocation. */
+ bytes = Interface->u.AllocateVideoMemory.width * bitsPerPixel
+ * Interface->u.AllocateVideoMemory.height
+ * Interface->u.AllocateVideoMemory.depth / 8;
+
+ /* Allocate memory. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateVideoMemory.pool,
+ bytes,
+ 64,
+ Interface->u.AllocateVideoMemory.type,
+ Interface->handle,
+ &Interface->u.AllocateVideoMemory.node));
+#else
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateVideoMemory.pool,
+ bytes,
+ 64,
+ Interface->u.AllocateVideoMemory.type,
+ &Interface->u.AllocateVideoMemory.node));
+#endif
+ break;
+
+ case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+ /* Allocate memory. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateLinearVideoMemory.pool,
+ Interface->u.AllocateLinearVideoMemory.bytes,
+ Interface->u.AllocateLinearVideoMemory.alignment,
+ Interface->u.AllocateLinearVideoMemory.type,
+ Interface->handle,
+ &Interface->u.AllocateLinearVideoMemory.node));
+
+ /* Set the current user pid in the node,
+ * which is used while locking memory. */
+ gcmkVERIFY_OK(gckVIDMEM_SetPID(
+ Interface->u.AllocateLinearVideoMemory.node,
+ Interface->pid));
+#else
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateLinearVideoMemory.pool,
+ Interface->u.AllocateLinearVideoMemory.bytes,
+ Interface->u.AllocateLinearVideoMemory.alignment,
+ Interface->u.AllocateLinearVideoMemory.type,
+ &Interface->u.AllocateLinearVideoMemory.node));
+#endif
+ break;
+
+ case gcvHAL_FREE_VIDEO_MEMORY:
+#ifdef __QNXNTO__
+ node = Interface->u.FreeVideoMemory.node;
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM
+ && node->VidMem.logical != gcvNULL)
+ {
+ gcmkONERROR(
+ gckKERNEL_UnmapVideoMemory(Kernel,
+ node->VidMem.logical,
+ Interface->pid,
+ node->VidMem.bytes));
+ node->VidMem.logical = gcvNULL;
+ }
+#endif
+ /* Free video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Free(Interface->u.FreeVideoMemory.node));
+ break;
+
+ case gcvHAL_LOCK_VIDEO_MEMORY:
+ /* Lock video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Lock(Interface->u.LockVideoMemory.node,
+ &Interface->u.LockVideoMemory.address));
+
+ locked = gcvTRUE;
+
+ node = Interface->u.LockVideoMemory.node;
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ /* Map video memory address into user space. */
+#ifdef __QNXNTO__
+ if (node->VidMem.logical == gcvNULL)
+ {
+ gcmkONERROR(
+ gckKERNEL_MapVideoMemory(Kernel,
+ FromUser,
+ Interface->u.LockVideoMemory.address,
+ Interface->pid,
+ node->VidMem.bytes,
+ &node->VidMem.logical));
+ }
+ Interface->u.LockVideoMemory.memory = node->VidMem.logical;
+#else
+ gcmkONERROR(
+ gckKERNEL_MapVideoMemory(Kernel,
+ FromUser,
+ Interface->u.LockVideoMemory.address,
+ &Interface->u.LockVideoMemory.memory));
+#endif
+
+#ifdef __QNXNTO__
+ /* Add more information to node, which is used while unmapping. */
+ gcmkVERIFY_OK(gckVIDMEM_SetPID(
+ Interface->u.LockVideoMemory.node,
+ Interface->pid));
+#endif
+ }
+
+ else
+ {
+ /* Copy logical memory for virtual memory. */
+ Interface->u.LockVideoMemory.memory = node->Virtual.logical;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+
+#if gcdSECURE_USER
+ /* Return logical address as physical address. */
+ Interface->u.LockVideoMemory.address =
+ gcmPTR2INT(Interface->u.LockVideoMemory.memory);
+#endif
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ /* Unlock video memory. */
+ node = Interface->u.UnlockVideoMemory.node;
+
+ /* Unlock video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Unlock(node,
+ Interface->u.UnlockVideoMemory.type,
+ &Interface->u.UnlockVideoMemory.asynchroneous));
+ break;
+
+ case gcvHAL_EVENT_COMMIT:
+ /* Commit an event queue. */
+ gcmkONERROR(
+ gckEVENT_Commit(Kernel->event,
+ Interface->u.Event.queue));
+ break;
+
+ case gcvHAL_COMMIT:
+ /* Commit a command and context buffer. */
+ gcmkONERROR(
+ gckCOMMAND_Commit(Kernel->command,
+ Interface->u.Commit.commandBuffer,
+ Interface->u.Commit.contextBuffer,
+ Interface->u.Commit.process));
+ break;
+
+ case gcvHAL_STALL:
+ /* Stall the command queue. */
+ gcmkONERROR(gckCOMMAND_Stall(Kernel->command));
+ break;
+
+ case gcvHAL_MAP_USER_MEMORY:
+ /* Map user memory to DMA. */
+ gcmkONERROR(
+ gckOS_MapUserMemory(Kernel->os,
+ Interface->u.MapUserMemory.memory,
+ Interface->u.MapUserMemory.size,
+ &Interface->u.MapUserMemory.info,
+ &Interface->u.MapUserMemory.address));
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ address = Interface->u.MapUserMemory.address;
+
+ /* Unmap user memory. */
+ gcmkONERROR(
+ gckOS_UnmapUserMemory(Kernel->os,
+ Interface->u.UnmapUserMemory.memory,
+ Interface->u.UnmapUserMemory.size,
+ Interface->u.UnmapUserMemory.info,
+ address));
+ break;
+
+#if !USE_NEW_LINUX_SIGNAL
+ case gcvHAL_USER_SIGNAL:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Dispatching gcvHAL_USER_SIGNAL %d", Interface->u.UserSignal.command);
+ /* 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.signalType,
+ &Interface->u.UserSignal.id));
+ break;
+
+ case gcvUSER_SIGNAL_DESTROY:
+ /* Destroy the signal. */
+ gcmkONERROR(
+ gckOS_DestroyUserSignal(Kernel->os,
+ Interface->u.UserSignal.id));
+ break;
+
+ case gcvUSER_SIGNAL_SIGNAL:
+ /* Signal the signal. */
+ gcmkONERROR(
+ gckOS_SignalUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.state));
+ break;
+
+ case gcvUSER_SIGNAL_WAIT:
+ /* Wait on the signal. */
+ status = gckOS_WaitUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.wait);
+ break;
+
+ default:
+ /* Invalid user signal command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ break;
+#endif
+
+ case gcvHAL_SET_POWER_MANAGEMENT_STATE:
+ /* Set the power management state. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(
+ Kernel->hardware,
+ Interface->u.SetPowerManagement.state));
+ break;
+
+ case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
+ /* Chip is not idle. */
+ Interface->u.QueryPowerManagement.isIdle = gcvFALSE;
+
+ /* Query the power management state. */
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+ Kernel->hardware,
+ &Interface->u.QueryPowerManagement.state));
+
+ /* Query the idle state. */
+ gcmkONERROR(
+ gckHARDWARE_QueryIdle(Kernel->hardware,
+ &Interface->u.QueryPowerManagement.isIdle));
+ break;
+
+ case gcvHAL_READ_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ /* Read a register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Kernel->os,
+ Interface->u.ReadRegisterData.address,
+ &Interface->u.ReadRegisterData.data));
+#else
+ /* No access from user land to read registers. */
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_WRITE_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ /* Write a register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Kernel->os,
+ Interface->u.WriteRegisterData.address,
+ Interface->u.WriteRegisterData.data));
+#else
+ /* No access from user land to write registers. */
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_READ_ALL_PROFILE_REGISTERS:
+#if VIVANTE_PROFILER
+ /* Read all 3D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_QueryProfileRegisters(
+ Kernel->hardware,
+ &Interface->u.RegisterProfileData.counters));
+#else
+ status = gcvSTATUS_OK;
+#endif
+ break;
+
+ case gcvHAL_PROFILE_REGISTERS_2D:
+#if VIVANTE_PROFILER
+ /* Read all 2D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_ProfileEngine2D(
+ Kernel->hardware,
+ Interface->u.RegisterProfileData2D.hwProfile2D));
+#else
+ status = gcvSTATUS_OK;
+#endif
+ break;
+
+ case gcvHAL_GET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+ /* Get profile setting */
+ Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
+
+ gcmkVERIFY_OK(
+ gckOS_MemCopy(Interface->u.GetProfileSetting.fileName,
+ Kernel->profileFileName,
+ gcdMAX_PROFILE_FILE_NAME));
+#endif
+
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_SET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+ /* Set profile setting */
+ Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
+
+ gcmkVERIFY_OK(
+ gckOS_MemCopy(Kernel->profileFileName,
+ Interface->u.SetProfileSetting.fileName,
+ gcdMAX_PROFILE_FILE_NAME));
+#endif
+
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_QUERY_KERNEL_SETTINGS:
+ /* Get kernel settings. */
+ gcmkONERROR(
+ gckKERNEL_QuerySettings(Kernel,
+ &Interface->u.QueryKernelSettings.settings));
+ break;
+
+ case gcvHAL_RESET:
+ /* Reset the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_Reset(Kernel->hardware));
+ break;
+
+ case gcvHAL_DEBUG:
+ /* Set debug level and zones. */
+ if (Interface->u.Debug.set)
+ {
+ gckOS_SetDebugLevel(Interface->u.Debug.level);
+ gckOS_SetDebugZones(Interface->u.Debug.zones,
+ Interface->u.Debug.enable);
+ }
+
+ if (Interface->u.Debug.message[0] != '\0')
+ {
+ /* Print a message to the debugger. */
+ gcmkPRINT(Interface->u.Debug.message);
+ }
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_CACHE:
+ if (Interface->u.Cache.invalidate)
+ {
+ /* Flush and invalidate the cache. */
+ status = gckOS_CacheInvalidate(Kernel->os,
+ Interface->u.Cache.process,
+ Interface->u.Cache.logical,
+ Interface->u.Cache.bytes);
+ }
+ else
+ {
+ /* Flush the cache. */
+ status = gckOS_CacheFlush(Kernel->os,
+ Interface->u.Cache.process,
+ Interface->u.Cache.logical,
+ Interface->u.Cache.bytes);
+ }
+ break;
+
+ default:
+ /* Invalid command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+OnError:
+ /* Save status. */
+ Interface->status = status;
+
+ if (gcmIS_ERROR(status))
+ {
+ if (locked)
+ {
+ /* Roll back the lock. */
+ gcmkVERIFY_OK(
+ gckVIDMEM_Unlock(Interface->u.LockVideoMemory.node,
+ gcvSURF_TYPE_UNKNOWN,
+ gcvNULL));
+ }
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ )
+{
+ gceSTATUS status;
+ gctINT32 old;
+
+ gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (Attach)
+ {
+ /* Increment the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 0)
+ {
+ /* gcmkONERROR(gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_ON)); */
+ }
+ }
+
+ else
+ {
+ /* Decrement the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 1)
+ {
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_OFF));
+
+ /* Flush the debug cache. */
+ gcmkPRINT("$$FLUSH$$");
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gctHANDLE Process,
+ IN OUT gctPOINTER * Data
+ )
+{
+ gctUINT i, oldest;
+ gceSTATUS status;
+ gctUINT32 baseAddress;
+
+ gcmkHEADER_ARG("Kernel=0x%x Process=0x%x *Data=0x%x",
+ Kernel, Process, gcmOPT_POINTER(Data));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ /* Get base address. */
+ gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
+
+ /* Walk all used cache slots. */
+ for (i = oldest = 0; i < Kernel->cacheSlots; ++i)
+ {
+ if ((Kernel->cache[i].logical == *Data)
+ && (Kernel->cache[i].process == Process)
+ )
+ {
+ /* Bail out. */
+ break;
+ }
+
+ if (i == 0)
+ {
+ /* First slot. */
+ oldest = i;
+ }
+
+ /* Test if this cache slot is older. */
+ else if (Kernel->cache[i].stamp < Kernel->cache[oldest].stamp)
+ {
+ oldest = i;
+ }
+ }
+
+ /* See if we had a match. */
+ if (i == Kernel->cacheSlots)
+ {
+ /* See if there is room in the cache. */
+ if (i < gcmCOUNTOF(Kernel->cache))
+ {
+ /* Just append to the cache. */
+ i = Kernel->cacheSlots++;
+ }
+
+ else
+ {
+ /* Evict the oldest cache line. */
+ i = oldest;
+ }
+
+ /* Initialize the cache line. */
+ Kernel->cache[i].logical = *Data;
+ Kernel->cache[i].process = Process;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os,
+ *Data,
+ &Kernel->cache[i].dma));
+
+ if (baseAddress != 0)
+ {
+ gctBOOL needBase;
+
+ /* Does this state load need a base address? */
+ gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
+ ((gctUINT32_PTR) Data)[-1],
+ &needBase));
+
+ if (needBase)
+ {
+ /* Add the base address. */
+ Kernel->cache[i].dma += baseAddress;
+ }
+ }
+ }
+
+ /* Increment time stamp of the cache slot. */
+ Kernel->cache[i].stamp = Kernel->cacheTimeStamp++;
+
+ /* Return DMA address. */
+ *Data = gcmINT2PTR(Kernel->cache[i].dma);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckKERNEL_Recovery
+**
+** Try to recover the GPU from a fatal error.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+ IN gckKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+ gckEVENT event;
+ gckHARDWARE hardware;
+#if gcdSECURE_USER
+ gctUINT32 processID;
+#endif
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Validate the arguemnts. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Grab gckEVENT object. */
+ event = Kernel->event;
+ gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+ /* Grab gckHARDWARE object. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Handle all outstanding events now. */
+ event->pending = ~0U;
+ gcmkONERROR(gckEVENT_Notify(event, 1));
+
+ /* Again in case more events got submitted. */
+ event->pending = ~0U;
+ gcmkONERROR(gckEVENT_Notify(event, 2));
+
+#if gcdSECURE_USER
+ /* Flush the secure mapping cache. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+ gcmkONERROR(gckKERNEL_MapLogicalToPhysical(Kernel, processID, gcvNULL));
+#endif
+
+ /* Try issuing a soft reset for the GPU. */
+ status = gckHARDWARE_Reset(hardware);
+ if (status == gcvSTATUS_NOT_SUPPORTED)
+ {
+ /* Switch to OFF power. The next submit should return the GPU to ON
+ ** state. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(hardware,
+ gcvPOWER_OFF_RECOVERY));
+ }
+ else
+ {
+ /* Bail out on reset error. */
+ gcmkONERROR(status);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.h
new file mode 100644
index 0000000..8daa449
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel.h
@@ -0,0 +1,427 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_h_
+#define __gc_hal_kernel_h_
+
+#include "gc_hal.h"
+#include "gc_hal_kernel_hardware.h"
+#include "gc_hal_driver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+#if gcdSECURE_USER
+typedef struct _gckLOGICAL_CACHE
+{
+ gctHANDLE process;
+ gctPOINTER logical;
+ gctUINT32 dma;
+ gctUINT64 stamp;
+}
+gckLOGICAL_CACHE;
+#endif
+
+/* gckKERNEL object. */
+struct _gckKERNEL
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* Pointer to gckCOMMAND object. */
+ gckCOMMAND command;
+
+ /* Pointer to gckEVENT object. */
+ gckEVENT event;
+
+ /* Pointer to context. */
+ gctPOINTER context;
+
+ /* Pointer to gckMMU object. */
+ gckMMU mmu;
+
+ /* Arom holding number of clients. */
+ gctPOINTER atomClients;
+
+ /* Require to notify idle status */
+ gctBOOL notifyIdle;
+
+#if VIVANTE_PROFILER
+ /* Enable profiling */
+ gctBOOL profileEnable;
+
+ /* The profile file name */
+ gctCHAR profileFileName[gcdMAX_PROFILE_FILE_NAME];
+#endif
+
+#if gcdSECURE_USER
+ gckLOGICAL_CACHE cache[gcdSECURE_CACHE_SLOTS];
+ gctUINT cacheSlots;
+ gctUINT64 cacheTimeStamp;
+#endif
+ /* Pointer to reversion string */
+ gctCONST_STRING version;
+
+#if MRVL_LOW_POWER_MODE_DEBUG
+ /* The buffer to pool the output message before entering D2
+ ** these message can be output after exiting D2
+ */
+ char* kernelMSG;
+ /* The length of kernelMSG */
+ gctINT32 msgLen;
+#endif
+};
+
+#define gcdCOMMAND_QUEUES 2
+
+/* gckCOMMAND object. */
+struct _gckCOMMAND
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to required object. */
+ gckKERNEL kernel;
+ gckOS os;
+
+ /* Number of bytes per page. */
+ gctSIZE_T pageSize;
+
+ /* Current pipe select. */
+ gctUINT32 pipeSelect;
+
+ /* Command queue running flag. */
+ gctBOOL running;
+
+ /* Idle flag and commit stamp. */
+ gctBOOL idle;
+ gctUINT64 commitStamp;
+
+ /* Command queue mutex. */
+ gctPOINTER mutexQueue;
+
+ /* Context switching mutex. */
+ gctPOINTER mutexContext;
+
+ /* Command queue power semaphore. */
+ gctPOINTER powerSemaphore;
+
+ /* Current command queue. */
+ struct _gcskCOMMAND_QUEUE
+ {
+ gctSIGNAL signal;
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ }
+ queues[gcdCOMMAND_QUEUES];
+
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ gctINT index;
+ gctUINT32 offset;
+
+ /* The command queue is new. */
+ gctBOOL newQueue;
+ gctBOOL submit;
+
+ /* Context counter used for unique ID. */
+ gctUINT64 contextCounter;
+
+ /* Current context ID. */
+ gctUINT64 currentContext;
+
+ /* Pointer to last WAIT command. */
+ gctPOINTER wait;
+ gctSIZE_T waitSize;
+
+ /* Command buffer alignment. */
+ gctSIZE_T alignment;
+ gctSIZE_T reservedHead;
+ gctSIZE_T reservedTail;
+
+ /* Commit counter. */
+ gctPOINTER atomCommit;
+
+ /* Dump command buffer and link chain when GC hangs */
+ gctBOOL dumpCmdBuf;
+};
+
+typedef struct _gcsEVENT * gcsEVENT_PTR;
+
+/* Structure holding one event to be processed. */
+typedef struct _gcsEVENT
+{
+ /* Pointer to next event in queue. */
+ gcsEVENT_PTR next;
+
+ /* Event information. */
+ gcsHAL_INTERFACE event;
+
+#ifdef __QNXNTO__
+ /* Kernel. */
+ gckKERNEL kernel;
+#endif
+}
+gcsEVENT;
+
+/* Structure holding a list of events to be processed by an interrupt. */
+typedef struct _gcsEVENT_QUEUE
+{
+ /* Time stamp. */
+ gctUINT64 stamp;
+
+ /* Source of the event. */
+ gceKERNEL_WHERE source;
+
+ /* Pointer to head of event queue. */
+ gcsEVENT_PTR head;
+
+ /* Pointer to tail of event queue. */
+ gcsEVENT_PTR tail;
+
+ /* Process ID owning the event queue. */
+ gctUINT32 processID;
+}
+gcsEVENT_QUEUE;
+
+/* gckEVENT object. */
+struct _gckEVENT
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to required objects. */
+ gckOS os;
+ gckKERNEL kernel;
+
+ /* Time stamp. */
+ gctUINT64 stamp;
+ gctUINT64 lastCommitStamp;
+
+ /* Queue mutex. */
+ gctPOINTER mutexQueue;
+
+ /* Event counter */
+ gctPOINTER atomEventRef;
+
+ /* Array of event queues. */
+ gcsEVENT_QUEUE queues[31];
+ gctUINT8 lastID;
+
+ /* Pending events. */
+ volatile gctUINT pending;
+
+ /* List of free event structures and its mutex. */
+ gcsEVENT_PTR freeList;
+ gctSIZE_T freeCount;
+ gctPOINTER freeMutex;
+
+ /* Events queued to be added to an event queue and its mutex. */
+ gcsEVENT_QUEUE list;
+ gctPOINTER listMutex;
+};
+
+/* gcuVIDMEM_NODE structure. */
+typedef union _gcuVIDMEM_NODE
+{
+ /* Allocated from gckVIDMEM. */
+ struct _gcsVIDMEM_NODE_VIDMEM
+ {
+ /* Owner of this node. */
+ gckVIDMEM memory;
+
+ /* Dual-linked list of nodes. */
+ gcuVIDMEM_NODE_PTR next;
+ gcuVIDMEM_NODE_PTR prev;
+
+ /* Dual linked list of free nodes. */
+ gcuVIDMEM_NODE_PTR nextFree;
+ gcuVIDMEM_NODE_PTR prevFree;
+
+ /* Information for this node. */
+ gctUINT32 offset;
+ gctSIZE_T bytes;
+ gctUINT32 alignment;
+
+#ifdef __QNXNTO__
+ /* Client/server vaddr (mapped using mmap_join). */
+ gctPOINTER logical;
+
+ /* Unique handle of the caller process channel. */
+ gctHANDLE handle;
+#endif
+
+ /* Locked counter. */
+ gctINT32 locked;
+
+ /* Memory pool. */
+ gcePOOL pool;
+ gctUINT32 physical;
+ }
+ VidMem;
+
+ /* Allocated from gckOS. */
+ struct _gcsVIDMEM_NODE_VIRTUAL
+ {
+ /* Pointer to gckKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Information for this node. */
+ gctBOOL contiguous;
+ gctPHYS_ADDR physical;
+ gctSIZE_T bytes;
+ gctPOINTER logical;
+
+ /* Page table information. */
+ gctSIZE_T pageCount;
+ gctPOINTER pageTable;
+ gctUINT32 address;
+
+ /* Mutex. */
+ gctPOINTER mutex;
+
+ /* Locked counter. */
+ gctINT32 locked;
+
+#ifdef __QNXNTO__
+ /* Single linked list of nodes. */
+ gcuVIDMEM_NODE_PTR next;
+
+ /* PID of the caller process channel. */
+ gctUINT32 userPID;
+
+ /* Unique handle of the caller process channel. */
+ gctHANDLE handle;
+
+ /* Unlock pending flag. */
+ gctBOOL unlockPending;
+
+ /* Free pending flag. */
+ gctBOOL freePending;
+#else
+ /* Pending flag. */
+ gctBOOL pending;
+#endif
+ }
+ Virtual;
+}
+gcuVIDMEM_NODE;
+
+/* gckVIDMEM object. */
+struct _gckVIDMEM
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Information for this video memory heap. */
+ gctUINT32 baseAddress;
+ gctSIZE_T bytes;
+ gctSIZE_T freeBytes;
+
+ /* Mapping for each type of surface. */
+ gctINT mapping[gcvSURF_NUM_TYPES];
+
+ /* Sentinel nodes for up to 8 banks. */
+ gcuVIDMEM_NODE sentinel[8];
+
+ /* Allocation threshold. */
+ gctSIZE_T threshold;
+
+ /* The heap mutex. */
+ gctPOINTER mutex;
+};
+
+/* gckMMU object. */
+struct _gckMMU
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* The page table mutex. */
+ gctPOINTER pageTableMutex;
+
+ /* Page table information. */
+ gctSIZE_T pageTableSize;
+ gctPHYS_ADDR pageTablePhysical;
+ gctUINT32_PTR pageTableLogical;
+ gctUINT32 pageTableEntries;
+ gctINT32 pageTableUsedEntries;
+
+ /* Free entries. */
+ gctUINT32 heapList;
+ gctBOOL freeNodes;
+
+#ifdef __QNXNTO__
+ /* Single linked list of all allocated nodes. */
+ gctPOINTER nodeMutex;
+ gcuVIDMEM_NODE_PTR nodeList;
+#endif
+};
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ );
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gctHANDLE Process,
+ IN OUT gctPOINTER * Data
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_command.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_command.c
new file mode 100644
index 0000000..68d0f9d
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_command.c
@@ -0,0 +1,2370 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_user_context.h"
+
+#if defined(__QNXNTO__)
+#include <sys/slog.h>
+#endif
+
+#if MRVL_LOW_POWER_MODE_DEBUG
+#include <linux/module.h>
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+#if MRVL_PRINT_CMD_BUFFER
+
+typedef struct _gcsRECORD_INFO * gcsRECORD_INFO_PTR;
+typedef struct _gcsRECORD_INFO
+{
+ gctUINT count;
+ gctUINT index;
+ gctUINT tail;
+}
+gcsRECORD_INFO;
+
+typedef enum _gceDUMPLOCATION
+{
+ gcvDUMP_NEW_QUEUE,
+ gcvDUMP_COMMIT,
+ gcvDUMP_EXECUTE,
+ gcvDUMP_STALL,
+ gcvDUMP_CMD,
+ gcvDUMP_EVENT,
+}
+gceDUMPLOCATION;
+
+typedef struct _gcsCMDBUF_RECORD * gcsCMDBUF_RECORD_PTR;
+typedef struct _gcsCMDBUF_RECORD
+{
+ gctPOINTER logical;
+ gctUINT32 address;
+ gctSIZE_T size;
+ gceDUMPLOCATION location;
+}
+gcsCMDBUF_RECORD;
+
+typedef struct _gcsLINK_RECORD * gcsLINK_RECORD_PTR;
+typedef struct _gcsLINK_RECORD
+{
+ gctUINT32_PTR fromLogical;
+ gctUINT32 fromAddress;
+ gctUINT32_PTR toLogical;
+ gctUINT32 toAddress;
+}
+gcsLINK_RECORD;
+
+#define gcdRECORD_COUNT 100
+
+static gctUINT _cmdQueueCount;
+
+static gcsRECORD_INFO _cmdInfo = { 0, ~0, 0 };
+static gcsRECORD_INFO _lnkInfo = { 0, ~0, 0 };
+
+static gcsCMDBUF_RECORD _cmdRecord[gcdRECORD_COUNT];
+static gcsLINK_RECORD _lnkRecord[gcdRECORD_COUNT];
+
+static void _AdvanceRecord(
+ gcsRECORD_INFO_PTR Record
+ )
+{
+ Record->index = (Record->index + 1) % gcdRECORD_COUNT;
+
+ if (Record->count < gcdRECORD_COUNT)
+ {
+ Record->count += 1;
+ }
+ else
+ {
+ Record->tail = (Record->tail + 1) % gcdRECORD_COUNT;
+ }
+}
+
+static void _AddCmdBuffer(
+ gckCOMMAND Command,
+ gctUINT8_PTR Logical,
+ gctSIZE_T Size,
+ gceDUMPLOCATION Location
+ )
+{
+ gctUINT address;
+ gcsCMDBUF_RECORD_PTR record;
+
+ if(!Command->dumpCmdBuf)
+ return;
+
+ _AdvanceRecord(&_cmdInfo);
+
+ if (Location == gcvDUMP_NEW_QUEUE)
+ {
+ _cmdQueueCount += 1;
+ }
+
+ gckHARDWARE_ConvertLogical(
+ Command->kernel->hardware, Logical, &address
+ );
+
+ if (Logical == gcvNULL)
+ {
+ address = ~0x00000000;
+ }
+
+ record = &_cmdRecord[_cmdInfo.index];
+
+ record->address = address;
+ record->size = Size;
+ record->location= Location;
+}
+
+static void _AddLink(
+ gckCOMMAND Command,
+ gctUINT32_PTR From,
+ gctUINT32_PTR To
+ )
+{
+ gctUINT from, to;
+ gcsLINK_RECORD_PTR record;
+
+ if(!Command->dumpCmdBuf)
+ return;
+
+ _AdvanceRecord(&_lnkInfo);
+
+ gckHARDWARE_ConvertLogical(
+ Command->kernel->hardware, From, &from
+ );
+
+ if (From == gcvNULL)
+ {
+ from = ~0x00000000;
+ }
+
+ gckHARDWARE_ConvertLogical(
+ Command->kernel->hardware, To, &to
+ );
+
+ if (To == gcvNULL)
+ {
+ to = ~0x00000000;
+ }
+
+ record = &_lnkRecord[_lnkInfo.index];
+
+ record->fromLogical = From;
+ record->fromAddress = from;
+ record->toLogical = To;
+ record->toAddress = to;
+}
+
+static gctUINT _FindCmdBuffer(
+ gctUINT Address
+ )
+{
+ gctUINT i, j, first, last;
+
+ i = (_cmdInfo.tail - 1 + _cmdInfo.count) % gcdRECORD_COUNT;
+
+ for (j = 0; j < _cmdInfo.count; j += 1)
+ {
+ first = _cmdRecord[i].address;
+ last = first + _cmdRecord[i].size;
+
+ if ((Address >= first) && (Address < last))
+ {
+ return i;
+ }
+
+ i = (i - 1 + gcdRECORD_COUNT) % gcdRECORD_COUNT;
+ }
+
+ return gcdRECORD_COUNT;
+}
+
+static void
+_PrintBuffer(
+ IN gckCOMMAND Command,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Address
+ )
+{
+ gctUINT32_PTR data = (gctUINT32_PTR) Pointer;
+ gctUINT32 address;
+ gctUINT32 printAddr;
+
+ if(Pointer == gcvNULL)
+ {
+ gcmkPRINT("@[kernel.command NULL pointer]");
+ return;
+ }
+
+ gckOS_GetPhysicalAddress(Command->os, Pointer, &address);
+
+ gcmkPRINT("@[kernel.command %08X %08X", address, Bytes);
+
+ printAddr = address;
+
+ while (Bytes >= 8*4)
+ {
+ if( (Address >= printAddr) && (Address < printAddr + 32))
+ {
+ gctINT i,j;
+
+ i = (Address - printAddr)/4;
+ j = (Address - printAddr)%4;
+ gcmkPRINT(" GPU stop @ below data[%d], bytes[%d]", i, j);
+ }
+
+ gcmkPRINT(" [%08X-%08X]: %08X %08X %08X %08X %08X %08X %08X %08X",
+ printAddr, printAddr + 32,
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6],
+ data[7]);
+
+ data += 8;
+ Bytes -= 32;
+ printAddr += 32;
+ }
+
+ if( (Address >= printAddr) && (Address < printAddr + 32))
+ {
+ gctINT i,j;
+
+ i = (Address - printAddr)/4;
+ j = (Address - printAddr)%4;
+ gcmkPRINT(" GPU stop @ below data[%d], bytes[%d]", i, j);
+ }
+
+ switch (Bytes)
+ {
+ case 7*4:
+ gcmkPRINT(" [%08X- ]: %08X %08X %08X %08X %08X %08X %08X", printAddr,
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
+ break;
+
+ case 6*4:
+ gcmkPRINT(" [%08X- ]: %08X %08X %08X %08X %08X %08X", printAddr,
+ data[0], data[1], data[2], data[3], data[4], data[5]);
+ break;
+
+ case 5*4:
+ gcmkPRINT(" [%08X- ]: %08X %08X %08X %08X %08X", printAddr,
+ data[0], data[1], data[2], data[3], data[4]);
+ break;
+
+ case 4*4:
+ gcmkPRINT(" [%08X- ]: %08X %08X %08X %08X", printAddr, data[0], data[1], data[2], data[3]);
+ break;
+
+ case 3*4:
+ gcmkPRINT(" [%08X- ]: %08X %08X %08X", printAddr, data[0], data[1], data[2]);
+ break;
+
+ case 2*4:
+ gcmkPRINT(" [%08X- ]: %08X %08X", printAddr, data[0], data[1]);
+ break;
+
+ case 1*4:
+ gcmkPRINT(" [%08X- ]: %08X", printAddr, data[0]);
+ break;
+
+ default:
+ break;
+ }
+
+ gcmkPRINT("] -- command");
+}
+
+void _PrintLinkChain(
+ gckCOMMAND Command
+ )
+{
+ gctUINT i, j;
+
+ gcmkPRINT("\nLink chain:\n\n");
+
+ i = _lnkInfo.tail;
+
+ for (j = 0; j < _lnkInfo.count; j += 1)
+ {
+ gcmkPRINT(" LINK 0x%08X --> 0x%08X\n",
+ _lnkRecord[i].fromAddress,
+ _lnkRecord[i].toAddress
+ );
+
+ i = (i + 1) % gcdRECORD_COUNT;
+ }
+}
+
+gceSTATUS
+_PrintCmdBuffer(
+ gckCOMMAND Command,
+ gctUINT Address
+ )
+{
+ gceSTATUS status;
+ gctUINT i, j, first, last, bufIndex;
+ gcsCMDBUF_RECORD_PTR buffer;
+ gctUINT address;
+
+ gcmkPRINT("\n%s(%d):\n"
+ " number of buffers stored %d;\n"
+ " buffer list:\n\n",
+ __FUNCTION__, __LINE__, _cmdInfo.count
+ );
+
+ i = _cmdInfo.tail;
+
+ for (j = 0; j < _cmdInfo.count; j += 1)
+ {
+ first = _cmdRecord[i].address;
+ last = first + _cmdRecord[i].size;
+
+ gcmkPRINT(" 0x%08X-0x%08X Location:%d\n",
+ first,
+ last,
+ _cmdRecord[i].location
+ );
+
+ i = (i + 1) % gcdRECORD_COUNT;
+ }
+
+ bufIndex = _FindCmdBuffer(Address);
+
+ if (bufIndex == gcdRECORD_COUNT)
+ {
+ gcmkPRINT("\n*** buffer not found for the specified location ***\n");
+ }
+ else
+ {
+ buffer = &_cmdRecord[bufIndex];
+ first = buffer->address;
+ last = first + buffer->size;
+
+ gcmkPRINT("\n%s(%d): buffer found 0x%08X-0x%08X Location:%d:\n\n",
+ __FUNCTION__, __LINE__,
+ first,
+ last,
+ buffer->location
+ );
+
+ gckOS_MapPhysical(Command->os, buffer->address, 0, buffer->size, &buffer->logical);
+ _PrintBuffer(Command, buffer->logical, buffer->size, Address);
+
+ gckOS_DumpToFile(Command->os,
+ "/data/dumpGC_CMDBUF.bin",
+ buffer->logical,
+ buffer->size);
+
+ gckOS_UnmapPhysical(Command->os, buffer->logical, buffer->size);
+ }
+
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Command->kernel->hardware, Command->logical, &address)
+ );
+
+ first = address;
+ last = first + Command->pageSize;
+
+ gcmkPRINT("\nCommand queue N%d: 0x%08X-0x%08X:\n\n",
+ _cmdQueueCount,
+ first,
+ last
+ );
+
+ _PrintBuffer(Command, Command->logical, Command->pageSize, Address);
+
+ gckOS_DumpToFile(Command->os,
+ "/data/dumpGC_CMDQUE.bin",
+ Command->logical,
+ Command->pageSize);
+
+ _PrintLinkChain(Command);
+
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ return status;
+}
+
+gceSTATUS
+_PrintAllCmdBuffer(
+ gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctUINT i, j, first, last;
+ gcsCMDBUF_RECORD_PTR buffer;
+ gctUINT address;
+
+ gcmkPRINT("\n%s(%d):\n"
+ " number of buffers stored %d;\n"
+ " buffer list:\n\n",
+ __FUNCTION__, __LINE__, _cmdInfo.count
+ );
+
+ i = _cmdInfo.tail;
+
+ for (j = 0; j < _cmdInfo.count; j += 1)
+ {
+ first = _cmdRecord[i].address;
+ last = first + _cmdRecord[i].size;
+
+ gcmkPRINT(" 0x%08X-0x%08X Location:%d\n",
+ first,
+ last,
+ _cmdRecord[i].location
+ );
+
+ {
+ buffer = &_cmdRecord[i];
+
+ gckOS_MapPhysical(Command->os, buffer->address, 0, buffer->size, &buffer->logical);
+ _PrintBuffer(Command, buffer->logical, buffer->size, 0xFFFFFFFF);
+ gckOS_UnmapPhysical(Command->os, buffer->logical, buffer->size);
+ }
+
+ i = (i + 1) % gcdRECORD_COUNT;
+ }
+
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Command->kernel->hardware, Command->logical, &address)
+ );
+
+ first = address;
+ last = first + Command->pageSize;
+
+ gcmkPRINT("\nCommand queue N%d: 0x%08X-0x%08X:\n\n",
+ _cmdQueueCount,
+ first,
+ last
+ );
+
+ _PrintBuffer(Command, Command->logical, Command->pageSize, 0xFFFFFFFF);
+
+ _PrintLinkChain(Command);
+
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ return status;
+}
+#endif
+
+#if gcdDUMP_COMMAND
+static void
+_DumpCommand(
+ IN gckCOMMAND Command,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Bytes
+ )
+{
+ gctUINT32_PTR data = (gctUINT32_PTR) Pointer;
+ gctUINT32 address;
+
+ gckOS_GetPhysicalAddress(Command->os, Pointer, &address);
+
+ gcmkPRINT("@[kernel.command %08X %08X %08X", Pointer, address, Bytes);
+ while (Bytes >= 8*4)
+ {
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6],
+ data[7]);
+ data += 8;
+ Bytes -= 32;
+ }
+
+ switch (Bytes)
+ {
+ case 7*4:
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4], data[5],
+ data[6]);
+ break;
+
+ case 6*4:
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4], data[5]);
+ break;
+
+ case 5*4:
+ gcmkPRINT(" %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4]);
+ break;
+
+ case 4*4:
+ gcmkPRINT(" %08X %08X %08X %08X", data[0], data[1], data[2], data[3]);
+ break;
+
+ case 3*4:
+ gcmkPRINT(" %08X %08X %08X", data[0], data[1], data[2]);
+ break;
+
+ case 2*4:
+ gcmkPRINT(" %08X %08X", data[0], data[1]);
+ break;
+
+ case 1*4:
+ gcmkPRINT(" %08X", data[0]);
+ break;
+ }
+
+ gcmkPRINT("] -- command");
+}
+#endif
+
+/*******************************************************************************
+**
+** _NewQueue
+**
+** Allocate a new command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** gckCOMMAND Command
+** gckCOMMAND object has been updated with a new command queue.
+*/
+static gceSTATUS
+_NewQueue(
+ IN OUT gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctINT currentIndex, newIndex;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Switch to the next command buffer. */
+ currentIndex = Command->index;
+ newIndex = (currentIndex + 1) % gcdCOMMAND_QUEUES;
+
+
+ /* Wait for availability. */
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.waitsignal]");
+#endif
+#if MRVL_PRINT_CMD_BUFFER
+ _AddCmdBuffer(
+ Command, gcvNULL, 0, gcvDUMP_NEW_QUEUE);
+#endif
+
+ gcmkONERROR(
+ gckOS_WaitSignal(Command->os,
+ Command->queues[newIndex].signal,
+ gcvINFINITE));
+
+ /* Update gckCOMMAND object with new command queue. */
+ Command->index = newIndex;
+ Command->newQueue = gcvTRUE;
+ Command->physical = Command->queues[newIndex].physical;
+ Command->logical = Command->queues[newIndex].logical;
+ Command->offset = 0;
+
+ if (currentIndex >= 0)
+ {
+ /* Mark the command queue as available. */
+ gcmkONERROR(gckEVENT_Signal(Command->kernel->event,
+ Command->queues[currentIndex].signal,
+ /*gcvKERNEL_COMMAND*/gcvKERNEL_PIXEL));
+ /* Submit the event queue. */
+ Command->submit = gcvTRUE;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("Command->index=%d", Command->index);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("index=%d, curIdx=%d, submit=%d", Command->index, currentIndex, Command->submit);
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/******************************************************************************\
+****************************** gckCOMMAND API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckCOMMAND_Construct
+**
+** Construct a new gckCOMMAND object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gckCOMMAND * Command
+** Pointer to a variable that will hold the pointer to the gckCOMMAND
+** object.
+*/
+gceSTATUS
+gckCOMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckCOMMAND * Command
+ )
+{
+ gckOS os;
+ gckCOMMAND command = gcvNULL;
+ gceSTATUS status;
+ gctINT i;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+ /* Extract the gckOS object. */
+ os = Kernel->os;
+
+ /* Allocate the gckCOMMAND structure. */
+ gcmkONERROR(
+ gckOS_Allocate(os,
+ gcmSIZEOF(struct _gckCOMMAND),
+ (gctPOINTER *) &command));
+
+ /* Initialize the gckCOMMAND object.*/
+ command->object.type = gcvOBJ_COMMAND;
+ command->kernel = Kernel;
+ command->os = os;
+ command->mutexQueue = gcvNULL;
+ command->mutexContext = gcvNULL;
+ command->powerSemaphore = gcvNULL;
+ command->atomCommit = gcvNULL;
+
+ /* No command queues created yet. */
+ command->index = 0;
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ command->queues[i].signal = gcvNULL;
+ command->queues[i].logical = gcvNULL;
+ }
+
+ /* Get the command buffer requirements. */
+ gcmkONERROR(
+ gckHARDWARE_QueryCommandBuffer(Kernel->hardware,
+ &command->alignment,
+ &command->reservedHead,
+ &command->reservedTail));
+
+ /* No contexts available yet. */
+ command->contextCounter = command->currentContext = 0;
+
+ /* Create the command queue mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &command->mutexQueue));
+
+ /* Create the context switching mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &command->mutexContext));
+
+ /* Create the power management semaphore. */
+ gcmkONERROR(
+ gckOS_CreateSemaphore(os, &command->powerSemaphore));
+
+ /* Create the commit atom. */
+ gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
+
+ /* Get the page size from teh OS. */
+ gcmkONERROR(
+ gckOS_GetPageSize(os, &command->pageSize));
+
+ /* Set hardware to pipe 0. */
+ command->pipeSelect = 0;
+
+ /* Pre-allocate the command queues. */
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemory(os,
+ gcvFALSE,
+ &command->pageSize,
+ &command->queues[i].physical,
+ &command->queues[i].logical));
+ gcmkONERROR(
+ gckOS_CreateSignal(os, gcvFALSE, &command->queues[i].signal));
+
+ gcmkONERROR(
+ gckOS_Signal(os, command->queues[i].signal, gcvTRUE));
+ }
+
+ /* No command queue in use yet. */
+ command->index = -1;
+ command->logical = gcvNULL;
+ command->newQueue = gcvFALSE;
+ command->submit = gcvFALSE;
+
+ /* Command is not yet running. */
+ command->running = gcvFALSE;
+
+ /* Command queue is idle. */
+ command->idle = gcvTRUE;
+
+ /* Commit stamp is zero. */
+ command->commitStamp = 0;
+
+ /* Don't dump command buffer and link chain by default */
+ command->dumpCmdBuf = gcvFALSE;
+
+ /* Return pointer to the gckCOMMAND object. */
+ *Command = command;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Command=0x%x", *Command);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (command != gcvNULL)
+ {
+ /* Destroy the commit atom. */
+ if (command->atomCommit != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, command->atomCommit));
+ command->atomCommit = gcvNULL;
+ }
+
+ /* Destroy the power management semaphore. */
+ if (command->powerSemaphore != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(os, command->powerSemaphore));
+ command->powerSemaphore = gcvNULL;
+ }
+
+ /* Delete the context switching mutex. */
+ if (command->mutexContext != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexContext));
+ command->mutexContext = gcvNULL;
+ }
+
+ /* Delete the command queue mutex. */
+ if (command->mutexQueue != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexQueue));
+ command->mutexQueue = gcvNULL;
+ }
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ if (command->queues[i].signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DestroySignal(os, command->queues[i].signal));
+
+ command->queues[i].signal = gcvNULL;
+ }
+
+ if (command->queues[i].physical != gcvNULL ||
+ command->queues[i].logical != gcvNULL
+ )
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeNonPagedMemory(os,
+ command->pageSize,
+ command->queues[i].physical,
+ command->queues[i].logical));
+ command->queues[i].physical = gcvNULL;
+ command->queues[i].logical = gcvNULL;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(os, command));
+
+ command = gcvNULL;
+ }
+
+ gcmkLOG_ERROR_STATUS();
+ /* 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;
+ gceSTATUS status;
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Stop the command queue. */
+ gcmkONERROR(gckCOMMAND_Stop(Command));
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ if (Command->queues[i].signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DestroySignal(Command->os, Command->queues[i].signal));
+
+ Command->queues[i].signal = gcvNULL;
+ }
+
+ if (Command->queues[i].physical != gcvNULL ||
+ Command->queues[i].logical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeNonPagedMemory(Command->os,
+ Command->pageSize,
+ Command->queues[i].physical,
+ Command->queues[i].logical));
+
+ Command->queues[i].physical = gcvNULL;
+ Command->queues[i].logical = gcvNULL;
+ }
+ }
+
+ /* Delete the context switching mutex. */
+ if (Command->mutexContext != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext));
+ Command->mutexContext = gcvNULL;
+ }
+
+ /* Delete the Command queue mutex. */
+ if (Command->mutexQueue != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue));
+ Command->mutexQueue = gcvNULL;
+ }
+
+ /* Destroy the power management semaphore. */
+ if (Command->powerSemaphore != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Command->os, Command->powerSemaphore));
+ Command->powerSemaphore = gcvNULL;
+ }
+
+ /* Destroy the commit atom. */
+ if (Command->atomCommit != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Command->os, Command->atomCommit));
+ Command->atomCommit = gcvNULL;
+ }
+
+ /* Mark object as unknown. */
+ Command->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckCOMMAND object. */
+ gcmkVERIFY_OK(gckOS_Free(Command->os, Command));
+
+ Command = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* 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
+ )
+{
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gctSIZE_T bytes;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->running)
+ {
+ /* Command queue already running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (Command->logical == gcvNULL)
+ {
+ /* Start at beginning of a new queue. */
+ gcmkONERROR(_NewQueue(Command));
+ }
+
+ /* Start at beginning of page. */
+ Command->offset = 0;
+
+ /* Append WAIT/LINK. */
+ bytes = Command->pageSize;
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(hardware,
+ Command->logical,
+ 0,
+ &bytes,
+ &Command->wait,
+ &Command->waitSize));
+
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ Command->logical,
+ bytes));
+
+ /* Adjust offset. */
+ Command->offset = bytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Enable command processor. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckHARDWARE_Execute(hardware,
+ Command->logical,
+ Command->physical,
+ gcvTRUE,
+ bytes));
+#else
+ gcmkONERROR(
+ gckHARDWARE_Execute(hardware,
+ Command->logical,
+ bytes));
+#endif
+ /* Command queue is running. */
+ Command->running = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stop
+**
+** Stop the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to stop.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command
+ )
+{
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gctUINT32 idle;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (!Command->running)
+ {
+ /* Command queue is not running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Replace last WAIT with END. */
+ gcmkONERROR(
+ gckHARDWARE_End(hardware,
+ Command->wait,
+ &Command->waitSize));
+
+ /* Wait for idle. */
+
+ while (1)
+ {
+ /* Read register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(hardware->os, 0x00004, &idle));
+
+ /* Wait for FE idle. */
+ if (idle & 0x1)
+ {
+ break;
+ }
+
+ /* Wait a little. */
+ gcmkVERIFY_OK(gckOS_Udelay(hardware->os, 1));
+ }
+
+ /* Command queue is no longer running. */
+ Command->running = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, Command=0x%08x", status, Command);
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+typedef struct _gcsMAPPED * gcsMAPPED_PTR;
+struct _gcsMAPPED
+{
+ gcsMAPPED_PTR next;
+ gctPOINTER pointer;
+ gctPOINTER kernelPointer;
+ gctSIZE_T bytes;
+};
+
+static gceSTATUS
+_AddMap(
+ IN gckOS Os,
+ IN gctPOINTER Source,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Destination,
+ IN OUT gcsMAPPED_PTR * Stack
+ )
+{
+ gcsMAPPED_PTR map = gcvNULL;
+ gceSTATUS status;
+
+ /* Don't try to map NULL pointers. */
+ if (Source == gcvNULL)
+ {
+ *Destination = gcvNULL;
+ return gcvSTATUS_OK;
+ }
+
+ /* Allocate the gcsMAPPED structure. */
+ gcmkONERROR(
+ gckOS_Allocate(Os, gcmSIZEOF(*map), (gctPOINTER *) &map));
+
+ /* Map the user pointer into kernel addressing space. */
+ gcmkONERROR(
+ gckOS_MapUserPointer(Os, Source, Bytes, Destination));
+
+ /* Save mapping. */
+ map->pointer = Source;
+ map->kernelPointer = *Destination;
+ map->bytes = Bytes;
+
+ /* Push structure on top of the stack. */
+ map->next = *Stack;
+ *Stack = map;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, map=0x%08x", status, map);
+ if (gcmIS_ERROR(status) && (map != gcvNULL))
+ {
+ /* Roll back on error. */
+ gcmkVERIFY_OK(gckOS_Free(Os, map));
+ map = gcvNULL;
+ }
+
+ /* Return the status. */
+ return status;
+}
+#define LATE_NOTIFY_BUSY 0
+/*******************************************************************************
+**
+** gckCOMMAND_Commit
+**
+** Commit a command buffer to the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gcoCMDBUF CommandBuffer
+** Pointer to an gcoCMDBUF object.
+**
+** gcoCONTEXT Context
+** Pointer to an gcoCONTEXT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Commit(
+ IN gckCOMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcoCONTEXT Context,
+ IN gctHANDLE Process
+ )
+{
+ gcoCMDBUF commandBuffer;
+ gcoCONTEXT context;
+ gckHARDWARE hardware = gcvNULL;
+ gceSTATUS status;
+ gctPOINTER initialLink, link;
+ gctSIZE_T bytes, initialSize, lastRun;
+ gcoCMDBUF buffer;
+ gctPOINTER wait;
+ gctSIZE_T waitSize;
+ gctUINT32 offset;
+ gctPOINTER fetchAddress;
+ gctSIZE_T fetchSize;
+ gctUINT8_PTR logical;
+ gcsMAPPED_PTR stack = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+#if gcdSECURE_USER
+ gctUINT32_PTR hint;
+#endif
+#if gcdDUMP_COMMAND
+ gctPOINTER dataPointer;
+ gctSIZE_T dataBytes;
+#endif
+#if MRVL_PRINT_CMD_BUFFER
+ gctPOINTER dumpLogical;
+ gctSIZE_T dumpSize;
+#endif
+ gctPOINTER flushPointer;
+ gctSIZE_T flushSize;
+
+ gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x Context=0x%x",
+ Command, CommandBuffer, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if gcdNULL_DRIVER == 2
+ /* Do nothing with infinite hardware. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#endif
+
+ gcmkONERROR(
+ _AddMap(Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *) &commandBuffer,
+ &stack));
+ gcmkVERIFY_OBJECT(commandBuffer, gcvOBJ_COMMANDBUFFER);
+ gcmkONERROR(
+ _AddMap(Command->os,
+ Context,
+ gcmSIZEOF(struct _gcoCONTEXT),
+ (gctPOINTER *) &context,
+ &stack));
+ gcmkVERIFY_OBJECT(context, gcvOBJ_CONTEXT);
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Grab the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireRecMutex(Command->os,
+ hardware->recMutexPower,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+#if !LATE_NOTIFY_BUSY
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_ON));
+
+ if (Command->kernel->notifyIdle)
+ {
+ /* Increase the commit stamp */
+ Command->commitStamp++;
+
+ /* Set busy if idle */
+ if (Command->idle)
+ {
+ Command->idle = gcvFALSE;
+
+ gcmkVERIFY_OK(gckOS_NotifyIdle(Command->os, gcvFALSE));
+ }
+ }
+#endif
+
+ /* Reserved slot in the context or command buffer. */
+ gcmkONERROR(
+ gckHARDWARE_PipeSelect(hardware, gcvNULL, 0, &bytes));
+
+ /* Test if we need to switch to this context. */
+ if ((context->id != 0)
+ && (context->id != Command->currentContext)
+ )
+ {
+ /* Map the context buffer.*/
+ gcmkONERROR(
+ _AddMap(Command->os,
+ context->logical,
+ context->bufferSize,
+ (gctPOINTER *) &logical,
+ &stack));
+
+#if gcdSECURE_USER
+ /* Map the hint array.*/
+ gcmkONERROR(
+ _AddMap(Command->os,
+ context->hintArray,
+ context->hintCount * gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &hint,
+ &stack));
+
+ /* Loop while we have valid hints. */
+ while (*hint != 0)
+ {
+ /* Map handle into physical address. */
+ gcmkONERROR(
+ gckKERNEL_MapLogicalToPhysical(
+ Command->kernel,
+ Process,
+ (gctPOINTER *) (logical + *hint)));
+
+ /* Next hint. */
+ ++hint;
+ }
+#endif
+
+ /* See if we have to check pipes. */
+ if (context->pipe2DIndex != 0)
+ {
+ /* See if we are in the correct pipe. */
+ if (context->initialPipe == Command->pipeSelect)
+ {
+ gctUINT32 reserved = bytes;
+ gctUINT8_PTR nop = logical;
+
+ /* Already in the correct pipe, fill context buffer with NOP. */
+ while (reserved > 0)
+ {
+ bytes = reserved;
+ gcmkONERROR(
+ gckHARDWARE_Nop(hardware, nop, &bytes));
+
+ gcmkASSERT(reserved >= bytes);
+ reserved -= bytes;
+ nop += bytes;
+ }
+ }
+ else
+ {
+ /* Switch to the correct pipe. */
+ gcmkONERROR(
+ gckHARDWARE_PipeSelect(hardware,
+ logical,
+ context->initialPipe,
+ &bytes));
+ }
+ }
+
+ /* Save initial link pointer. */
+ initialLink = logical;
+ initialSize = context->bufferSize;
+
+ /* Save initial buffer to flush. */
+ flushPointer = initialLink;
+ flushSize = initialSize;
+
+ /* Save pointer to next link. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ context->link,
+ 8,
+ &link,
+ &stack));
+
+ /* Start parsing CommandBuffer. */
+ buffer = commandBuffer;
+
+ /* Mark context buffer as used. */
+ if (context->inUse != gcvNULL)
+ {
+ gctBOOL_PTR inUse;
+
+ gcmkONERROR(
+ _AddMap(Command->os,
+ (gctPOINTER) context->inUse,
+ gcmSIZEOF(gctBOOL),
+ (gctPOINTER *) &inUse,
+ &stack));
+
+ *inUse = gcvTRUE;
+ }
+ }
+
+ else
+ {
+ /* Test if this is a new context. */
+ if (context->id == 0)
+ {
+ /* Generate unique ID for the context buffer. */
+ context->id = ++ Command->contextCounter;
+
+ if (context->id == 0)
+ {
+ /* Context counter overflow (wow!) */
+ gcmkONERROR(gcvSTATUS_TOO_COMPLEX);
+ }
+ }
+
+ /* Map the command buffer. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ commandBuffer->logical,
+ commandBuffer->offset,
+ (gctPOINTER *) &logical,
+ &stack));
+
+#if gcdSECURE_USER
+ /* Map the hint table. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ commandBuffer->hintCommit,
+ commandBuffer->offset - commandBuffer->startOffset,
+ (gctPOINTER *) &hint,
+ &stack));
+
+ /* Walk while we have valid hints. */
+ while (*hint != 0)
+ {
+ /* Map the handle to a physical address. */
+ gcmkONERROR(
+ gckKERNEL_MapLogicalToPhysical(
+ Command->kernel,
+ Process,
+ (gctPOINTER *) (logical + *hint)));
+
+ /* Next hint. */
+ ++hint;
+ }
+#endif
+
+ if (context->entryPipe == Command->pipeSelect)
+ {
+ gctUINT32 reserved = Command->reservedHead;
+ gctUINT8_PTR nop = logical + commandBuffer->startOffset;
+
+ /* Already in the correct pipe, fill context buffer with NOP. */
+ while (reserved > 0)
+ {
+ bytes = reserved;
+ gcmkONERROR(
+ gckHARDWARE_Nop(hardware, nop, &bytes));
+
+ gcmkASSERT(reserved >= bytes);
+ reserved -= bytes;
+ nop += bytes;
+ }
+ }
+ else
+ {
+ /* Switch to the correct pipe. */
+ gcmkONERROR(
+ gckHARDWARE_PipeSelect(hardware,
+ logical + commandBuffer->startOffset,
+ context->entryPipe,
+ &bytes));
+ }
+
+ /* Save initial link pointer. */
+ initialLink = logical + commandBuffer->startOffset;
+ initialSize = commandBuffer->offset
+ - commandBuffer->startOffset
+ + Command->reservedTail;
+
+ /* Save initial buffer to flush. */
+ flushPointer = initialLink;
+ flushSize = initialSize;
+
+ /* Save pointer to next link. */
+ link = logical + commandBuffer->offset;
+
+ /* No more data. */
+ buffer = gcvNULL;
+ }
+
+#if MRVL_PRINT_CMD_BUFFER
+ _AddLink(Command, Command->wait, initialLink);
+#endif
+
+#if gcdDUMP_COMMAND
+ dataPointer = initialLink;
+ dataBytes = initialSize;
+#endif
+
+#if MRVL_PRINT_CMD_BUFFER
+ dumpLogical = initialLink;
+ dumpSize = initialSize;
+#endif
+
+ /* Loop through all remaining command buffers. */
+ if (buffer != gcvNULL)
+ {
+ /* Map the command buffer. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ buffer->logical,
+ buffer->offset + Command->reservedTail,
+ (gctPOINTER *) &logical,
+ &stack));
+
+#if gcdSECURE_USER
+ /* Map the hint table. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ buffer->hintCommit,
+ buffer->offset - buffer->startOffset,
+ (gctPOINTER *) &hint,
+ &stack));
+
+ /* Walk while we have valid hints. */
+ while (*hint != 0)
+ {
+ /* Map the handle to a physical address. */
+ gcmkONERROR(
+ gckKERNEL_MapLogicalToPhysical(
+ Command->kernel,
+ Process,
+ (gctPOINTER *) (logical + *hint)));
+
+ /* Next hint. */
+ ++hint;
+ }
+#endif
+
+ /* First slot becomes a NOP. */
+ {
+ gctUINT32 reserved = Command->reservedHead;
+ gctUINT8_PTR nop = logical + buffer->startOffset;
+
+ /* Already in the correct pipe, fill context buffer with NOP. */
+ while (reserved > 0)
+ {
+ bytes = reserved;
+ gcmkONERROR(
+ gckHARDWARE_Nop(hardware, nop, &bytes));
+
+ gcmkASSERT(reserved >= bytes);
+ reserved -= bytes;
+ nop += bytes;
+ }
+ }
+
+ /* Generate the LINK to this command buffer. */
+ gcmkONERROR(
+ gckHARDWARE_Link(hardware,
+ link,
+ logical + buffer->startOffset,
+ buffer->offset
+ - buffer->startOffset
+ + Command->reservedTail,
+ &bytes));
+#if MRVL_PRINT_CMD_BUFFER
+ _AddLink(Command, link, (gctUINT32_PTR)logical);
+#endif
+
+ /* Flush the initial buffer. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ Process,
+ flushPointer,
+ flushSize));
+
+ /* Save new flush pointer. */
+ flushPointer = logical + buffer->startOffset;
+ flushSize = buffer->offset
+ - buffer->startOffset
+ + Command->reservedTail;
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, dataPointer, dataBytes);
+ dataPointer = logical + buffer->startOffset;
+ dataBytes = buffer->offset - buffer->startOffset
+ + Command->reservedTail;
+#endif
+
+#if MRVL_PRINT_CMD_BUFFER
+ _AddCmdBuffer(
+ Command, dumpLogical, dumpSize, gcvDUMP_CMD);
+ dumpLogical = logical + buffer->startOffset;
+ dumpSize = buffer->offset - buffer->startOffset
+ + Command->reservedTail;
+#endif
+
+ /* Save pointer to next link. */
+ link = logical + buffer->offset;
+ }
+
+ /* Compute number of bytes required for WAIT/LINK. */
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(hardware,
+ gcvNULL,
+ Command->offset,
+ &bytes,
+ gcvNULL,
+ gcvNULL));
+
+ lastRun = bytes;
+
+#if LATE_NOTIFY_BUSY
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_ON));
+
+ if (Command->kernel->notifyIdle)
+ {
+ /* Increase the commit stamp */
+ Command->commitStamp++;
+
+ /* Set busy if idle */
+ if (Command->idle)
+ {
+ Command->idle = gcvFALSE;
+
+ gcmkVERIFY_OK(gckOS_NotifyIdle(Command->os, gcvFALSE));
+ }
+ }
+#endif
+
+ /* Compute number of bytes left in current command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ if (bytes < lastRun)
+ {
+ /* Create a new command queue. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Adjust run size with any extra commands inserted. */
+ lastRun += Command->offset;
+ }
+
+ /* Get current offset. */
+ offset = Command->offset;
+
+ /* Append WAIT/LINK in command queue. */
+ bytes = Command->pageSize - offset;
+
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(hardware,
+ (gctUINT8 *) Command->logical + offset,
+ offset,
+ &bytes,
+ &wait,
+ &waitSize));
+
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ (gctUINT8 *) Command->logical + offset,
+ bytes));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, (gctUINT8 *) Command->logical + offset, bytes);
+#endif
+
+#if MRVL_PRINT_CMD_BUFFER
+ _AddCmdBuffer(Command, (gctUINT8 *) Command->logical + offset, bytes, gcvDUMP_CMD);
+#endif
+
+ /* Adjust offset. */
+ offset += bytes;
+
+ if (Command->newQueue)
+ {
+ /* Compute fetch location and size for a new command queue. */
+ fetchAddress = Command->logical;
+ fetchSize = offset;
+ }
+ else
+ {
+ /* Compute fetch location and size for an existing command queue. */
+ fetchAddress = (gctUINT8 *) Command->logical + Command->offset;
+ fetchSize = offset - Command->offset;
+ }
+
+ bytes = 8;
+
+ /* Link in WAIT/LINK. */
+ gcmkONERROR(
+ gckHARDWARE_Link(hardware,
+ link,
+ fetchAddress,
+ fetchSize,
+ &bytes));
+#if MRVL_PRINT_CMD_BUFFER
+ _AddLink(Command, link, fetchAddress);
+#endif
+
+ /* Flush the cache for the command buffer. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ Process,
+ flushPointer,
+ flushSize));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, dataPointer, dataBytes);
+#endif
+
+#if MRVL_PRINT_CMD_BUFFER
+ _AddCmdBuffer(Command, dumpLogical, dumpSize, gcvDUMP_CMD);
+#endif
+
+ /* Execute the entire sequence. */
+ gcmkONERROR(
+ gckHARDWARE_Link(hardware,
+ Command->wait,
+ initialLink,
+ initialSize,
+ &Command->waitSize));
+
+ /* Flush the cache for the link. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ Command->wait,
+ Command->waitSize));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, Command->wait, Command->waitSize);
+#endif
+
+#if MRVL_PRINT_CMD_BUFFER
+ _AddCmdBuffer(Command, Command->wait, Command->waitSize, gcvDUMP_CMD);
+#endif
+
+ /* Update command queue offset. */
+ Command->offset = offset;
+ Command->newQueue = gcvFALSE;
+
+ /* Update address of last WAIT. */
+ Command->wait = wait;
+ Command->waitSize = waitSize;
+
+ /* Update context and pipe select. */
+ Command->currentContext = context->id;
+ Command->pipeSelect = context->currentPipe;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(
+ gckHARDWARE_UpdateQueueTail(hardware,
+ Command->logical,
+ Command->offset));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.commit]");
+#endif
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseRecMutex(Command->os, hardware->recMutexPower));
+ acquired = gcvFALSE;
+
+ /* Submit events if asked for. */
+ if (Command->submit)
+ {
+ /* Submit events. */
+ status = gckEVENT_Submit(Command->kernel->event, gcvFALSE);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Success. */
+ Command->submit = gcvFALSE;
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND,
+ "gckEVENT_Submit returned %d",
+ status);
+ }
+ }
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+
+OnError:
+ if (!gcmIS_SUCCESS(status))
+ {
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d",
+ status, acquired);
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseRecMutex(Command->os, hardware->recMutexPower));
+ }
+
+ /* Unmap all mapped pointers. */
+ while (stack != gcvNULL)
+ {
+ gcsMAPPED_PTR map = stack;
+ stack = map->next;
+
+ gcmkVERIFY_OK(
+ gckOS_UnmapUserPointer(Command->os,
+ map->pointer,
+ map->bytes,
+ map->kernelPointer));
+
+ gcmkVERIFY_OK(
+ gckOS_Free(Command->os, map));
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Reserve
+**
+** Reserve space in the command queue. Also acquire the command queue mutex.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** gctPOINTER * Buffer
+** Pointer to a variable that will receive the address of the reserved
+** space.
+**
+** gctSIZE_T * BufferSize
+** Pointer to a variable that will receive the number of bytes
+** available in the command queue.
+*/
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctSIZE_T * BufferSize
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T requiredBytes, bytes;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Grab the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireRecMutex(Command->os,
+ Command->kernel->hardware->recMutexPower,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+#if !LATE_NOTIFY_BUSY
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(Command->kernel->hardware, gcvPOWER_ON));
+
+ if (Command->kernel->notifyIdle)
+ {
+ /* Increase the commit stamp */
+ Command->commitStamp++;
+
+ /* Set busy if idle */
+ if (Command->idle)
+ {
+ Command->idle = gcvFALSE;
+
+ gcmkVERIFY_OK(gckOS_NotifyIdle(Command->os, gcvFALSE));
+ }
+ }
+#endif
+
+ /* Compute number of bytes required for WAIT/LINK. */
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(Command->kernel->hardware,
+ gcvNULL,
+ Command->offset + gcmALIGN(RequestedBytes,
+ Command->alignment),
+ &requiredBytes,
+ gcvNULL,
+ gcvNULL));
+
+ /* Compute total number of bytes required. */
+ requiredBytes += gcmALIGN(RequestedBytes, Command->alignment);
+
+ /* Compute number of bytes available in command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ if (bytes < requiredBytes)
+ {
+ /* Create a new command queue. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Recompute number of bytes available in command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ if (bytes < requiredBytes)
+ {
+ /* Rare case, not enough room in command queue. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+ }
+
+ /* Fill hole in command queue with value NOP */
+ {
+ gctSIZE_T alignBytes = gcmALIGN(RequestedBytes, Command->alignment) - RequestedBytes;
+
+ if (alignBytes > 0)
+ {
+ gctSIZE_T reserved = alignBytes;
+ gctUINT8_PTR nop = (gctUINT8_PTR) Command->logical + Command->offset + RequestedBytes;
+
+ while (reserved > 0)
+ {
+ gctSIZE_T size = sizeof(gctUINT32);
+ gctUINT32_PTR ptr = (gctUINT32_PTR) nop;
+
+ if (reserved < size)
+ break;
+
+ *ptr = GC_NOP_COMMAND;
+ reserved -= size;
+ nop += size;
+ }
+ }
+ }
+
+ /* 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:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d, requiredBytes=%d",
+ status, acquired, requiredBytes);
+
+
+ if (acquired)
+ {
+ /* Release mutex on error. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseRecMutex(Command->os, Command->kernel->hardware->recMutexPower));
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Release
+**
+** Release a previously reserved command queue. The command FIFO mutex will be
+** released.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Release(
+ IN gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseRecMutex(Command->os, Command->kernel->hardware->recMutexPower));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Execute
+**
+** Execute a previously reserved command queue by appending a WAIT/LINK command
+** sequence after it and modifying the last WAIT into a LINK command. The
+** command FIFO mutex will be released whether this function succeeds or not.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequestedBytes
+ )
+{
+ gctUINT32 offset;
+ gctPOINTER address;
+ gctSIZE_T bytes;
+ gceSTATUS status;
+ gctPOINTER wait;
+ gctSIZE_T waitBytes;
+
+ gctBOOL queueReleased = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if LATE_NOTIFY_BUSY
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(Command->kernel->hardware, gcvPOWER_ON));
+
+ if (Command->kernel->notifyIdle)
+ {
+ /* Increase the commit stamp */
+ Command->commitStamp++;
+
+ /* Set busy if idle */
+ if (Command->idle)
+ {
+ Command->idle = gcvFALSE;
+
+ gcmkVERIFY_OK(gckOS_NotifyIdle(Command->os, gcvFALSE));
+ }
+ }
+#endif
+
+ /* Compute offset for WAIT/LINK. */
+ offset = Command->offset + RequestedBytes;
+
+ /* Compute number of byts left in command queue. */
+ bytes = Command->pageSize - offset;
+
+ /* Append WAIT/LINK in command queue. */
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(Command->kernel->hardware,
+ (gctUINT8 *) Command->logical + offset,
+ offset,
+ &bytes,
+ &wait,
+ &waitBytes));
+
+ if (Command->newQueue)
+ {
+ /* For a new command queue, point to the start of the command
+ ** queue and include both the commands inserted at the head of it
+ ** and the WAIT/LINK. */
+ address = Command->logical;
+ bytes += offset;
+ }
+ else
+ {
+ /* For an existing command queue, point to the current offset and
+ ** include the WAIT/LINK. */
+ address = (gctUINT8 *) Command->logical + Command->offset;
+ bytes += RequestedBytes;
+ }
+
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os, gcvNULL, address, bytes));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, address, bytes);
+#endif
+
+#if MRVL_PRINT_CMD_BUFFER
+ _AddCmdBuffer(Command, address, bytes, gcvDUMP_EVENT);
+#endif
+
+ /* Convert the last WAIT into a LINK. */
+ gcmkONERROR(gckHARDWARE_Link(Command->kernel->hardware,
+ Command->wait,
+ address,
+ bytes,
+ &Command->waitSize));
+#if MRVL_PRINT_CMD_BUFFER
+ _AddLink(Command, Command->wait, address);
+#endif
+
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ Command->wait,
+ Command->waitSize));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, Command->wait, 8);
+#endif
+
+#if MRVL_PRINT_CMD_BUFFER
+ _AddCmdBuffer(Command, Command->wait, 8, gcvDUMP_EVENT);
+#endif
+
+ /* Update the pointer to the last WAIT. */
+ Command->wait = wait;
+ Command->waitSize = waitBytes;
+
+ /* Update the command queue. */
+ Command->offset += bytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(
+ gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
+ Command->logical,
+ Command->offset));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.execute]");
+#endif
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseRecMutex(Command->os, Command->kernel->hardware->recMutexPower));
+ queueReleased = gcvTRUE;
+
+ /* Submit events if asked for. */
+ if (Command->submit)
+ {
+ /* Submit events. */
+ status = gckEVENT_Submit(Command->kernel->event, gcvFALSE);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Success. */
+ Command->submit = gcvFALSE;
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND,
+ "gckEVENT_Submit returned %d",
+ status);
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, queueReleased=%d",
+ status, queueReleased);
+
+ /* Release the mutex. */
+ if (!queueReleased)
+ {
+ gcmkVERIFY_OK(
+ gckOS_ReleaseRecMutex(Command->os, Command->kernel->hardware->recMutexPower));
+ }
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stall
+**
+** The calling thread will be suspended until the command queue has been
+** completed.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stall(
+ IN gckCOMMAND Command
+ )
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gckEVENT event;
+ gceSTATUS status;
+ gctSIGNAL signal = gcvNULL;
+#if VIVANTE_POWER_MANAGE
+ gctUINT timer = 0;
+#endif
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if gcdNULL_DRIVER == 2
+ /* Do nothing with infinite hardware. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#endif
+
+ /* Extract the gckOS object pointer. */
+ os = Command->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Extract the gckEVENT object pointer. */
+ event = Command->kernel->event;
+ gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+ /* Allocate the signal. */
+ gcmkONERROR(
+ gckOS_CreateSignal(os, gcvTRUE, &signal));
+
+ /* Append the EVENT command to trigger the signal. */
+ gcmkONERROR(gckEVENT_Signal(event,
+ signal,
+ gcvKERNEL_PIXEL));
+
+ /* Submit the event queue. */
+ gcmkONERROR(gckEVENT_Submit(event, gcvTRUE));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.stall]");
+#endif
+
+ if (status == gcvSTATUS_CHIP_NOT_READY)
+ {
+ /* Error. */
+ goto OnError;
+ }
+
+ do
+ {
+ /* Wait for the signal. */
+ status = gckOS_WaitSignalNoInterruptible(os, signal, gcvINFINITE);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+#if gcdDEBUG
+ gctUINT32 idle;
+
+ /* IDLE */
+ gcmkONERROR(gckOS_ReadRegister(Command->os, 0x0004, &idle));
+
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "%s(%d): idle=%08x",
+ __FUNCTION__, __LINE__, idle);
+ gckOS_Log(_GFX_LOG_WARNING_, "%s : %d : idle register = 0x%08x \n",
+ __FUNCTION__, __LINE__, idle);
+#endif
+
+#if MRVL_LOW_POWER_MODE_DEBUG
+ {
+ int i = 0;
+
+ gcmkPRINT(">>>>>>>>>>>>galDevice->kernel->kernelMSG\n");
+ gcmkPRINT("galDevice->kernel->msgLen=%d\n",Command->kernel->msgLen);
+
+ for(i=0;i<Command->kernel->msgLen;i+=1024)
+ {
+ Command->kernel->kernelMSG[i+1023] = '\0';
+ gcmkPRINT("%s\n",(char*)Command->kernel->kernelMSG + i);
+ }
+ }
+#endif
+#ifdef __QNXNTO__
+ gctUINT32 reg_cmdbuf_fetch;
+ gctUINT32 reg_intr;
+
+ gcmkONERROR(
+ gckOS_ReadRegister(Command->kernel->hardware->os, 0x0664, &reg_cmdbuf_fetch));
+
+ if (idle == 0x7FFFFFFE)
+ {
+ /*
+ * GPU is idle so there should not be pending interrupts.
+ * Just double check.
+ *
+ * Note that reading interrupt register clears it.
+ * That's why we don't read it in all cases.
+ */
+ gcmkONERROR(
+ gckOS_ReadRegister(Command->kernel->hardware->os, 0x10, &reg_intr));
+
+ slogf(
+ _SLOG_SETCODE(1, 0),
+ _SLOG_CRITICAL,
+ "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X, interrupt = 0x%X)",
+ idle, reg_cmdbuf_fetch, reg_intr);
+ }
+ else
+ {
+ slogf(
+ _SLOG_SETCODE(1, 0),
+ _SLOG_CRITICAL,
+ "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X)",
+ idle, reg_cmdbuf_fetch);
+ }
+#endif
+ gcmkONERROR(
+ gckOS_MemoryBarrier(os, gcvNULL));
+#if VIVANTE_POWER_MANAGE
+ /* Advance timer. */
+ timer += 250;
+#endif
+ }
+ }
+
+#if !VIVANTE_POWER_MANAGE
+ while (gcmIS_ERROR(status));
+#else
+ while (gcmIS_ERROR(status)
+#if gcdGPU_TIMEOUT
+ && (timer < gcdGPU_TIMEOUT)
+#endif
+ );
+ /* Bail out on timeout. */
+ if (gcmIS_ERROR(status))
+ {
+ /* Broadcast the stuck GPU. */
+ gcmkONERROR(gckOS_Broadcast(os,
+ Command->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK));
+
+ gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+ }
+#endif
+
+ /* Delete the signal. */
+ gcmkONERROR(gckOS_DestroySignal(os, signal));
+ signal = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+#if VIVANTE_POWER_MANAGE
+ gcmkLOG_ERROR_ARGS("status=%d, signal=0x%08x, timer=%d", status, signal, timer);
+#else
+ gcmkLOG_ERROR_ARGS("status=%d, signal=0x%08x", status, signal);
+#endif
+ /* Free the signal. */
+ if (signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+
+ signal = gcvNULL;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_event.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_event.c
new file mode 100644
index 0000000..b92b043
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_event.c
@@ -0,0 +1,1746 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_user_context.h"
+
+#define _GC_OBJ_ZONE gcvZONE_EVENT
+
+#define gcdEVENT_ALLOCATION_COUNT (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
+#define gcdEVENT_MIN_THRESHOLD 4
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _GetEvent
+**
+** Get an empty event ID.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** gctUINT8 * EventID
+** Pointer to a variable that receives an empty event ID.
+*/
+static gceSTATUS
+_GetEvent(
+ IN gckEVENT Event,
+ OUT gctUINT8 * EventID,
+ IN gceKERNEL_WHERE Source
+ )
+{
+ gctINT i, id;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
+
+ /* Grab the queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->mutexQueue,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Walk through all events. */
+ id = Event->lastID;
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[id].head == gcvNULL)
+ {
+ *EventID = (gctUINT8) id;
+
+ Event->lastID = (id + 1) % gcmCOUNTOF(Event->queues);
+
+ /* Save time stamp of event. */
+ Event->queues[id].stamp = ++(Event->stamp);
+ Event->queues[id].source = Source;
+
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*EventID=%u", *EventID);
+ return gcvSTATUS_OK;
+ }
+
+ id = (id + 1) % gcmCOUNTOF(Event->queues);
+ }
+
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ acquired = gcvFALSE;
+
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+
+OnError:
+ if (acquired)
+ {
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#if VIVANTE_POWER_MANAGE
+static gceSTATUS
+_IsEmpty(
+ IN gckEVENT Event,
+ OUT gctBOOL_PTR IsEmpty
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T i;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
+
+ /* Assume the event queue is empty. */
+ *IsEmpty = gcvTRUE;
+
+ /* Walk the event queue. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ /* Check whether this event is in use. */
+ if (Event->queues[i].head != gcvNULL)
+ {
+ /* The event is in use, hence the queue is not empty. */
+ *IsEmpty = gcvFALSE;
+ break;
+ }
+ }
+
+ /* Try acquiring the mutex. */
+ status = gckOS_AcquireMutex(Event->os, Event->mutexQueue, 0);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Timeout - queue is no longer empty. */
+ *IsEmpty = gcvFALSE;
+ }
+ else
+ {
+ /* Bail out on error. */
+ gcmkONERROR(status);
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#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 event = gcvNULL;
+ int i;
+ gcsEVENT_PTR record;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Event != gcvNULL);
+
+ /* Extract the pointer to the gckOS object. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate the gckEVENT object. */
+ gcmkONERROR(
+ gckOS_Allocate(os,
+ gcmSIZEOF(struct _gckEVENT),
+ (gctPOINTER *) &event));
+
+ /* Initialize the gckEVENT object. */
+ event->object.type = gcvOBJ_EVENT;
+ event->kernel = Kernel;
+ event->os = os;
+ event->mutexQueue = gcvNULL;
+ event->freeList = gcvNULL;
+ event->freeCount = 0;
+ event->freeMutex = gcvNULL;
+ event->list.head = gcvNULL;
+ event->list.tail = gcvNULL;
+ event->listMutex = gcvNULL;
+ event->lastID = 0;
+
+ /* Construct atom holding number of event counts. */
+ event->atomEventRef= gcvNULL;
+ gcmkONERROR(
+ gckOS_AtomConstruct(os, &event->atomEventRef));
+
+ /* Create the mutexes. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &event->mutexQueue));
+
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &event->freeMutex));
+
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &event->listMutex));
+
+ /* Create a bunch of event reccords. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; ++i)
+ {
+ /* Allocate an event record. */
+ gcmkONERROR(
+ gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), (gctPOINTER *) &record));
+
+ /* Push it on the free list. */
+ record->next = event->freeList;
+ event->freeList = record;
+ event->freeCount += 1;
+ }
+
+ /* Zero out the entire event queue. */
+ for (i = 0; i < gcmCOUNTOF(event->queues); ++i)
+ {
+ event->queues[i].head = gcvNULL;
+ }
+
+ /* Zero out the time stamp. */
+ event->stamp = 0;
+
+ /* No events to handle. */
+ event->pending = 0;
+
+ /* Return pointer to the gckEVENT object. */
+ *Event = event;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Event=0x%x", *Event);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Roll back. */
+ if (event != gcvNULL)
+ {
+ if (event->atomEventRef != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, event->atomEventRef));
+ event->atomEventRef = gcvNULL;
+ }
+
+ if (event->mutexQueue != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->mutexQueue));
+ event->mutexQueue = gcvNULL;
+ }
+
+ if (event->freeMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->freeMutex));
+ event->freeMutex = gcvNULL;
+ }
+
+ if (event->listMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->listMutex));
+ event->listMutex = gcvNULL;
+ }
+
+ while (event->freeList != gcvNULL)
+ {
+ record = event->freeList;
+ event->freeList = record->next;
+
+ gcmkVERIFY_OK(gckOS_Free(os, record));
+ }
+ event->freeList = gcvNULL;
+
+ gcmkVERIFY_OK(gckOS_Free(os, event));
+ event = gcvNULL;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Destroy
+**
+** Destroy an gckEVENT object.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ )
+{
+ gcsEVENT_PTR record;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Detsroy the event counts atom. */
+ if (Event->atomEventRef != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->atomEventRef));
+ Event->atomEventRef = gcvNULL;
+ }
+
+ /* Delete the queue mutex. */
+ if (Event->mutexQueue != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->mutexQueue));
+ Event->mutexQueue = gcvNULL;
+ }
+
+ /* Free all free events. */
+ while (Event->freeList != gcvNULL)
+ {
+ record = Event->freeList;
+ Event->freeList = record->next;
+
+ gcmkVERIFY_OK(gckOS_Free(Event->os, record));
+ }
+
+ Event->freeList = gcvNULL;
+
+
+ /* Delete the free mutex. */
+ if(Event->freeMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeMutex));
+ Event->freeMutex = gcvNULL;
+ }
+
+ /* Free all pending events. */
+ while (Event->list.head != gcvNULL)
+ {
+ record = Event->list.head;
+ Event->list.head = record->next;
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_EVENT,
+ "Event record 0x%x is still pending for %d.",
+ record, Event->list.source);
+ gcmkVERIFY_OK(gckOS_Free(Event->os, record));
+ }
+
+ Event->list.head = gcvNULL;
+
+ /* Delete the list mutex. */
+ if(Event->listMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->listMutex));
+ Event->listMutex = gcvNULL;
+ }
+
+ /* Mark the gckEVENT object as unknown. */
+ Event->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckEVENT object. */
+ gcmkVERIFY_OK(gckOS_Free(Event->os, Event));
+
+ Event = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckEVENT_AllocateRecord(
+ IN gckEVENT Event,
+ OUT gcsEVENT_PTR * Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctINT i;
+ gcsEVENT_PTR record;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Test if we are below the allocation threshold. */
+ if (Event->freeCount < gcdEVENT_MIN_THRESHOLD)
+ {
+ /* Allocate a bunch of records. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; ++i)
+ {
+ /* Allocate an event record. */
+ status = gckOS_Allocate(Event->os,
+ gcmSIZEOF(gcsEVENT),
+ (gctPOINTER *) &record);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkLOG_WARNING_ARGS("status=%d, i=%d, Out of memory allocating event records",
+ status, i);
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_EVENT,
+ "Out of memory allocating event records.");
+ break;
+ }
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->freeMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Push it on the free list. */
+ record->next = Event->freeList;
+ Event->freeList = record;
+ Event->freeCount += 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+ acquired = gcvFALSE;
+ }
+ }
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ *Record = Event->freeList;
+ Event->freeList = Event->freeList->next;
+ Event->freeCount -= 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+ acquired = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeRecord(
+ IN gckEVENT Event,
+ IN gcsEVENT_PTR Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Push the record on the free list. */
+ Record->next = Event->freeList;
+ Event->freeList = Record;
+ Event->freeCount += 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckEVENT_AddList(
+ IN gckEVENT Event,
+ IN gcsHAL_INTERFACE_PTR Interface,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsEVENT_PTR record = gcvNULL;
+
+ gcmkHEADER_ARG("Event=0x%x Interface=0x%x FromWhere=%d",
+ Event, Interface, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ switch (FromWhere)
+ {
+ case gcvKERNEL_COMMAND:
+ case gcvKERNEL_PIXEL:
+ /* Check if the requested source matches the list. */
+ if ((Event->list.head != gcvNULL)
+ && (Event->list.source != FromWhere)
+ )
+ {
+ /* No match - auto-submit the list. */
+ status = gckEVENT_Submit(Event, gcvFALSE);
+
+ if (status == gcvSTATUS_OUT_OF_RESOURCES)
+ {
+ /* When we are out of resources, just convert to submit from
+ ** PIXEL. */
+ Event->list.source = FromWhere = gcvKERNEL_PIXEL;
+ }
+
+ else
+ {
+ /* Check for error. */
+ gcmkONERROR(status);
+ }
+ }
+ break;
+
+ default:
+ /* Invalid argument. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Allocate a free record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, &record));
+
+ /* Copy the event interface into the record. */
+ gcmkONERROR(gckOS_MemCopy(&record->event,
+ Interface,
+ gcmSIZEOF(record->event)));
+
+#if 0
+ gcmkASSERT
+ ( (Interface->command == gcvHAL_FREE_NON_PAGED_MEMORY)
+ || (Interface->command == gcvHAL_FREE_CONTIGUOUS_MEMORY)
+ || (Interface->command == gcvHAL_FREE_VIDEO_MEMORY)
+ || (Interface->command == gcvHAL_WRITE_DATA)
+ || (Interface->command == gcvHAL_UNLOCK_VIDEO_MEMORY)
+ || (Interface->command == gcvHAL_SIGNAL)
+ || (Interface->command == gcvHAL_UNMAP_USER_MEMORY)
+ );
+#endif
+
+ record->next = gcvNULL;
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->listMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (Event->list.head == gcvNULL)
+ {
+ /* List doesn't exist yet. */
+ Event->list.head = record;
+ Event->list.tail = record;
+ }
+ else
+ {
+ /* Append to the current list. */
+ Event->list.tail->next = record;
+ Event->list.tail = record;
+ }
+
+ /* Mark the source of this event. */
+ Event->list.source = FromWhere;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d, record=0x%08x", status, acquired, record);
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+ }
+
+ if (record != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeNonPagedMemory
+**
+** Schedule an event to free non-paged memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of non-paged memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of non-paged memory to free.
+**
+** gctPOINTER Logical
+** Logical address of non-paged memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
+ iface.u.FreeNonPagedMemory.bytes = Bytes;
+ iface.u.FreeNonPagedMemory.physical = Physical;
+ iface.u.FreeNonPagedMemory.logical = Logical;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeContigiuousMemory
+**
+** Schedule an event to free contiguous memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of contiguous memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of contiguous memory to free.
+**
+** gctPOINTER Logical
+** Logical address of contiguous memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY;
+ iface.u.FreeContiguousMemory.bytes = Bytes;
+ iface.u.FreeContiguousMemory.physical = Physical;
+ iface.u.FreeContiguousMemory.logical = Logical;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeVideoMemory
+**
+** Schedule an event to free video memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcuVIDMEM_NODE_PTR VideoMemory
+** Pointer to a gcuVIDMEM_NODE object to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+ IN gckEVENT Event,
+ IN gcuVIDMEM_NODE_PTR VideoMemory,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x VideoMemory=0x%x FromWhere=%d",
+ Event, VideoMemory, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(VideoMemory != gcvNULL);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_VIDEO_MEMORY;
+ iface.u.FreeVideoMemory.node = VideoMemory;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Signal
+**
+** Schedule an event to trigger a signal.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIGNAL Signal
+** Pointer to the signal to trigger.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+*/
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Signal=0x%x FromWhere=%d",
+ Event, Signal, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Mark the event as a signal. */
+ iface.command = gcvHAL_SIGNAL;
+ iface.u.Signal.signal = Signal;
+#ifdef __QNXNTO__
+ iface.u.Signal.coid = 0;
+ iface.u.Signal.rcvid = 0;
+#else
+ iface.u.Signal.auxSignal = gcvNULL;
+ iface.u.Signal.process = gcvNULL;
+#endif
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Unlock
+**
+** Schedule an event to unlock virtual memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union that specifies the virtual memory
+** to unlock.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+*/
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x FromWhere=%d Node=0x%x Type=%d",
+ Event, FromWhere, Node, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Mark the event as an unlock. */
+ iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
+ iface.u.UnlockVideoMemory.node = Node;
+ iface.u.UnlockVideoMemory.type = Type;
+ iface.u.UnlockVideoMemory.asynchroneous = 0;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckEVENT_Commit(
+ IN gckEVENT Event,
+ IN gcsQUEUE_PTR Queue
+ )
+{
+ gceSTATUS status;
+ gcsQUEUE_PTR record = gcvNULL, next;
+
+ gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ if(Queue == gcvNULL)
+ {
+#if !VIVANTE_POWER_MANAGE
+ /* Try to set idle */
+ gcmkVERIFY_OK(gckEVENT_TryToSetIdle(Event));
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#endif
+ }
+
+ /* Loop while there are records in the queue. */
+ while (Queue != gcvNULL)
+ {
+ /* Map record into kernel memory. */
+ gcmkONERROR(gckOS_MapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) &record));
+
+ /* Append event record to event queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL));
+
+ /* Next record in the queue. */
+ next = record->next;
+
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(
+ gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ record = gcvNULL;
+
+ Queue = next;
+ }
+
+ /* Submit the event list. */
+ gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE));
+
+ /* Success */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, record=0x%08x, Queue=0x%08x", status, record, Queue);
+ /* Roll back. */
+ if (record == gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+ IN gctUINT32 Data
+ )
+{
+ gcmkHEADER_ARG("Event=0x%x Data=%08x", Event, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Combine current interrupt status with pending flags. */
+ Event->pending |= Data;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctBOOL IsReset
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctINT i;
+ gcsEVENT_QUEUE * queue = gcvNULL;
+ gctUINT mask = 0;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL cmdAcquired = gcvFALSE;
+#ifdef __QNXNTO__
+ gcuVIDMEM_NODE_PTR node;
+#endif
+ gctUINT pending;
+ gctBOOL suspended = gcvFALSE;
+#if VIVANTE_POWER_MANAGE
+ gctBOOL empty = gcvFALSE, idle = gcvFALSE;
+#endif
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ for (;;)
+ {
+ /* Suspend interrupts. */
+ gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+ suspended = gcvTRUE;
+
+ /* Get current interrupts. */
+ pending = Event->pending;
+
+ /* Resume interrupts. */
+ gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+ suspended = gcvFALSE;
+
+ if (pending == 0)
+ {
+ /* No more pending interrupts - done. */
+ break;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Pending interrupts 0x%08x", pending);
+
+ queue = gcvNULL;
+
+#if gcdDEBUG
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Queue(%d): stamp=%llu source=%d",
+ i,
+ Event->queues[i].stamp,
+ Event->queues[i].source);
+ }
+ }
+#endif
+
+ /* Find the oldest pending interrupt. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if ((Event->queues[i].head != gcvNULL)
+ && (pending & (1 << i))
+ )
+ {
+ if ((queue == gcvNULL)
+ || (Event->queues[i].stamp < queue->stamp)
+ )
+ {
+ queue = &Event->queues[i];
+ mask = 1 << i;
+ }
+ }
+ }
+
+ if (queue == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Queue is null,interrupts 0x%08x are not pending", pending);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_EVENT,
+ "Interrupts 0x%08x are not pending.", pending);
+
+ 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)
+ )
+ {
+ gcmkLOG_WARNING_ARGS("Event %d lost (stamp %llu)",
+ i, Event->queues[i].stamp);
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "Event %d lost (stamp %llu)",
+ i, Event->queues[i].stamp);
+
+ /* Use this event instead. */
+ queue = &Event->queues[i];
+ mask = 0;
+ }
+ }
+
+ /* Walk all events for this interrupt. */
+ while (queue->head != gcvNULL)
+ {
+ gcsEVENT_PTR event;
+#ifndef __QNXNTO__
+ gctPOINTER logical;
+#endif
+
+ event = queue->head;
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "event->event.command: %d", event->event.command);
+ /* Dispatch on event type. */
+ switch (event->event.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ /* Free non-paged memory. */
+ status = gckOS_FreeNonPagedMemory(
+ Event->os,
+ event->event.u.FreeNonPagedMemory.bytes,
+ event->event.u.FreeNonPagedMemory.physical,
+ event->event.u.FreeNonPagedMemory.logical);
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ /* Unmap the user memory. */
+ status = gckOS_FreeContiguous(
+ Event->os,
+ event->event.u.FreeContiguousMemory.physical,
+ event->event.u.FreeContiguousMemory.logical,
+ event->event.u.FreeContiguousMemory.bytes);
+ break;
+
+ case gcvHAL_FREE_VIDEO_MEMORY:
+#ifdef __QNXNTO__
+ node = event->event.u.FreeVideoMemory.node;
+ if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ && (node->VidMem.logical != gcvNULL)
+ )
+ {
+ gcmkERR_BREAK(
+ gckKERNEL_UnmapVideoMemory(event->kernel,
+ node->VidMem.logical,
+ event->event.pid,
+ node->VidMem.bytes));
+ node->VidMem.logical = gcvNULL;
+ }
+#endif
+
+ /* Free video memory. */
+ status = gckVIDMEM_Free(event->event.u.FreeVideoMemory.node);
+ break;
+
+ case gcvHAL_WRITE_DATA:
+#ifndef __QNXNTO__
+ /* Convert physical into logical address. */
+ gcmkERR_BREAK(
+ gckOS_MapPhysical(Event->os,
+ event->event.u.WriteData.address,
+ gcmPTR2INT(event->event.u.WriteData.kernelAddress),
+ gcmSIZEOF(gctUINT32),
+ &logical));
+
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ logical,
+ event->event.u.WriteData.data));
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(
+ gckOS_UnmapPhysical(Event->os,
+ logical,
+ gcmSIZEOF(gctUINT32)));
+#else
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ (gctPOINTER)
+ event->event.u.WriteData.address,
+ event->event.u.WriteData.data));
+#endif
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ /* Unlock. */
+ status = gckVIDMEM_Unlock(event->event.u.UnlockVideoMemory.node,
+ event->event.u.UnlockVideoMemory.type,
+ gcvNULL);
+ break;
+
+ case gcvHAL_SIGNAL:
+#ifdef __QNXNTO__
+ if ((event->event.u.Signal.coid == 0)
+ && (event->event.u.Signal.rcvid == 0)
+ )
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_Signal(Event->os,
+ event->event.u.Signal.signal,
+ gcvTRUE));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ event->event.u.Signal.signal,
+ event->event.u.Signal.rcvid,
+ event->event.u.Signal.coid));
+ }
+#else
+ /* Set signal. */
+ if (event->event.u.Signal.process == gcvNULL)
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_Signal(Event->os,
+ event->event.u.Signal.signal,
+ gcvTRUE));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ event->event.u.Signal.signal,
+ event->event.u.Signal.process));
+ }
+
+ gcmkASSERT(event->event.u.Signal.auxSignal == gcvNULL);
+#endif
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ /* Unmap the user memory. */
+ status =
+ gckOS_UnmapUserMemory(Event->os,
+ event->event.u.UnmapUserMemory.memory,
+ event->event.u.UnmapUserMemory.size,
+ event->event.u.UnmapUserMemory.info,
+ event->event.u.UnmapUserMemory.address);
+ break;
+
+ case gcvHAL_SET_IDLE:
+ if(!IsReset)
+ {
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireRecMutex(Event->os,
+ Event->kernel->hardware->recMutexPower,
+ gcvINFINITE));
+ cmdAcquired = gcvTRUE;
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "lastCommitStamp=%llu commitStamp=%llu",
+ Event->lastCommitStamp, Event->kernel->command->commitStamp);
+
+ /* Set idle if no new commitments */
+ if (Event->lastCommitStamp == Event->kernel->command->commitStamp)
+ {
+ if(Event->kernel->command->idle == gcvFALSE)
+ {
+ Event->kernel->command->idle = gcvTRUE;
+ gcmkVERIFY_OK(gckOS_NotifyIdle(Event->os, gcvTRUE));
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(Event->os, Event->kernel->hardware->recMutexPower));
+ cmdAcquired = gcvFALSE;
+ }
+ break;
+
+ default:
+ /* Invalid argument. */
+ gcmkFATAL("Unknown event type: %d", event->event.command);
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+ /* Make sure there are no errors generated. */
+ gcmkASSERT(gcmNO_ERROR(status));
+
+ /* Pop the event from the event queue. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Event->os, Event->mutexQueue, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Unlink head from chain. */
+ queue->head = event->next;
+
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ acquired = gcvFALSE;
+
+ /* Free the event. */
+ gcmkVERIFY_OK(gckOS_Free(Event->os, event));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Handled interrupt 0x%08x", mask);
+
+ /* Suspend interrupts. */
+ gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+ suspended = gcvTRUE;
+
+ /* Mark pending interrupt as handled. */
+ Event->pending &= ~mask;
+
+ /* Resume interrupts. */
+ gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+ suspended = gcvFALSE;
+ }
+
+ if(!IsReset)
+ {
+#if VIVANTE_POWER_MANAGE
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireRecMutex(Event->os,
+ Event->kernel->hardware->recMutexPower,
+ gcvINFINITE));
+ cmdAcquired = gcvTRUE;
+
+ /* Check whether the event queue is empty. */
+ gcmkONERROR(_IsEmpty(Event, &empty));
+
+ if (empty)
+ {
+ /* Query whether the hardware is idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
+
+ if (idle)
+ {
+ if(Event->kernel->command->idle == gcvFALSE)
+ {
+ Event->kernel->command->idle = gcvTRUE;
+ gcmkVERIFY_OK(gckOS_NotifyIdle(Event->os, gcvTRUE));
+ }
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(Event->os, Event->kernel->hardware->recMutexPower));
+ cmdAcquired = gcvFALSE;
+#else
+ {
+ /* Try to set idle */
+ gcmkVERIFY_OK(gckEVENT_TryToSetIdle(Event));
+ }
+#endif
+ }
+
+ {
+ gctINT32 old = 0;
+ /* Increment the number of event counts. */
+ gcmkONERROR(
+ gckOS_AtomIncrement(Event->kernel->os, Event->atomEventRef, &old));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d, suspended=%d, queue=0x%08x",
+ status, acquired, suspended, queue);
+ if (acquired)
+ {
+ /* Release mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ }
+
+ if (suspended)
+ {
+ /* Resume interrupts. */
+ gcmkVERIFY_OK(gckOS_ResumeInterrupt(Event->os));
+ }
+
+ if (cmdAcquired)
+ {
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(Event->os, Event->kernel->hardware->recMutexPower));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckEVENT_Submit(
+ IN gckEVENT Event,
+ IN gctBOOL Wait
+ )
+{
+ gctUINT8 id = 0xFF;
+ gctSIZE_T bytes;
+ gctPOINTER buffer;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL reserved = gcvFALSE;
+#if gcdGPU_TIMEOUT
+ gctUINT32 timer = 0;
+#endif
+
+ gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
+
+ /* Only process if we have events queued. */
+ if (Event->list.head != gcvNULL)
+ {
+ for (;;)
+ {
+ /* Allocate an event ID. */
+ status = _GetEvent(Event, &id, Event->list.source);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Out of resources? */
+ if (Wait && (status == gcvSTATUS_OUT_OF_RESOURCES))
+ {
+ /* Delay a while. */
+ gcmkONERROR(gckOS_Delay(Event->os, 1));
+
+#if gcdGPU_TIMEOUT && VIVANTE_POWER_MANAGE
+ if (++timer >= gcdGPU_TIMEOUT)
+ {
+ gcmkONERROR(gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK));
+
+ gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+ }
+#endif
+ }
+ else
+ {
+ gcmkONERROR(status);
+ }
+ }
+ else
+ {
+ /* Got en event ID. */
+ break;
+ }
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_EVENT, "Using id=%d", id);
+
+ /* Acquire the list mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->listMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Copy event list to event ID queue. */
+ Event->queues[id].source = Event->list.source;
+ Event->queues[id].head = Event->list.head;
+
+ /* Get process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&Event->queues[id].processID));
+
+ /* Mark event list as empty. */
+ Event->list.head = gcvNULL;
+
+ /* Release the list mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+ acquired = gcvFALSE;
+
+#if gcdNULL_DRIVER == 2
+ /* Notify immediately on infinite hardware. */
+ gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
+
+ gcmkONERROR(gckEVENT_Notify(Event, 0));
+#else
+ /* Get the size of the hardware event. */
+ gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
+ gcvNULL,
+ id,
+ gcvKERNEL_PIXEL,
+ &bytes));
+
+ /* Reserve space in the command queue. */
+ gcmkONERROR(gckCOMMAND_Reserve(Event->kernel->command,
+ bytes,
+ &buffer,
+ &bytes));
+ reserved = gcvTRUE;
+
+ /* Set the hardware event in the command queue. */
+ gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
+ buffer,
+ id,
+ Event->queues[id].source,
+ &bytes));
+
+ /* Execute the hardware event. */
+ gcmkONERROR(gckCOMMAND_Execute(Event->kernel->command, bytes));
+ reserved = gcvFALSE;
+#endif
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d, reserved=%d, eventId=%d",
+ status, acquired, reserved, id);
+ if (acquired)
+ {
+ /* Need to unroll the mutex acquire. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+ }
+
+ if (reserved)
+ {
+ /* Need to release the command buffer. */
+ gcmkVERIFY_OK(gckCOMMAND_Release(Event->kernel->command));
+ }
+
+ if (id != 0xFF)
+ {
+ /* Need to unroll the event allocation. */
+ Event->queues[id].head = gcvNULL;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_SetIdle
+**
+** Schedule an event to set idle status.
+**
+** INPUT:
+**
+** gcoEVENT Event
+** Pointer to an gcoEVENT object.
+**
+** gctPOINTER CommandBuffer
+** Pointer to the command buffer to append the event.
+**
+** gctSIZE_T * CommandSize
+** Pointer to the number of bytes available in the command buffer.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** gctBOOL Wait
+** Wait flag. Should be set to gcvFALSE for any event that needs to be
+** copied into a command buffer since we might exhaust the number of
+** events.
+**
+** OUTPUT:
+**
+** gctSIZE_T * CommandSize
+** Number of bytes used for the event.
+*/
+gceSTATUS
+gckEVENT_SetIdle(
+ IN gckEVENT Event,
+ IN gctPOINTER CommandBuffer,
+ IN OUT gctSIZE_T * CommandSize,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctBOOL Wait
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkHEADER_ARG("Event=0x%x CommandBuffer=0x%x CommandSize=0x%x FromWhere=%d Wait=%d",
+ Event, CommandBuffer, CommandSize, FromWhere, Wait);
+
+ /* Create an event. */
+ iface.command = gcvHAL_SET_IDLE;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#define ENABLE_COMMITSTAMP_CHECK 0
+gceSTATUS
+gckEVENT_TryToSetIdle(
+ IN gckEVENT Event
+ )
+{
+ gctINT i = -1;
+ gctBOOL setIdle;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ if (!Event->kernel->notifyIdle)
+ {
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Initialize the flag */
+ setIdle = gcvFALSE;
+
+ /* Grab the queue mutex. */
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Event->os,
+ Event->mutexQueue,
+ gcvINFINITE));
+
+ /* Suspend interrupt */
+ gcmkVERIFY_OK(gckOS_SuspendInterrupt(Event->os));
+
+ /*
+ FIXME: this check may cause system enter into idle status every 120 seconds in home screen scenario on TD,
+ Temp solution -- disable this.
+ */
+#if ENABLE_COMMITSTAMP_CHECK
+ if (Event->lastCommitStamp != Event->kernel->command->commitStamp)
+#endif
+ {
+ setIdle = gcvTRUE;
+
+ /* Check if no pending events */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ setIdle = gcvFALSE;
+ break;
+ }
+ }
+ }
+
+ /* Resume interrupt */
+ gcmkVERIFY_OK(gckOS_ResumeInterrupt(Event->os));
+
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+
+ /* Issue an event to set idle if necessary */
+ if (setIdle)
+ {
+ /* Grab the conmmand queue mutex. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Event->kernel->command->os,
+ Event->kernel->command->mutexQueue,
+ gcvINFINITE));
+
+ /* Append the EVENT command to write data into the boolean. */
+ gcmkVERIFY_OK(gckEVENT_SetIdle(Event,
+ gcvNULL,
+ 0,
+ gcvKERNEL_PIXEL,
+ gcvTRUE));
+
+ Event->lastCommitStamp = Event->kernel->command->commitStamp + 1;
+
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Event->kernel->command->os, Event->kernel->command->mutexQueue));
+
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("i=%d setIdle=%d", i, setIdle);
+ return gcvSTATUS_OK;
+}
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_heap.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_heap.c
new file mode 100644
index 0000000..78e95fd
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_heap.c
@@ -0,0 +1,1079 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/**
+** @file
+** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
+** based memory allocation. An arena-based memory heap allocates data quickly
+** from specified arenas and reduces memory fragmentation.
+**
+*/
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_HEAP
+
+/*******************************************************************************
+***** Structures ***************************************************************
+*******************************************************************************/
+
+#define gcdIN_USE ((gcskNODE_PTR) ~0)
+
+typedef struct _gcskNODE * gcskNODE_PTR;
+typedef struct _gcskNODE
+{
+ /* Number of byets in node. */
+ gctSIZE_T bytes;
+
+ /* Pointer to next free node, or gcvNULL to mark the node as freed, or
+ ** gcdIN_USE to mark the node as used. */
+ gcskNODE_PTR next;
+
+#if gcdDEBUG
+ /* Time stamp of allocation. */
+ gctUINT64 timeStamp;
+#endif
+}
+gcskNODE;
+
+typedef struct _gcskHEAP * gcskHEAP_PTR;
+typedef struct _gcskHEAP
+{
+ /* Linked list. */
+ gcskHEAP_PTR next;
+ gcskHEAP_PTR prev;
+
+ /* Heap size. */
+ gctSIZE_T size;
+
+ /* Free list. */
+ gcskNODE_PTR freeList;
+}
+gcskHEAP;
+
+struct _gckHEAP
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to a gckOS object. */
+ gckOS os;
+
+ /* Locking mutex. */
+ gctPOINTER mutex;
+
+ /* Allocation parameters. */
+ gctSIZE_T allocationSize;
+
+ /* Heap list. */
+ gcskHEAP_PTR heap;
+#if gcdDEBUG
+ gctUINT64 timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Profile information. */
+ gctUINT32 allocCount;
+ gctUINT64 allocBytes;
+ gctUINT64 allocBytesMax;
+ gctUINT64 allocBytesTotal;
+ gctUINT32 heapCount;
+ gctUINT32 heapCountMax;
+ gctUINT64 heapMemory;
+ gctUINT64 heapMemoryMax;
+#endif
+};
+
+/*******************************************************************************
+***** Static Support Functions *************************************************
+*******************************************************************************/
+
+#if gcdDEBUG
+static gctSIZE_T
+_DumpHeap(
+ IN gcskHEAP_PTR Heap
+ )
+{
+ gctPOINTER p;
+ gctSIZE_T leaked = 0;
+
+ /* Start at first node. */
+ for (p = Heap + 1;;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ /* Check if this is a used node. */
+ if (node->next == gcdIN_USE)
+ {
+ /* Print the leaking node. */
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
+ "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
+ "(%08X %c%c%c%c)",
+ node, node->bytes, node->timeStamp,
+ ((gctUINT32_PTR) (node + 1))[0],
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
+
+ /* Add leaking byte count. */
+ leaked += node->bytes;
+ }
+
+ /* Test for end of heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ else
+ {
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+ }
+
+ /* Return the number of leaked bytes. */
+ return leaked;
+}
+#endif
+
+static gceSTATUS
+_CompactKernelHeap(
+ IN gckHEAP Heap
+ )
+{
+ gceSTATUS status;
+ gcskHEAP_PTR heap, next;
+ gctPOINTER p;
+ gcskHEAP_PTR freeList = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = next)
+ {
+ gcskNODE_PTR lastFree = gcvNULL;
+
+ /* Zero out the free list. */
+ heap->freeList = gcvNULL;
+
+ /* Start at the first node. */
+ for (p = (gctUINT8_PTR) (heap + 1);;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
+
+ /* Test if this node not used. */
+ if (node->next != gcdIN_USE)
+ {
+ /* Test if this is the end of the heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ /* Test of this is the first free node. */
+ else if (lastFree == gcvNULL)
+ {
+ /* Initialzie the free list. */
+ heap->freeList = node;
+ lastFree = node;
+ }
+
+ else
+ {
+ /* Test if this free node is contiguous with the previous
+ ** free node. */
+ if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
+ {
+ /* Just increase the size of the previous free node. */
+ lastFree->bytes += node->bytes;
+ }
+ else
+ {
+ /* Add to linked list. */
+ lastFree->next = node;
+ lastFree = node;
+ }
+ }
+ }
+
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+
+ /* Mark the end of the chain. */
+ if (lastFree != gcvNULL)
+ {
+ lastFree->next = gcvNULL;
+ }
+
+ /* Get next heap. */
+ next = heap->next;
+
+ /* Check if the entire heap is free. */
+ if ((heap->freeList != gcvNULL)
+ && (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
+ )
+ {
+ /* Remove the heap from the linked list. */
+ if (heap->prev == gcvNULL)
+ {
+ Heap->heap = next;
+ }
+ else
+ {
+ heap->prev->next = next;
+ }
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profiling. */
+ Heap->heapCount -= 1;
+ Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
+#endif
+
+ /* Add this heap to the list of heaps that need to be freed. */
+ heap->next = freeList;
+ freeList = heap;
+ }
+ }
+
+ if (freeList != gcvNULL)
+ {
+ /* Release the mutex, remove any chance for a dead lock. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Free all heaps in the free list. */
+ for (heap = freeList; heap != gcvNULL; heap = next)
+ {
+ /* Get pointer to the next heap. */
+ next = heap->next;
+
+ /* Free the heap. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Freeing heap 0x%x (%lu bytes)",
+ heap, heap->size + gcmSIZEOF(gcskHEAP));
+ gcmkONERROR(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Acquire the mutex again. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+***** gckHEAP API Code *********************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHEAP_Construct
+**
+** Construct a new gckHEAP object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctSIZE_T AllocationSize
+** Minimum size per arena.
+**
+** OUTPUT:
+**
+** gckHEAP * Heap
+** Pointer to a variable that will hold the pointer to the gckHEAP
+** object.
+*/
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ )
+{
+ gceSTATUS status;
+ gckHEAP heap = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
+
+ /* Allocate the gckHEAP object. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Os,
+ gcmSIZEOF(struct _gckHEAP),
+ (gctPOINTER *) &heap));
+
+ /* Initialize the gckHEAP object. */
+ heap->object.type = gcvOBJ_HEAP;
+ heap->os = Os;
+ heap->allocationSize = AllocationSize;
+ heap->heap = gcvNULL;
+#if gcdDEBUG
+ heap->timeStamp = 0;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Zero the counters. */
+ heap->allocCount = 0;
+ heap->allocBytes = 0;
+ heap->allocBytesMax = 0;
+ heap->allocBytesTotal = 0;
+ heap->heapCount = 0;
+ heap->heapCountMax = 0;
+ heap->heapMemory = 0;
+ heap->heapMemoryMax = 0;
+#endif
+
+ /* Create the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
+
+ /* Return the pointer to the gckHEAP object. */
+ *Heap = heap;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Heap=0x%x", Heap);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, *Heap=0x%08x", status, Heap);
+ /* Roll back. */
+ if (heap != gcvNULL)
+ {
+ /* Free the heap structure. */
+ gcmkERR_RETURN(gckOS_FreeMemory(Os, heap));
+ heap = gcvNULL;
+ }
+
+ /* 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
+ )
+{
+ gceSTATUS status;
+ gcskHEAP_PTR heap;
+#if gcdDEBUG
+ gctSIZE_T leaked = 0;
+#endif
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
+ {
+ /* Unlink heap from linked list. */
+ Heap->heap = heap->next;
+
+#if gcdDEBUG
+ /* Check for leaked memory. */
+ leaked += _DumpHeap(heap);
+#endif
+
+ /* Free the heap. */
+ gcmkONERROR(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Free the mutex. */
+ if(Heap->mutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
+ Heap->mutex = gcvNULL;
+ }
+
+ /* Free the heap structure. */
+ gcmkONERROR(gckOS_FreeMemory(Heap->os, Heap));
+ Heap = gcvNULL;
+
+ /* Success. */
+#if gcdDEBUG
+ gcmkFOOTER_ARG("leaked=%lu", leaked);
+#else
+ gcmkFOOTER_NO();
+#endif
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Allocate
+**
+** Allocate data from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the address of the allocated
+** memory.
+*/
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctBOOL acquired = gcvFALSE;
+ gcskHEAP_PTR heap;
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gcskNODE_PTR node, used, prevFree = gcvNULL;
+ gctPOINTER memory = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Determine number of bytes required for a node. */
+ bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Check if this allocation is bigger than the default allocation size. */
+ if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP))
+ {
+ /* Adjust allocation size. */
+ Heap->allocationSize = bytes * 2;
+ }
+
+ else if (Heap->heap != gcvNULL)
+ {
+ gctINT i;
+
+ /* 2 retries, since we might need to compact. */
+ for (i = 0; i < 2; ++i)
+ {
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
+ {
+ /* Check if this heap has enough bytes to hold the request. */
+ if (bytes < heap->size)
+ {
+ prevFree = gcvNULL;
+
+ /* Walk the chain of free nodes. */
+ for (node = heap->freeList;
+ node != gcvNULL;
+ node = node->next
+ )
+ {
+ gcmkASSERT(node->next != gcdIN_USE);
+
+ /* Check if this free node has enough bytes. */
+ if (node->bytes >= bytes)
+ {
+ /* Use the node. */
+ goto UseNode;
+ }
+
+ /* Save current free node for linked list management. */
+ prevFree = node;
+ }
+ }
+ }
+
+ if (i == 0)
+ {
+ /* Compact the heap. */
+ gcmkVERIFY_OK(_CompactKernelHeap(Heap));
+
+#if gcdDEBUG
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "===== KERNEL HEAP =====");
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of allocations : %12u",
+ Heap->allocCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of bytes allocated : %12llu",
+ Heap->allocBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum allocation size : %12llu",
+ Heap->allocBytesMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Total number of bytes allocated : %12llu",
+ Heap->allocBytesTotal);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of heaps : %12u",
+ Heap->heapCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Heap memory in bytes : %12llu",
+ Heap->heapMemory);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum number of heaps : %12u",
+ Heap->heapCountMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum heap memory in bytes : %12llu",
+ Heap->heapMemoryMax);
+#endif
+ }
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ acquired = gcvFALSE;
+
+ /* Allocate a new heap. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Heap->os,
+ Heap->allocationSize,
+ &memory));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Allocated heap 0x%x (%lu bytes)",
+ memory, Heap->allocationSize);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Use the allocated memory as the heap. */
+ heap = (gcskHEAP_PTR) memory;
+
+ /* Insert this heap to the head of the chain. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap;
+ }
+ Heap->heap = heap;
+
+ /* Mark the end of the heap. */
+ node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
+ + Heap->allocationSize
+ - gcmSIZEOF(gcskNODE)
+ );
+ node->bytes = 0;
+ node->next = gcvNULL;
+
+ /* Create a free list. */
+ node = (gcskNODE_PTR) (heap + 1);
+ heap->freeList = node;
+
+ /* Initialize the free list. */
+ node->bytes = heap->size - gcmSIZEOF(gcskNODE);
+ node->next = gcvNULL;
+
+ /* No previous free. */
+ prevFree = gcvNULL;
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profiling. */
+ Heap->heapCount += 1;
+ Heap->heapMemory += Heap->allocationSize;
+
+ if (Heap->heapCount > Heap->heapCountMax)
+ {
+ Heap->heapCountMax = Heap->heapCount;
+ }
+ if (Heap->heapMemory > Heap->heapMemoryMax)
+ {
+ Heap->heapMemoryMax = Heap->heapMemory;
+ }
+#endif
+
+UseNode:
+ /* Verify some stuff. */
+ gcmkASSERT(heap != gcvNULL);
+ gcmkASSERT(node != gcvNULL);
+ gcmkASSERT(node->bytes >= bytes);
+
+ if (heap->prev != gcvNULL)
+ {
+ /* Unlink the heap from the linked list. */
+ heap->prev->next = heap->next;
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+ /* Move the heap to the front of the list. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ Heap->heap = heap;
+ heap->next->prev = heap;
+ }
+
+ /* Check if there is enough free space left after usage for another free
+ ** node. */
+ if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
+ {
+ /* Allocated used space from the back of the free list. */
+ used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
+
+ /* Adjust the number of free bytes. */
+ node->bytes -= bytes;
+ gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
+ }
+ else
+ {
+ /* Remove this free list from the chain. */
+ if (prevFree == gcvNULL)
+ {
+ heap->freeList = node->next;
+ }
+ else
+ {
+ prevFree->next = node->next;
+ }
+
+ /* Consume the entire free node. */
+ used = (gcskNODE_PTR) node;
+ bytes = node->bytes;
+ }
+
+ /* Mark node as used. */
+ used->bytes = bytes;
+ used->next = gcdIN_USE;
+#if gcdDEBUG
+ used->timeStamp = ++Heap->timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profile counters. */
+ Heap->allocCount += 1;
+ Heap->allocBytes += bytes;
+ Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
+ Heap->allocBytesTotal += bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Return pointer to memory. */
+ *Memory = used + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+ }
+
+ if (memory != gcvNULL)
+ {
+ /* Free the heap memory. */
+ gcmkERR_RETURN(gckOS_FreeMemory(Heap->os, memory));
+ memory = gcvNULL;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Free
+**
+** Free allocated memory from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctPOINTER Memory
+** Pointer to memory to free.
+**
+** OUTPUT:
+**
+** NOTHING.
+*/
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Memory
+ )
+{
+ gcskNODE_PTR node;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ /* Pointer to structure. */
+ node = (gcskNODE_PTR) Memory - 1;
+
+ /* Mark the node as freed. */
+ node->next = gcvNULL;
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profile counters. */
+ Heap->allocBytes -= node->bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+
+ /* Zero the counters. */
+ Heap->allocCount = 0;
+ Heap->allocBytes = 0;
+ Heap->allocBytesMax = 0;
+ Heap->allocBytesTotal = 0;
+ Heap->heapCount = 0;
+ Heap->heapCountMax = 0;
+ Heap->heapMemory = 0;
+ Heap->heapMemoryMax = 0;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Title != gcvNULL);
+
+ gcmkPRINT("");
+ gcmkPRINT("=====[ HEAP - %s ]=====", Title);
+ gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
+ gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
+ gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
+ gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
+ gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
+ gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
+ gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
+ gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
+ gcmkPRINT("==============================================");
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif /* VIVANTE_PROFILER */
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
+#if defined gcdHAL_TEST
+
+#include <stdlib.h>
+#define gcmRANDOM(n) (rand() % n)
+
+typedef struct
+{
+ gctSIZE_T bytes;
+ gctPOINTER memory;
+}
+gcskHEAP_TEST;
+
+gceSTATUS
+gckHEAP_Test(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Vectors,
+ IN gctSIZE_T MaxSize
+ )
+{
+ gctSIZE_T nodeCount = MaxSize / 4;
+ gcskHEAP_TEST * nodes = gcvNULL;
+ gctSIZE_T bytes, index, i;
+ gceSTATUS status, failure = gcvSTATUS_OK;
+ gctUINT8_PTR memory;
+ gcskHEAP_PTR heap, current;
+
+ /* Allocate the node array. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Heap->os,
+ nodeCount * gcmSIZEOF(gcskHEAP_TEST),
+ (gctPOINTER *) &nodes));
+
+ /* Mark all nodes as free. */
+ gcmkONERROR(
+ gckOS_ZeroMemory(nodes, nodeCount * gcmSIZEOF(gcskHEAP_TEST)));
+
+ gcmkONERROR(gckHEAP_ProfileStart(Heap));
+
+ /* Loop through all vectors. */
+ while (Vectors-- > 0)
+ {
+ /* Get a random index. */
+ index = gcmRANDOM(nodeCount);
+
+ /* Test if we need to allocate pages. */
+ if (nodes[index].bytes == 0)
+ {
+ /* Generate a random byte size. */
+ do
+ {
+ bytes = gcmALIGN(gcmRANDOM(MaxSize), gcmSIZEOF(gctSIZE_T));
+ }
+ while (bytes == 0);
+
+ /* Allocate pages. */
+ status = gckHEAP_Allocate(Heap, bytes, (gctPOINTER *) &memory);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Mark node as allocated. */
+ nodes[index].bytes = bytes;
+ nodes[index].memory = memory;
+
+ /* Put signature in the memory. */
+ for (i = 0; i < bytes; i += gcmSIZEOF(gctSIZE_T))
+ {
+ *(gctSIZE_T_PTR) (memory + i) = index;
+ }
+ }
+ else
+ {
+ gcmkTRACE(gcvLEVEL_WARNING,
+ "%s(%d): Failed to allocate %lu bytes",
+ __FUNCTION__, __LINE__, bytes);
+ }
+ }
+ else
+ {
+ /* Verify the memory. */
+ memory = nodes[index].memory;
+ for (i = 0; i < nodes[index].bytes; i += gcmSIZEOF(gctSIZE_T))
+ {
+ if (*(gctSIZE_T_PTR) (memory + i) != index)
+ {
+ gcmkFATAL("%s(%d): Corruption detected at index %lu",
+ __FUNCTION__, __LINE__, index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the memory. */
+ status = gckHEAP_Free(Heap, memory);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("%s(%d): Cannot free %lu bytes at 0x%x (index=%lu)",
+ __FUNCTION__, __LINE__,
+ nodes[index].bytes, memory, index);
+
+ failure = status;
+ }
+
+ /* Mark the node as free. */
+ nodes[index].bytes = 0;
+ }
+
+ /* Verify the heap chain. */
+ i = 0;
+ for (current = Heap->heap; current != gcvNULL; current = current->next)
+ {
+ gctSIZE_T j;
+ for (heap = Heap->heap, j = 0; j < i; heap = heap->next, ++j)
+ {
+ if (heap == current)
+ {
+ gcmkFATAL("%s(%d): Linked list corrupted for heap 0x%x",
+ __FUNCTION__, __LINE__, current);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ if (heap != current)
+ {
+ gcmkFATAL("%s(%d): Linked list corrupted for heap 0x%x",
+ __FUNCTION__, __LINE__, current);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+ ++i;
+ }
+ }
+
+ /* Walk the entire array of nodes. */
+ for (index = 0; index < nodeCount; ++index)
+ {
+ /* Test if we need to free pages. */
+ if (nodes[index].bytes != 0)
+ {
+ /* Verify the memory. */
+ memory = nodes[index].memory;
+ for (i = 0; i < nodes[index].bytes; i += gcmSIZEOF(gctSIZE_T))
+ {
+ if (*(gctSIZE_T_PTR) (memory + i) != index)
+ {
+ gcmkFATAL("%s(%d): Corruption detected at page %lu",
+ __FUNCTION__, __LINE__, index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the memory. */
+ status = gckHEAP_Free(Heap, memory);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("%s(%d): Cannot free %u bytes at 0x%x (index=%lu)",
+ __FUNCTION__, __LINE__,
+ nodes[index].bytes, memory, index);
+
+ failure = status;
+ }
+ }
+ }
+
+ /* Perform garbage collection. */
+ gcmkONERROR(_CompactKernelHeap(Heap));
+
+ /* Show profiling. */
+ gcmkONERROR(gckHEAP_ProfileEnd(Heap, "Profile"));
+
+ /* Verify we did not loose any nodes. */
+ if (Heap->heap != gcvNULL)
+ {
+ gcmkFATAL("%s(%d): Detected leaking in the heap.",
+ __FUNCTION__, __LINE__);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+OnError:
+ /* Roll back. */
+ if (nodes != gcvNULL)
+ {
+ gcmkERR_RETURN(
+ gckOS_FreeMemory(Heap->os, nodes));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_mmu.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_mmu.c
new file mode 100644
index 0000000..a4f8e2e
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_mmu.c
@@ -0,0 +1,962 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_MMU
+
+typedef enum _gceMMU_TYPE
+{
+ gcvMMU_USED = 0,
+ gcvMMU_SINGLE,
+ gcvMMU_FREE,
+}
+gceMMU_TYPE;
+
+static gceSTATUS
+_Link(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 Next
+ )
+{
+ if (Index >= Mmu->pageTableEntries)
+ {
+ /* Just move heap pointer. */
+ Mmu->heapList = Next;
+ }
+ else
+ {
+ /* Address page table. */
+ gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+
+ /* Dispatch on node type. */
+ switch (pageTable[Index] & 0xFF)
+ {
+ case gcvMMU_SINGLE:
+ /* Set single index. */
+ pageTable[Index] = (Next << 8) | gcvMMU_SINGLE;
+ break;
+
+ case gcvMMU_FREE:
+ /* Set index. */
+ pageTable[Index + 1] = Next;
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", Index);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_AddFree(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 Node,
+ IN gctUINT32 Count
+ )
+{
+ gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+
+ if (Count == 1)
+ {
+ /* Initialize a single page node. */
+ pageTable[Node] = (~0U << 8) | gcvMMU_SINGLE;
+ }
+ else
+ {
+ /* Initialize the node. */
+ pageTable[Node + 0] = (Count << 8) | gcvMMU_FREE;
+ pageTable[Node + 1] = ~0U;
+ }
+
+ /* Append the node. */
+ return _Link(Mmu, Index, Node);
+}
+
+static gceSTATUS
+_Collect(
+ IN gckMMU Mmu
+ )
+{
+ gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+ gceSTATUS status;
+ gctUINT32 i, previous, start = 0, count = 0;
+
+ /* Flush the MMU cache. */
+ gcmkONERROR(
+ gckHARDWARE_FlushMMU(Mmu->hardware));
+
+ previous = Mmu->heapList = ~0U;
+ Mmu->freeNodes = gcvFALSE;
+
+ /* Walk the entire page table. */
+ for (i = 0; i < Mmu->pageTableEntries; ++i)
+ {
+ /* Dispatch based on type of page. */
+ switch (pageTable[i] & 0xFF)
+ {
+ case gcvMMU_USED:
+ /* Used page, so close any open node. */
+ if (count > 0)
+ {
+ /* Add the node. */
+ gcmkONERROR(_AddFree(Mmu, previous, start, count));
+
+ /* Reset the node. */
+ previous = start;
+ count = 0;
+ }
+ break;
+
+ case gcvMMU_SINGLE:
+ /* Single free node. */
+ if (count++ == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* A free node. */
+ if (count == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+
+ /* Advance the count. */
+ count += pageTable[i] >> 8;
+
+ /* Advance the index into the page table. */
+ i += (pageTable[i] >> 8) - 1;
+ break;
+
+ default:
+ gcmkFATAL("MMU page table correcupted at index %u!", i);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* See if we have an open node left. */
+ if (count > 0)
+ {
+ /* Add the node to the list. */
+ gcmkONERROR(_AddFree(Mmu, previous, start, count));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
+ "Performed a garbage collection of the MMU heap.");
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the staus. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_Construct
+**
+** Construct a new gckMMU object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T MmuSize
+** Number of bytes for the page table.
+**
+** OUTPUT:
+**
+** gckMMU * Mmu
+** Pointer to a variable that receives the gckMMU object pointer.
+*/
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ )
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gckMMU mmu = gcvNULL;
+ gctUINT32_PTR pageTable;
+
+ gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(MmuSize > 0);
+ gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Allocate memory for the gckMMU object. */
+ gcmkONERROR(
+ gckOS_Allocate(os, sizeof(struct _gckMMU), (gctPOINTER *) &mmu));
+
+ /* Initialize the gckMMU object. */
+ mmu->object.type = gcvOBJ_MMU;
+ mmu->os = os;
+ mmu->hardware = hardware;
+ mmu->pageTableMutex = gcvNULL;
+ mmu->pageTableLogical = gcvNULL;
+#ifdef __QNXNTO__
+ mmu->nodeList = gcvNULL;
+ mmu->nodeMutex = gcvNULL;
+#endif
+
+ /* Create the page table mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
+
+#ifdef __QNXNTO__
+ /* Create the node list mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &mmu->nodeMutex));
+#endif
+
+ /* Allocate the page table (not more than 256 kB). */
+ mmu->pageTableSize = gcmMIN(MmuSize, 256 << 10);
+ gcmkONERROR(
+ gckOS_AllocateContiguous(os,
+ gcvFALSE,
+ &mmu->pageTableSize,
+ &mmu->pageTablePhysical,
+ (gctPOINTER *) &mmu->pageTableLogical));
+
+ /* Compute number of entries in page table. */
+ mmu->pageTableEntries = mmu->pageTableSize / sizeof(gctUINT32);
+
+ /* Mark all pages as free. */
+ pageTable = mmu->pageTableLogical;
+ pageTable[0] = (mmu->pageTableEntries << 8) | gcvMMU_FREE;
+ pageTable[1] = ~0U;
+ mmu->heapList = 0;
+ mmu->freeNodes = gcvFALSE;
+
+ /* Set page table address. */
+ gcmkONERROR(
+ gckHARDWARE_SetMMU(hardware, (gctPOINTER) mmu->pageTableLogical));
+
+ /* Reset used page table entries. */
+ mmu->pageTableUsedEntries = 0;
+
+ /* Return the gckMMU object pointer. */
+ *Mmu = mmu;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Mmu=0x%x", *Mmu);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Roll back. */
+ if (mmu != gcvNULL)
+ {
+ if (mmu->pageTableLogical != gcvNULL)
+ {
+ /* Free the page table. */
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(os,
+ mmu->pageTablePhysical,
+ (gctPOINTER) mmu->pageTableLogical,
+ mmu->pageTableSize));
+ mmu->pageTableLogical = gcvNULL;
+ }
+
+ if (mmu->pageTableMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, mmu->pageTableMutex));
+ mmu->pageTableMutex = gcvNULL;
+ }
+
+#ifdef __QNXNTO__
+ if (mmu->nodeMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, mmu->nodeMutex));
+ mmu->nodeMutex = gcvNULL;
+ }
+#endif
+
+ /* Mark the gckMMU object as unknown. */
+ mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the allocates memory. */
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+
+ mmu = gcvNULL;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_Destroy
+**
+** Destroy a gckMMU object.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ )
+{
+#ifdef __QNXNTO__
+ gcuVIDMEM_NODE_PTR node, next;
+#endif
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+#ifdef __QNXNTO__
+ /* Free all associated virtual memory. */
+ for (node = Mmu->nodeList; node != gcvNULL; node = next)
+ {
+ next = node->Virtual.next;
+ gcmkVERIFY_OK(gckVIDMEM_Free(node, gcvNULL));
+ }
+#endif
+
+ /* Free the page table. */
+ if(Mmu->pageTableLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ Mmu->pageTablePhysical,
+ (gctPOINTER) Mmu->pageTableLogical,
+ Mmu->pageTableSize));
+ Mmu->pageTableLogical = gcvNULL;
+ }
+
+#ifdef __QNXNTO__
+ if (Mmu->nodeMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Mmu->os, Mmu->nodeMutex));
+ Mmu->nodeMutex = gcvNULL;
+ }
+#endif
+
+ if (Mmu->pageTableMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Mmu->os, Mmu->pageTableMutex));
+ Mmu->pageTableMutex = gcvNULL;
+ }
+
+ /* Mark the gckMMU object as unknown. */
+ Mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckMMU object. */
+ gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
+
+ Mmu = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckMMU_AllocatePages
+**
+** Allocate pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctSIZE_T PageCount
+** Number of pages to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * PageTable
+** Pointer to a variable that receives the base address of the page
+** table.
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gctUINT32 index = 0, previous = ~0U, left;
+ gctUINT32_PTR pageTable;
+ gctBOOL gotIt;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+ if (PageCount > Mmu->pageTableEntries)
+ {
+ /* Not enough pages avaiable. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ /* Cast pointer to page table. */
+ for (pageTable = Mmu->pageTableLogical, gotIt = gcvFALSE; !gotIt;)
+ {
+ /* Walk the heap list. */
+ for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);)
+ {
+ /* Check the node type. */
+ switch (pageTable[index] & 0xFF)
+ {
+ case gcvMMU_SINGLE:
+ /* Single odes are valid if we only need 1 page. */
+ if (PageCount == 1)
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = pageTable[index] >> 8;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* Test if the node has enough space. */
+ if (PageCount <= (pageTable[index] >> 8))
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = pageTable[index + 1];
+ }
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ /* Test if we are out of memory. */
+ if (index >= Mmu->pageTableEntries)
+ {
+ if (Mmu->freeNodes)
+ {
+ /* Time to move out the trash! */
+ gcmkONERROR(_Collect(Mmu));
+ }
+ else
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+ }
+
+ switch (pageTable[index] & 0xFF)
+ {
+ case gcvMMU_SINGLE:
+ /* Unlink single node from free list. */
+ gcmkONERROR(
+ _Link(Mmu, previous, pageTable[index] >> 8));
+ break;
+
+ case gcvMMU_FREE:
+ /* Check how many pages will be left. */
+ left = (pageTable[index] >> 8) - PageCount;
+ switch (left)
+ {
+ case 0:
+ /* The entire node is consumed, just unlink it. */
+ gcmkONERROR(
+ _Link(Mmu, previous, pageTable[index + 1]));
+ break;
+
+ case 1:
+ /* One page will remain. Convert the node to a single node and
+ ** advance the index. */
+ pageTable[index] = (pageTable[index + 1] << 8) | gcvMMU_SINGLE;
+ index ++;
+ break;
+
+ default:
+ /* Enough pages remain for a new node. However, we will just adjust
+ ** the size of the current node and advance the index. */
+ pageTable[index] = (left << 8) | gcvMMU_FREE;
+ index += left;
+ break;
+ }
+ break;
+ }
+
+ /* Mark node as used. */
+ pageTable[index] = gcvMMU_USED;
+
+ /* Return pointer to page table. */
+ *PageTable = &pageTable[index];
+
+ /* Build virtual address. */
+ gcmkONERROR(
+ gckHARDWARE_BuildVirtualAddress(Mmu->hardware, index, 0, &address));
+
+ if (Address != gcvNULL)
+ {
+ *Address = address;
+ }
+
+ /* Update used pageTable entries. */
+ Mmu->pageTableUsedEntries += PageCount;
+
+ /* 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:
+ gcmkLOG_ERROR_ARGS("status=%d, mutex=%d", status, mutex);
+ if (mutex)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_FreePages
+**
+** Free pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctPOINTER PageTable
+** Base address of the page table to free.
+**
+** gctSIZE_T PageCount
+** Number of pages to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32_PTR pageTable;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
+ Mmu, PageTable, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ /* Convert the pointer. */
+ pageTable = (gctUINT32_PTR) PageTable;
+
+ if (PageCount == 1)
+ {
+ /* Single page node. */
+ pageTable[0] = (~0U << 8) | gcvMMU_SINGLE;
+ }
+ else
+ {
+ /* Mark the node as free. */
+ pageTable[0] = (PageCount << 8) | gcvMMU_FREE;
+ pageTable[1] = ~0U;
+ }
+
+ /* We have free nodes. */
+ Mmu->freeNodes = gcvTRUE;
+
+ /* Update used pageTable entries. */
+ Mmu->pageTableUsedEntries -= PageCount;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_InsertNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node)
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+
+ gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ Node->Virtual.next = Mmu->nodeList;
+ Mmu->nodeList = Node;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutex)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_RemoveNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node)
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gcuVIDMEM_NODE_PTR *iter;
+
+ gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ for (iter = &Mmu->nodeList; *iter; iter = &(*iter)->Virtual.next)
+ {
+ if (*iter == Node)
+ {
+ *iter = Node->Virtual.next;
+ break;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutex)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_FreeHandleMemory(
+ IN gckMMU Mmu,
+ IN gctHANDLE Handle
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcuVIDMEM_NODE_PTR curr, next;
+
+ gcmkHEADER_ARG("Mmu=0x%x Handle=0x%x", Mmu, Handle);
+
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ for (curr = Mmu->nodeList; curr != gcvNULL; curr = next)
+ {
+ next = curr->Virtual.next;
+
+ if (curr->Virtual.handle == Handle)
+ {
+ while (curr->Virtual.locked > 0 || curr->Virtual.unlockPending)
+ {
+ gcmkONERROR(gckVIDMEM_Unlock(curr, gcvSURF_TYPE_UNKNOWN, gcvNULL, gcvNULL));
+ }
+
+ gcmkVERIFY_OK(gckVIDMEM_Free(curr, gcvNULL));
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/******************************************************************************
+****************************** T E S T C O D E ******************************
+******************************************************************************/
+
+#if defined gcdHAL_TEST
+
+#include <stdlib.h>
+#define gcmRANDOM(n) (rand() % n)
+
+typedef struct
+{
+ gctSIZE_T pageCount;
+ gctUINT32_PTR pageTable;
+}
+gcsMMU_TEST;
+
+gceSTATUS
+gckMMU_Test(
+ IN gckMMU Mmu,
+ IN gctSIZE_T Vectors,
+ IN gctINT MaxSize
+ )
+{
+ const gctINT nodeCount = MaxSize / 4;
+ gcsMMU_TEST * nodes = gcvNULL;
+ gceSTATUS status, failure = gcvSTATUS_OK;
+ gctSIZE_T i, count;
+ gctUINT32_PTR pageTable;
+ gctINT index;
+
+ /* Allocate the node array. */
+ gcmkONERROR(
+ gckOS_Allocate(Mmu->os,
+ nodeCount * gcmSIZEOF(gcsMMU_TEST),
+ (gctPOINTER *) &nodes));
+
+ /* Mark all nodes as free. */
+ gcmkONERROR(
+ gckOS_ZeroMemory(nodes, nodeCount * gcmSIZEOF(gcsMMU_TEST)));
+
+ /* Loop through all vectors. */
+ while (Vectors-- > 0)
+ {
+ /* Get a random index. */
+ index = gcmRANDOM(nodeCount);
+
+ /* Test if we need to allocate pages. */
+ if (nodes[index].pageCount == 0)
+ {
+ /* Generate a random page count. */
+ do
+ {
+ count = gcmRANDOM(MaxSize);
+ }
+ while (count == 0);
+
+ /* Allocate pages. */
+ status = gckMMU_AllocatePages(Mmu,
+ count,
+ (gctPOINTER *) &pageTable,
+ gcvNULL);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Mark node as allocated. */
+ nodes[index].pageCount = count;
+ nodes[index].pageTable = pageTable;
+
+ /* Put signature in the page table. */
+ for (i = 0; i < count; ++i)
+ {
+ pageTable[i] = (index << 8) | gcvMMU_USED;
+ }
+ }
+ else
+ {
+ gcmkTRACE(gcvLEVEL_WARNING,
+ "gckMMU_Test: Failed to allocate %u pages",
+ count);
+ }
+ }
+ else
+ {
+ /* Verify the page table. */
+ pageTable = nodes[index].pageTable;
+ for (i = 0; i < nodes[index].pageCount; ++i)
+ {
+ if (pageTable[i] != ((index << 8) | gcvMMU_USED))
+ {
+ gcmkFATAL("gckMMU_Test: Corruption detected at page %u",
+ index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the pages. */
+ status = gckMMU_FreePages(Mmu, pageTable, nodes[index].pageCount);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("gckMMU_Test: Cannot free %u pages at 0x%x (index=%u)",
+ nodes[index].pageCount, pageTable, index);
+
+ failure = status;
+ }
+
+ /* Mark the node as free. */
+ nodes[index].pageCount = 0;
+ }
+ }
+
+ /* Walk the entire array of nodes. */
+ for (index = 0; index < nodeCount; ++index)
+ {
+ /* Test if we need to free pages. */
+ if (nodes[index].pageCount != 0)
+ {
+ /* Verify the page table. */
+ pageTable = nodes[index].pageTable;
+ for (i = 0; i < nodes[index].pageCount; ++i)
+ {
+ if (pageTable[i] != ((index << 8) | gcvMMU_USED))
+ {
+ gcmkFATAL("gckMMU_Test: Corruption detected at page %u",
+ index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the pages. */
+ status = gckMMU_FreePages(Mmu, pageTable, nodes[index].pageCount);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("gckMMU_Test: Cannot free %u pages at 0x%x (index=%u)",
+ nodes[index].pageCount, pageTable, index);
+
+ failure = status;
+ }
+ }
+ }
+
+ /* Perform garbage collection. */
+ gcmkONERROR(_Collect(Mmu));
+
+ /* Verify we did not loose any nodes. */
+ if ((Mmu->heapList != 0)
+ || ((Mmu->pageTableLogical[0] & 0xFF) != gcvMMU_FREE)
+ || (Mmu->pageTableEntries != (Mmu->pageTableLogical[0] >> 8))
+ )
+ {
+ gcmkFATAL("gckMMU_Test: Detected leaking in the page table.");
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+OnError:
+ /* Free the array of nodes. */
+ if (nodes != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Free(Mmu->os, nodes));
+ }
+
+ /* Return test status. */
+ return failure;
+}
+#endif
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_precomp.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_precomp.h
new file mode 100644
index 0000000..0379a75
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_precomp.h
@@ -0,0 +1,32 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_precomp_h_
+#define __gc_hal_kernel_precomp_h_
+
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+
+#endif /* __gc_hal_kernel_precomp_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_video_memory.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_video_memory.c
new file mode 100644
index 0000000..ab57b59
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/gc_hal_kernel_video_memory.c
@@ -0,0 +1,1783 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_VIDMEM
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _Split
+**
+** Split a node on the required byte boundary.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the node to split.
+**
+** gctSIZE_T Bytes
+** Number of bytes to keep in the node.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gctBOOL
+** gcvTRUE if the node was split successfully, or gcvFALSE if there is an
+** error.
+**
+*/
+static gctBOOL
+_Split(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+
+ /* Make sure the byte boundary makes sense. */
+ if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
+ {
+ return gcvFALSE;
+ }
+
+ /* Allocate a new gcuVIDMEM_NODE object. */
+ if (gcmIS_ERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(gcuVIDMEM_NODE),
+ (gctPOINTER *) &node)))
+ {
+ /* Error. */
+ return gcvFALSE;
+ }
+
+ /* Initialize gcuVIDMEM_NODE structure. */
+ node->VidMem.offset = Node->VidMem.offset + Bytes;
+ node->VidMem.bytes = Node->VidMem.bytes - Bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.locked = 0;
+ node->VidMem.memory = Node->VidMem.memory;
+ node->VidMem.pool = Node->VidMem.pool;
+ node->VidMem.physical = Node->VidMem.physical;
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ node->VidMem.handle = 0;
+#endif
+
+ /* Insert node behind specified node. */
+ node->VidMem.next = Node->VidMem.next;
+ node->VidMem.prev = Node;
+ Node->VidMem.next = node->VidMem.next->VidMem.prev = node;
+
+ /* Insert free node behind specified node. */
+ node->VidMem.nextFree = Node->VidMem.nextFree;
+ node->VidMem.prevFree = Node;
+ Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
+
+ /* Adjust size of specified node. */
+ Node->VidMem.bytes = Bytes;
+
+ /* Success. */
+ return gcvTRUE;
+}
+
+/*******************************************************************************
+**
+** _Merge
+**
+** Merge two adjacent nodes together.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the first of the two nodes to merge.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+*/
+static gceSTATUS
+_Merge(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+
+ /* Save pointer to next node. */
+ node = Node->VidMem.next;
+
+ /* This is a good time to make sure the heap is not corrupted. */
+ if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
+ {
+ /* Corrupted heap. */
+ gcmkASSERT(
+ Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+ /* Adjust byte count. */
+ Node->VidMem.bytes += node->VidMem.bytes;
+
+ /* Unlink next node from linked list. */
+ Node->VidMem.next = node->VidMem.next;
+ Node->VidMem.nextFree = node->VidMem.nextFree;
+
+ Node->VidMem.next->VidMem.prev =
+ Node->VidMem.nextFree->VidMem.prevFree = Node;
+
+ /* Free next node. */
+ return gckOS_Free(Os, node);
+}
+
+/******************************************************************************\
+******************************* gckVIDMEM API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVIDMEM_ConstructVirtual
+**
+** Construct a new gcuVIDMEM_NODE union for virtual memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
+*/
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x Bytes=%lu", Kernel, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+#ifdef __QNXNTO__
+ gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate an gcuVIDMEM_NODE union. */
+ gcmkONERROR(
+ gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), (gctPOINTER *) &node));
+
+ /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+ node->Virtual.kernel = Kernel;
+ node->Virtual.contiguous = Contiguous;
+ node->Virtual.locked = 0;
+ node->Virtual.logical = gcvNULL;
+ node->Virtual.pageTable = gcvNULL;
+ node->Virtual.mutex = gcvNULL;
+#ifdef __QNXNTO__
+ node->Virtual.next = gcvNULL;
+ node->Virtual.unlockPending = gcvFALSE;
+ node->Virtual.freePending = gcvFALSE;
+ node->Virtual.handle = Handle;
+#else
+ node->Virtual.pending = gcvFALSE;
+#endif
+
+ /* Create the mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &node->Virtual.mutex));
+
+ /* Allocate the virtual memory. */
+ gcmkONERROR(
+ gckOS_AllocatePagedMemoryEx(os,
+ node->Virtual.contiguous,
+ node->Virtual.bytes = Bytes,
+ &node->Virtual.physical));
+
+#ifdef __QNXNTO__
+ /* Register. */
+ gckMMU_InsertNode(Kernel->mmu, node);
+#endif
+
+ /* Return pointer to the gcuVIDMEM_NODE union. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Created virtual node 0x%x for %u bytes @ 0x%x",
+ node, Bytes, node->Virtual.physical);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, node=0x%08x", status, node);
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ if (node->Virtual.mutex != gcvNULL)
+ {
+ /* Destroy the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->Virtual.mutex));
+ node->Virtual.mutex= gcvNULL;
+ }
+
+ /* Free the structure. */
+ gcmkVERIFY_OK(gckOS_Free(os, node));
+ node = gcvNULL;
+ }
+
+ /* 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;
+ gceSTATUS status;
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+ /* Extact the gckOS object pointer. */
+ os = Node->Virtual.kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+#ifdef __QNXNTO__
+ /* Unregister. */
+ gcmkVERIFY_OK(
+ gckMMU_RemoveNode(Node->Virtual.kernel->mmu, Node));
+
+ /* Free virtual memory. */
+ gcmkVERIFY_OK(
+ gckOS_FreePagedMemory(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes));
+#endif
+
+ /* Delete the mutex. */
+ if(Node->Virtual.mutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, Node->Virtual.mutex));
+ }
+
+ if (Node->Virtual.pageTable != gcvNULL)
+ {
+ /* Free the pages. */
+ gcmkONERROR(gckMMU_FreePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageTable,
+ Node->Virtual.pageCount));
+ }
+
+
+ /* Delete the gcuVIDMEM_NODE union. */
+ gcmkVERIFY_OK(gckOS_Free(os, Node));
+ Node = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Construct
+**
+** Construct a new gckVIDMEM object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 BaseAddress
+** Base address for the video memory heap.
+**
+** gctSIZE_T Bytes
+** Number of bytes in the video memory heap.
+**
+** gctSIZE_T Threshold
+** Minimum number of bytes beyond am allocation before the node is
+** split. Can be used as a minimum alignment requirement.
+**
+** gctSIZE_T BankSize
+** Number of bytes per physical memory bank. Used by bank
+** optimization.
+**
+** OUTPUT:
+**
+** gckVIDMEM * Memory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object.
+*/
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T BankSize,
+ OUT gckVIDMEM * Memory
+ )
+{
+ gckVIDMEM memory = gcvNULL;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctINT i, banks = 0;
+
+ gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
+ "BankSize=%lu",
+ Os, BaseAddress, Bytes, Threshold, BankSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Allocate the gckVIDMEM object. */
+ gcmkONERROR(
+ gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckVIDMEM),
+ (gctPOINTER *) &memory));
+
+ /* Initialize the gckVIDMEM object. */
+ memory->object.type = gcvOBJ_VIDMEM;
+ memory->os = Os;
+
+ /* Set video memory heap information. */
+ memory->baseAddress = BaseAddress;
+ memory->bytes = Bytes;
+ memory->freeBytes = Bytes;
+ memory->threshold = Threshold;
+ memory->mutex = gcvNULL;
+
+ BaseAddress = 0;
+
+ /* Walk all possible banks. */
+ for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
+ {
+ gctSIZE_T bytes;
+
+ if (BankSize == 0)
+ {
+ /* Use all bytes for the first bank. */
+ bytes = Bytes;
+ }
+ else
+ {
+ /* Compute number of bytes for this bank. */
+ bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress;
+
+ if (bytes > Bytes)
+ {
+ /* Make sure we don't exceed the total number of bytes. */
+ bytes = Bytes;
+ }
+ }
+
+ if (bytes == 0)
+ {
+ /* Mark heap is not used. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = gcvNULL;
+ continue;
+ }
+
+ /* Allocate one gcuVIDMEM_NODE union. */
+ gcmkONERROR(
+ gckOS_Allocate(Os,
+ gcmSIZEOF(gcuVIDMEM_NODE),
+ (gctPOINTER *) &node));
+
+ /* Initialize gcuVIDMEM_NODE union. */
+ node->VidMem.memory = memory;
+
+ node->VidMem.next =
+ node->VidMem.prev =
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = &memory->sentinel[i];
+
+ node->VidMem.offset = BaseAddress;
+ node->VidMem.bytes = bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.physical = 0;
+ node->VidMem.pool = gcvPOOL_UNKNOWN;
+
+ node->VidMem.locked = 0;
+
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ node->VidMem.handle = 0;
+#endif
+
+ /* Initialize the linked list of nodes. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = node;
+
+ /* Mark sentinel. */
+ memory->sentinel[i].VidMem.bytes = 0;
+
+ /* Adjust address for next bank. */
+ BaseAddress += bytes;
+ Bytes -= bytes;
+ banks ++;
+ }
+
+ /* Assign all the bank mappings. */
+ memory->mapping[gcvSURF_RENDER_TARGET] = banks - 1;
+ memory->mapping[gcvSURF_BITMAP] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_DEPTH] = banks - 1;
+ memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TEXTURE] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_VERTEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_INDEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TILE_STATUS] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TYPE_UNKNOWN] = 0;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] INDEX: bank %d",
+ memory->mapping[gcvSURF_INDEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] VERTEX: bank %d",
+ memory->mapping[gcvSURF_VERTEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TEXTURE: bank %d",
+ memory->mapping[gcvSURF_TEXTURE]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] RENDER_TARGET: bank %d",
+ memory->mapping[gcvSURF_RENDER_TARGET]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] DEPTH: bank %d",
+ memory->mapping[gcvSURF_DEPTH]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TILE_STATUS: bank %d",
+ memory->mapping[gcvSURF_TILE_STATUS]);
+
+ /* Allocate the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));
+
+ /* Return pointer to the gckVIDMEM object. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, memory=0x%08x", status, memory);
+ /* Roll back. */
+ if (memory != gcvNULL)
+ {
+ if (memory->mutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
+ memory->mutex = gcvNULL;
+ }
+
+ for (i = 0; i < banks; ++i)
+ {
+ /* Free the heap. */
+ gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
+ gcmkVERIFY_OK(gckOS_Free(Os, memory->sentinel[i].VidMem.next));
+ }
+
+ /* Free the object. */
+ gcmkVERIFY_OK(gckOS_Free(Os, memory));
+
+ memory = gcvNULL;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Destroy
+**
+** Destroy an gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ )
+{
+ gcuVIDMEM_NODE_PTR node, next;
+ gctINT i;
+
+ gcmkHEADER_ARG("Memory=0x%x", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+ /* Walk all sentinels. */
+ for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ /* Bail out of the heap is not used. */
+ if (Memory->sentinel[i].VidMem.next == gcvNULL)
+ {
+ break;
+ }
+
+ /* Walk all the nodes until we reach the sentinel. */
+ for (node = Memory->sentinel[i].VidMem.next;
+ node->VidMem.bytes != 0;
+ node = next)
+ {
+ /* Save pointer to the next node. */
+ next = node->VidMem.next;
+
+ /* Free the node. */
+ gcmkVERIFY_OK(gckOS_Free(Memory->os, node));
+ }
+ }
+
+ /* Free the mutex. */
+ if(Memory->mutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex));
+ Memory->mutex = gcvNULL;
+ }
+
+ /* Mark the object as unknown. */
+ Memory->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVIDMEM object. */
+ gcmkVERIFY_OK(gckOS_Free(Memory->os, Memory));
+ Memory = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Allocate
+**
+** Allocate rectangular memory from the gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object.
+**
+** gctUINT Width
+** Width of rectangle to allocate. Make sure the width is properly
+** aligned.
+**
+** gctUINT Height
+** Height of rectangle to allocate. Make sure the height is properly
+** aligned.
+**
+** gctUINT Depth
+** Depth of rectangle to allocate. This equals to the number of
+** rectangles to allocate contiguously (i.e., for cubic maps and volume
+** textures).
+**
+** gctUINT BytesPerPixel
+** Number of bytes per pixel.
+**
+** gctUINT32 Alignment
+** Byte alignment for allocation.
+**
+** gceSURF_TYPE Type
+** Type of surface to allocate (use by bank optimization).
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that will hold the allocated memory node.
+*/
+gceSTATUS
+gckVIDMEM_Allocate(
+ IN gckVIDMEM Memory,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT BytesPerPixel,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gctSIZE_T bytes;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Memory=0x%x Width=%u Height=%u Depth=%u BytesPerPixel=%u "
+ "Alignment=%u Type=%d",
+ Memory, Width, Height, Depth, BytesPerPixel, Alignment,
+ Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+ gcmkVERIFY_ARGUMENT(Width > 0);
+ gcmkVERIFY_ARGUMENT(Height > 0);
+ gcmkVERIFY_ARGUMENT(Depth > 0);
+ gcmkVERIFY_ARGUMENT(BytesPerPixel > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+#ifdef __QNXNTO__
+ gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+ if(gckOS_ForceMemAllocFail(Memory->os))
+ return gcvSTATUS_OUT_OF_MEMORY;
+
+ /* Compute linear size. */
+ bytes = Width * Height * Depth * BytesPerPixel;
+
+ /* Allocate through linear function. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Handle, Node));
+#else
+ gcmkONERROR(
+ gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Node));
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gcuVIDMEM_NODE_PTR
+_FindNode(
+ IN gckVIDMEM Memory,
+ IN gctINT Bank,
+ IN gctSIZE_T Bytes,
+ IN OUT gctUINT32_PTR Alignment
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+
+ /* Walk all free nodes until we have one that is big enough or we have
+ reached the sentinel. */
+ for (node = Memory->sentinel[Bank].VidMem.nextFree;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.nextFree)
+ {
+ /* Compute number of bytes to skip for alignment. */
+ alignment = (*Alignment == 0)
+ ? 0
+ : (*Alignment - (node->VidMem.offset % *Alignment));
+
+ if (alignment == *Alignment)
+ {
+ /* Node is already aligned. */
+ alignment = 0;
+ }
+
+ if (node->VidMem.bytes >= Bytes + alignment)
+ {
+ /* This node is big enough. */
+ *Alignment = alignment;
+ return node;
+ }
+ }
+
+ /* Not enough memory. */
+ return gcvNULL;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_AllocateLinear
+**
+** Allocate linear memory from the gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** gctUINT32 Alignment
+** Byte alignment for allocation.
+**
+** gceSURF_TYPE Type
+** Type of surface to allocate (use by bank optimization).
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that will hold the allocated memory node.
+*/
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+ IN gckVIDMEM Memory,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+ gctINT bank, i;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
+ Memory, Bytes, Alignment, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+#ifdef __QNXNTO__
+ gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ if (Bytes > Memory->freeBytes)
+ {
+ gcmkLOG_WARNING_ARGS("Not enough video memory, Bytes=%d, Memory->freeBytes=%d", Bytes, Memory->freeBytes);
+ /* Not enough memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Find the default bank for this surface type. */
+ gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
+ bank = Memory->mapping[Type];
+ alignment = Alignment;
+
+ /* Find a free node in the default bank. */
+ node = _FindNode(Memory, bank, Bytes, &alignment);
+
+ /* Out of memory? */
+ if (node == gcvNULL)
+ {
+ /* Walk all lower banks. */
+ for (i = bank - 1; i >= 0; --i)
+ {
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Memory, i, Bytes, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ /* Walk all upper banks. */
+ for (i = bank + 1; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ if (Memory->sentinel[i].VidMem.nextFree == gcvNULL)
+ {
+ /* Abort when we reach unused banks. */
+ break;
+ }
+
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Memory, i, Bytes, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Can't find a free node");
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Do we have an alignment? */
+ if (alignment > 0)
+ {
+ /* Split the node so it is aligned. */
+ if (_Split(Memory->os, node, alignment))
+ {
+ /* Successful split, move to aligned node. */
+ node = node->VidMem.next;
+
+ /* Remove alignment. */
+ alignment = 0;
+ }
+ }
+
+ /* Do we have enough memory after the allocation to split it? */
+ if (node->VidMem.bytes - Bytes > Memory->threshold)
+ {
+ /* Adjust the node size. */
+ _Split(Memory->os, node, Bytes);
+ }
+
+ /* Remove the node from the free list. */
+ node->VidMem.prevFree->VidMem.nextFree = node->VidMem.nextFree;
+ node->VidMem.nextFree->VidMem.prevFree = node->VidMem.prevFree;
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = gcvNULL;
+
+ /* Fill in the information. */
+ node->VidMem.alignment = alignment;
+ node->VidMem.memory = Memory;
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ node->VidMem.handle = Handle;
+#endif
+
+ /* Adjust the number of free bytes. */
+ Memory->freeBytes -= node->VidMem.bytes;
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+
+ /* Return the pointer to the node. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Allocated %u bytes @ 0x%x [0x%08X]",
+ node->VidMem.bytes, node, node->VidMem.offset);
+
+ /* Update video memory usage. */
+ gckOS_UpdateVidMemUsage(Memory->os, gcvTRUE, node->VidMem.bytes);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Free
+**
+** Free an allocated video memory node.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Free(
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gckVIDMEM memory = gcvNULL;
+ gcuVIDMEM_NODE_PTR node;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctSIZE_T bytes = 0;
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ if (Node->VidMem.locked > 0)
+ {
+ gcmkLOG_ERROR_ARGS("Node 0x%x is locked", Node);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
+ "Node 0x%x is locked (%d)",
+ Node, Node->VidMem.locked);
+
+ /* Node is locked. */
+ gcmkONERROR(gcvSTATUS_MEMORY_LOCKED);
+ }
+
+ /* Extract pointer to gckVIDMEM object owning the node. */
+ memory = Node->VidMem.memory;
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+ bytes = Node->VidMem.bytes;
+#ifdef __QNXNTO__
+ /* Reset handle to 0. */
+ Node->VidMem.logical = gcvNULL;
+ Node->VidMem.handle = 0;
+
+ /* Don't try to a re-free an already freed node. */
+ if ((Node->VidMem.nextFree == gcvNULL)
+ && (Node->VidMem.prevFree == gcvNULL)
+ )
+#endif
+ {
+ /* Update the number of free bytes. */
+ memory->freeBytes += Node->VidMem.bytes;
+
+ /* Find the next free node. */
+ for (node = Node->VidMem.next;
+ node->VidMem.nextFree == gcvNULL;
+ node = node->VidMem.next) ;
+
+ /* Insert this node in the free list. */
+ Node->VidMem.nextFree = node;
+ Node->VidMem.prevFree = node->VidMem.prevFree;
+
+ Node->VidMem.prevFree->VidMem.nextFree =
+ node->VidMem.prevFree = Node;
+
+ /* Is the next node a free node and not the sentinel? */
+ if ((Node->VidMem.next == Node->VidMem.nextFree)
+ && (Node->VidMem.next->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the next node. */
+ gcmkONERROR(_Merge(memory->os, node = Node));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+
+ /* Is the previous node a free node and not the sentinel? */
+ if ((Node->VidMem.prev == Node->VidMem.prevFree)
+ && (Node->VidMem.prev->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the previous node. */
+ gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+ }
+ /* Update video memory usage. */
+ gckOS_UpdateVidMemUsage(memory->os, gcvFALSE, bytes);
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ /* Verify the gckKERNEL object pointer. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+#ifdef __QNXNTO__
+ if (!Node->Virtual.unlockPending && (Node->Virtual.locked > 0))
+#else
+ if (!Node->Virtual.pending && (Node->Virtual.locked > 0))
+#endif
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
+ "gckVIDMEM_Free: Virtual node 0x%x is locked (%d)",
+ Node, Node->Virtual.locked);
+
+ /* Node is locked. */
+ gcmkONERROR(gcvSTATUS_MEMORY_LOCKED);
+ }
+
+#ifdef __QNXNTO__
+ if (!Node->Virtual.freePending) { if (Node->Virtual.unlockPending)
+#else
+ if (Node->Virtual.pending)
+#endif
+ {
+ gcmkASSERT(Node->Virtual.locked == 1);
+
+ /* Schedule the node to be freed. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "gckVIDMEM_Free: Scheduling node 0x%x to be freed later",
+ Node);
+
+ /* Schedule the video memory to be freed again. */
+ gcmkONERROR(gckEVENT_FreeVideoMemory(Node->Virtual.kernel->event,
+ Node,
+ gcvKERNEL_PIXEL));
+
+#ifdef __QNXNTO__
+ Node->Virtual.freePending = gcvTRUE; }
+#endif
+ }
+
+ else
+ {
+ /* Free the virtual memory. */
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(Node->Virtual.kernel->os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes));
+
+ /* Destroy the gcuVIDMEM_NODE union. */
+ gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+#ifdef __QNXNTO__
+/*******************************************************************************
+**
+** gcoVIDMEM_FreeHandleMemory
+**
+** Free all allocated video memory nodes for a handle.
+**
+** INPUT:
+**
+** gcoVIDMEM Memory
+** Pointer to an gcoVIDMEM object..
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_FreeHandleMemory(
+ IN gckVIDMEM Memory,
+ IN gctHANDLE Handle
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gcuVIDMEM_NODE_PTR node;
+ gctINT i;
+ gctUINT32 nodeCount = 0, byteCount = 0;
+ gctBOOL again;
+
+ gcmkHEADER_ARG("Memory=0x%x Handle=0x%x", Memory, Handle);
+
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+ gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ /* Walk all sentinels. */
+ for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ /* Bail out of the heap if it is not used. */
+ if (Memory->sentinel[i].VidMem.next == gcvNULL)
+ {
+ break;
+ }
+
+ do
+ {
+ again = gcvFALSE;
+
+ /* Walk all the nodes until we reach the sentinel. */
+ for (node = Memory->sentinel[i].VidMem.next;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.next)
+ {
+ /* Free the node if it was allocated by Handle. */
+ if (node->VidMem.handle == Handle)
+ {
+ /* Unlock video memory. */
+ while (gckVIDMEM_Unlock(node, gcvSURF_TYPE_UNKNOWN, gcvNULL, gcvNULL)
+ != gcvSTATUS_MEMORY_UNLOCKED)
+ ;
+
+ nodeCount++;
+ byteCount += node->VidMem.bytes;
+
+ /* Free video memory. */
+ gcmkVERIFY_OK(gckVIDMEM_Free(node, gcvNULL));
+
+ /*
+ * Freeing may cause a merge which will invalidate our iteration.
+ * Don't be clever, just restart.
+ */
+ again = gcvTRUE;
+
+ break;
+ }
+ }
+ }
+ while (again);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutex)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckVIDMEM_Lock
+**
+** Lock a video memory node and return it's hardware specific address.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable that will hold the hardware specific address.
+*/
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL locked = gcvFALSE;
+ gckOS os = gcvNULL;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ /* Increment the lock count. */
+ Node->VidMem.locked ++;
+
+ /* Return the address of the node. */
+ *Address = Node->VidMem.memory->baseAddress
+ + Node->VidMem.offset
+ + Node->VidMem.alignment;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Locked node 0x%x (%d) @ 0x%08X",
+ Node,
+ Node->VidMem.locked,
+ *Address);
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+ /* Verify the gckKERNEL object pointer. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+ /* Extract the gckOS object pointer. */
+ os = Node->Virtual.kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Increment the lock count. */
+ if (Node->Virtual.locked ++ == 0)
+ {
+ /* Is this node pending for a final unlock? */
+#ifdef __QNXNTO__
+ if (!Node->Virtual.contiguous && Node->Virtual.unlockPending)
+#else
+ if (!Node->Virtual.contiguous && Node->Virtual.pending)
+#endif
+ {
+ /* Make sure we have a page table. */
+ gcmkASSERT(Node->Virtual.pageTable != gcvNULL);
+
+ /* Remove pending unlock. */
+#ifdef __QNXNTO__
+ Node->Virtual.unlockPending = gcvFALSE;
+#else
+ Node->Virtual.pending = gcvFALSE;
+#endif
+ }
+
+ /* First lock - create a page table. */
+ gcmkASSERT(Node->Virtual.pageTable == gcvNULL);
+
+ /* Make sure we mark our node as not flushed. */
+#ifdef __QNXNTO__
+ Node->Virtual.unlockPending = gcvFALSE;
+#else
+ Node->Virtual.pending = gcvFALSE;
+#endif
+
+ /* Lock the allocated pages. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckOS_LockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ Node->Virtual.userPID,
+ &Node->Virtual.logical,
+ &Node->Virtual.pageCount));
+#else
+ gcmkONERROR(
+ gckOS_LockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ &Node->Virtual.logical,
+ &Node->Virtual.pageCount));
+#endif
+
+ locked = gcvTRUE;
+
+ if (Node->Virtual.contiguous)
+ {
+ /* Get physical address directly */
+ gcmkONERROR(gckOS_GetPhysicalAddress(os,
+ Node->Virtual.logical,
+ &Node->Virtual.address));
+ }
+ else
+ {
+ /* Allocate pages inside the MMU. */
+ gcmkONERROR(
+ gckMMU_AllocatePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageCount,
+ &Node->Virtual.pageTable,
+ &Node->Virtual.address));
+
+ /* Map the pages. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckOS_MapPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.logical,
+ Node->Virtual.pageCount,
+ Node->Virtual.pageTable));
+#else
+ gcmkONERROR(
+ gckOS_MapPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.pageCount,
+ Node->Virtual.pageTable));
+#endif
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Mapped virtual node 0x%x to 0x%08X",
+ Node,
+ Node->Virtual.address);
+ }
+ }
+
+ /* Return hardware address. */
+ *Address = Node->Virtual.address;
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, locked=%d, acquired=%d", status, locked, acquired);
+ if (locked)
+ {
+ if (Node->Virtual.pageTable != gcvNULL)
+ {
+ /* Free the pages from the MMU. */
+ gcmkVERIFY_OK(
+ gckMMU_FreePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageTable,
+ Node->Virtual.pageCount));
+
+ Node->Virtual.pageTable = gcvNULL;
+ }
+
+ /* Unlock the pages. */
+#ifdef __QNXNTO__
+ gcmkERR_RETURN(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.userPID,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+
+#else
+ gcmkERR_RETURN(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+#endif
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Unlock
+**
+** Unlock a video memory node.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a locked gcuVIDMEM_NODE union.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+**
+** gctSIZE_T * CommandSize
+** Pointer to a variable specifying the number of bytes in the command
+** buffer specified by 'Commands'. If gcvNULL, there is no command
+** buffer and the video memory shoud be unlocked synchronously.
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable specifying whether the surface should be
+** unlocked asynchroneously or not.
+**
+** OUTPUT:
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable receiving the number of bytes used in the
+** command buffer specified by 'Commands'. If gcvNULL, there is no
+** command buffer.
+*/
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ )
+{
+ gceSTATUS status;
+ gckKERNEL kernel;
+ gckHARDWARE hardware;
+ gctPOINTER buffer;
+ gctSIZE_T requested, bufferSize;
+ gckCOMMAND command = gcvNULL;
+ gceKERNEL_FLUSH flush;
+ gckOS os = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL needRelease = gcvFALSE;
+ gctBOOL pendingUnlock = gcvFALSE;
+
+ gcmkHEADER_ARG("Node=0x%x Type=%d *Asynchroneous=%d",
+ Node, Type, gcmOPT_VALUE(Asynchroneous));
+
+ /* Verify the arguments. */
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ if (Node->VidMem.locked <= 0)
+ {
+ /* The surface was not locked. */
+ gcmkONERROR(gcvSTATUS_MEMORY_UNLOCKED);
+ }
+
+ /* Decrement the lock count. */
+ Node->VidMem.locked --;
+
+ if (Asynchroneous != gcvNULL)
+ {
+ /* No need for any events. */
+ *Asynchroneous = gcvFALSE;
+ }
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+ /* Verify the gckKERNEL object pointer. */
+ kernel = Node->Virtual.kernel;
+ gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
+
+ /* Verify the gckHARDWARE object pointer. */
+ hardware = Node->Virtual.kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Verify the gckCOMMAND object pointer. */
+ command = Node->Virtual.kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+ if (Asynchroneous == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "gckVIDMEM_Unlock: Unlocking virtual node 0x%x (%d)",
+ Node,
+ Node->Virtual.locked);
+
+ /* Get the gckOS object pointer. */
+ os = kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Grab the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+
+ /* If we need to unlock a node from virtual memory we have to be
+ ** very carefull. If the node is still inside the caches we
+ ** might get a bus error later if the cache line needs to be
+ ** replaced. So - we have to flush the caches before we do
+ ** anything. We also need to stall to make sure the flush has
+ ** happened. However - when we get to this point we are inside
+ ** the interrupt handler and we cannot just gckCOMMAND_Wait
+ ** because it will wait forever. So - what we do here is we
+ ** verify the type of the surface, flush the appropriate cache,
+ ** mark the node as flushed, and issue another unlock to unmap
+ ** the MMU. */
+ if (!Node->Virtual.contiguous
+ && (Node->Virtual.locked == 1)
+#ifdef __QNXTO__
+ && !Node->Virtual.unlockPending
+#else
+ && !Node->Virtual.pending
+#endif
+ )
+ {
+ if (Type == gcvSURF_BITMAP)
+ {
+ /* Flush 2D cache. */
+ flush = gcvFLUSH_2D;
+ }
+ else if (Type == gcvSURF_RENDER_TARGET)
+ {
+ /* Flush color cache. */
+ flush = gcvFLUSH_COLOR;
+ }
+ else if (Type == gcvSURF_DEPTH)
+ {
+ /* Flush depth cache. */
+ flush = gcvFLUSH_DEPTH;
+ }
+ else
+ {
+ /* No flush required. */
+ flush = (gceKERNEL_FLUSH) 0;
+ }
+
+ gcmkONERROR(
+ gckHARDWARE_Flush(hardware, flush, gcvNULL, &requested));
+
+ if (requested != 0)
+ {
+ gcmkONERROR(
+ gckCOMMAND_Reserve(command,
+ requested,
+ &buffer,
+ &bufferSize));
+
+ needRelease = gcvTRUE;
+
+ gcmkONERROR(gckHARDWARE_Flush(hardware,
+ flush,
+ buffer,
+ &bufferSize));
+
+ gcmkONERROR(
+ gckEVENT_Unlock(Node->Virtual.kernel->event,
+ gcvKERNEL_PIXEL,
+ Node,
+ Type));
+
+ /* Mark node as pending. */
+#ifdef __QNXNTO__
+ Node->Virtual.unlockPending = gcvTRUE;
+#else
+ Node->Virtual.pending = gcvTRUE;
+#endif
+
+ needRelease = gcvFALSE;
+
+ gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+ pendingUnlock = gcvTRUE;
+ }
+ }
+
+ if (!pendingUnlock)
+ {
+ /* Decrement lock count. */
+ -- Node->Virtual.locked;
+
+ /* See if we can unlock the resources. */
+ if (Node->Virtual.locked == 0)
+ {
+ /* Unlock the pages. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.userPID,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+#else
+ gcmkONERROR(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+#endif
+
+ /* Free the page table. */
+ if (Node->Virtual.pageTable != gcvNULL)
+ {
+ gcmkONERROR(
+ gckMMU_FreePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageTable,
+ Node->Virtual.pageCount));
+
+ /* Mark page table as freed. */
+ Node->Virtual.pageTable = gcvNULL;
+ }
+
+ /* Mark node as unlocked. */
+#ifdef __QNXTO
+ Node->Virtual.unlockPending = gcvFALSE;
+#else
+ Node->Virtual.pending = gcvFALSE;
+#endif
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Unmapped virtual node 0x%x from 0x%08X",
+ Node, Node->Virtual.address);
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Scheduled unlock for virtual node 0x%x",
+ Node);
+
+ /* Schedule the surface to be unlocked. */
+ *Asynchroneous = gcvTRUE;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, needRelease=%d, acquired=%d", status, needRelease, acquired);
+ if (needRelease)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Release(command));
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#ifdef __QNXNTO__
+/* Set the allocating process' PID for this node. */
+gceSTATUS
+gckVIDMEM_SetPID(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctUINT32 Pid
+ )
+{
+ if (Node != gcvNULL)
+ {
+ if (Node->VidMem.memory->object.type != gcvOBJ_VIDMEM)
+ {
+ Node->Virtual.userPID = Pid;
+ }
+
+ }
+ else
+ {
+ return gcvSTATUS_INVALID_OBJECT;
+ }
+
+ return gcvSTATUS_OK;
+}
+#endif
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/makefile.linux b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/makefile.linux
new file mode 100644
index 0000000..6d344b2
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/kernel/makefile.linux
@@ -0,0 +1,61 @@
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+
+#
+# Linux build file for architecture dependent kernel HAL layer.
+#
+#
+
+
+################################################################################
+# Include common definitions.
+
+include $(AQROOT)/makefile.linux.def
+
+################################################################################
+# Define a shortcut for the main target.
+
+STATIC = 1
+TARGET_NAME = libhalkernel.a
+
+################################################################################
+# Supply additional include directories.
+
+INCLUDE += -I$(AQROOT)/hal/inc
+INCLUDE += -I$(AQROOT)/hal/user
+INCLUDE += -I$(AQARCH)/hal/kernel
+
+#CFLAGS += $(INCLUDE) -Werror -ansi
+# cy modify for build using GCC4.6.6 compiler
+CFLAGS += $(INCLUDE) -ansi
+
+################################################################################
+# Describe object files.
+
+OBJECTS = $(OBJ_DIR)/gc_hal_kernel_command.o \
+ $(OBJ_DIR)/gc_hal_kernel_event.o \
+ $(OBJ_DIR)/gc_hal_kernel_heap.o \
+ $(OBJ_DIR)/gc_hal_kernel.o \
+ $(OBJ_DIR)/gc_hal_kernel_mmu.o \
+ $(OBJ_DIR)/gc_hal_kernel_video_memory.o
+
+include $(AQROOT)/common.target
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/makefile.linux b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/makefile.linux
new file mode 100644
index 0000000..f957d92
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/makefile.linux
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+#
+# The material in this file is confidential and contains trade secrets
+# of Vivante Corporation. This is proprietary information owned by
+# Vivante Corporation. No part of this work may be disclosed,
+# reproduced, copied, transmitted, or used in any way for any purpose,
+# without the express written permission of Vivante Corporation.
+#
+##############################################################################
+#
+#
+##############################################################################
+
+
+
+#
+# Linux build file for the user level HAL libraries.
+#
+
+
+
+################################################################################
+# Define make command.
+
+MAKE = make --makefile=makefile.linux
+
+
+################################################################################
+# Define build directories.
+
+HAL_USER_DRV_ARCH := $(AQARCH)/hal/user
+ifeq ($(QNX), 1)
+HAL_USER_DRV_OS := $(AQROOT)/hal/os/qnx/user
+else
+HAL_USER_DRV_OS := $(AQROOT)/hal/os/linux/user
+endif
+HAL_USER_DRV_MAIN := $(AQROOT)/hal/user
+
+$(HAL_USER_DRV_MAIN): $(HAL_USER_DRV_ARCH) $(HAL_USER_DRV_OS)
+
+MODULES := $(HAL_USER_DRV_ARCH) $(HAL_USER_DRV_OS) $(HAL_USER_DRV_MAIN)
+MAIN_MODULE = $(HAL_USER_DRV_MAIN)
+
+include $(AQROOT)/common.node
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_debug.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_debug.c
new file mode 100644
index 0000000..80225f6
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_debug.c
@@ -0,0 +1,453 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+#include "linux/spinlock.h"
+#include <stdarg.h>
+
+/*
+ gcdBUFFERED_OUTPUT
+
+ When set to non-zero, all output is collected into a buffer with the
+ specified size. Once the buffer gets full, or the token "$$FLUSH$$" has
+ been received, the debug buffer will be printed to the console.
+*/
+#define gcdBUFFERED_OUTPUT 0
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
+static gctUINT32 _debugZones = gcvZONE_NONE;
+static gctINT _indent = 0;
+#if 0
+static spinlock_t _lock = SPIN_LOCK_UNLOCKED;
+#else
+DEFINE_SPINLOCK(_lock);
+#endif
+
+static void
+OutputDebugString(
+ IN gctCONST_STRING String
+ )
+{
+#if gcdBUFFERED_OUTPUT
+ static gctCHAR outputBuffer[gcdBUFFERED_OUTPUT];
+ static gctINT outputBufferIndex = 0;
+ gctINT n, i;
+
+ n = (String != gcvNULL) ? strlen(String) + 1 : 0;
+
+ if ((n == 0) || (outputBufferIndex + n > gcmSIZEOF(outputBuffer)))
+ {
+ for (i = 0; i < outputBufferIndex; i += strlen(outputBuffer + i) + 1)
+ {
+ printk(outputBuffer + i);
+ }
+
+ outputBufferIndex = 0;
+ }
+
+ if (n > 0)
+ {
+ memcpy(outputBuffer + outputBufferIndex, String, n);
+ outputBufferIndex += n;
+ }
+#else
+ if (String != gcvNULL)
+ {
+ printk(String);
+ }
+#endif
+}
+
+static void
+_Print(
+ IN gctCONST_STRING Message,
+ IN va_list Arguments
+ )
+{
+ char buffer[1024];
+ int i, n;
+
+ if (strcmp(Message, "$$FLUSH$$") == 0)
+ {
+ spin_lock(&_lock);
+ {
+ OutputDebugString(gcvNULL);
+ }
+ spin_unlock(&_lock);
+ return;
+ }
+
+ if (strncmp(Message, "--", 2) == 0)
+ {
+ if (_indent == 0)
+ {
+ printk("ERROR: _indent=0\n");
+ }
+
+ _indent -= 2;
+ }
+
+ for (i = 0; i < _indent; ++i)
+ {
+ buffer[i] = ' ';
+ }
+
+ /* Print message to buffer. */
+ n = vsnprintf(buffer + i, sizeof(buffer) - i, Message, Arguments);
+ if ((n <= 0) || (buffer[i + n - 1] != '\n'))
+ {
+ /* Append new-line. */
+ strncat(buffer, "\n", sizeof(buffer));
+ }
+
+ /* Output to debugger. */
+ spin_lock(&_lock);
+ {
+ OutputDebugString(buffer);
+ }
+ spin_unlock(&_lock);
+
+ if (strncmp(Message, "++", 2) == 0)
+ {
+ _indent += 2;
+ }
+}
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#define _DEBUGPRINT(Message) \
+{ \
+ va_list arguments; \
+ \
+ va_start(arguments, Message); \
+ _Print(Message, arguments); \
+ va_end(arguments); \
+}
+
+/******************************************************************************\
+********************************** Debug Code **********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Print
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTrace
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZone
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugBreak
+**
+** Break into the debugger.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugBreak(
+ void
+ )
+{
+ gckOS_DebugTrace(gcvLEVEL_ERROR, "gckOS_DebugBreak");
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFatal
+**
+** Send a message to the debugger and break into the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ _DEBUGPRINT(Message);
+
+ /* Break into the debugger. */
+ gckOS_DebugBreak();
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevel
+**
+** Set the debug level.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ )
+{
+ _debugLevel = Level;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZone
+**
+** Set the debug zone.
+**
+** INPUT:
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ )
+{
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevelZone
+**
+** Set the debug level and zone.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ )
+{
+ _debugLevel = Level;
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZones
+**
+** Enable or disable debug zones.
+**
+** INPUT:
+**
+** gctUINT32 Zones
+** Debug zones to enable or disable.
+**
+** gctBOOL Enable
+** Set to gcvTRUE to enable the zones (or the Zones with the current
+** zones) or gcvFALSE to disable the specified Zones.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ )
+{
+ if (Enable)
+ {
+ /* Enable the zones. */
+ _debugZones |= Zones;
+ }
+ else
+ {
+ /* Disable the zones. */
+ _debugZones &= ~Zones;
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_Verify
+**
+** Called to verify the result of a function call.
+**
+** INPUT:
+**
+** gceSTATUS Status
+** Function call result.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Verify(
+ IN gceSTATUS Status
+ )
+{
+ _lastError = Status;
+}
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.c
new file mode 100644
index 0000000..d4240d7
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.c
@@ -0,0 +1,1251 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/slab.h>
+#define _GC_OBJ_ZONE gcvZONE_DEVICE
+
+#ifdef FLAREON
+static struct dove_gpio_irq_handler gc500_handle;
+#endif
+
+/******************************************************************************\
+******************************** gckGALDEVICE Code *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckGALDEVICE_AllocateMemory(
+ IN gckGALDEVICE Device,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPHYS_ADDR *Physical,
+ OUT gctUINT32 *PhysAddr
+ )
+{
+ gceSTATUS status;
+
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PhysAddr != gcvNULL);
+
+ status = gckOS_AllocateContiguous(Device->os,
+ gcvFALSE,
+ &Bytes,
+ Physical,
+ Logical);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkLOG_ERROR_ARGS("status=%d, allocate memory error", status);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "gckGALDEVICE_AllocateMemory: error status->0x%x",
+ status);
+
+ return status;
+ }
+
+ *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "gckGALDEVICE_AllocateMemory: phys_addr->0x%x phsical->0x%x Logical->0x%x",
+ (gctUINT32)*Physical,
+ (gctUINT32)*PhysAddr,
+ (gctUINT32)*Logical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_FreeMemory(
+ IN gckGALDEVICE Device,
+ IN gctPOINTER Logical,
+ IN gctPHYS_ADDR Physical)
+{
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ return gckOS_FreeContiguous(Device->os,
+ Physical,
+ Logical,
+ ((PLINUX_MDL)Physical)->numPages*PAGE_SIZE);
+}
+
+irqreturn_t isrRoutine(int irq, void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+ int handled = 0;
+
+ /* Call kernel interrupt notification. */
+ if (gckKERNEL_Notify(device->kernel,
+ gcvNOTIFY_INTERRUPT,
+ gcvTRUE) == gcvSTATUS_OK)
+ {
+ device->dataReady = gcvTRUE;
+
+ up(&device->sema);
+
+ handled = 1;
+ }
+
+ return IRQ_RETVAL(handled);
+}
+
+int threadRoutine(void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Starting isr Thread with extension->0x%p\n",
+ device);
+
+ while (1)
+ {
+
+ if(down_interruptible(&device->sema) == 0)
+ {
+ device->dataReady = gcvFALSE;
+
+ if (device->killThread == gcvTRUE)
+ {
+ /* The daemon exits. */
+ while (!kthread_should_stop())
+ {
+ gckOS_Delay(device->os, 1);
+ }
+
+ return 0;
+ }
+ else
+ {
+ gckKERNEL_Notify(device->kernel, gcvNOTIFY_INTERRUPT, gcvFALSE);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+#if MRVL_TIMER
+
+int timer_thread(void *ctxt)
+{
+ gceSTATUS status;
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+ gctUINT32 idle;
+
+ while (1)
+ {
+ if(down_interruptible(&device->timersema) == 0)
+ {
+ gcmkONERROR(gckOS_AcquireRecMutex(device->os,
+ device->kernel->hardware->recMutexPower,
+ gcvINFINITE));
+
+ gcmkONERROR(gckHARDWARE_GetIdle(device->kernel->hardware,
+ gcvFALSE,
+ &idle));
+
+ gcmkPRINT("idle = %x\n", idle);
+ gcmkONERROR(gckOS_ReleaseRecMutex(device->os,
+ device->kernel->hardware->recMutexPower));
+ }
+ }
+
+ return 0;
+
+OnError:
+ gcmkPRINT("ERROR: %s has error \n",__func__);
+ return status;
+}
+
+void timer_fn(unsigned long arg)
+{
+ gckGALDEVICE device = (gckGALDEVICE) arg;
+
+ up(&device->timersema);
+
+ /* triggle per second */
+ mod_timer(&device->timer, jiffies + HZ);
+}
+#endif
+
+#if MRVL_PROFILE_THREAD
+int profile_thread(void *ctxt)
+{
+ gceSTATUS status;
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+ gctUINT32 delayTime = 300; /* should be the max time of once draw */
+
+ while (1)
+ {
+ delayTime = device->profileStep;
+
+ if((device->os != gcvNULL)
+ && (device->kernel != gcvNULL)
+ && (device->kernel->command != gcvNULL)
+ && (device->kernel->atomClients > 0))
+ {
+ gckCOMMAND command = device->kernel->command;
+
+ /* hold profile thread if GC is off */
+ gcmkONERROR(gckOS_AcquireSemaphore(device->os, command->powerSemaphore));
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(device->os, command->powerSemaphore));
+
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireRecMutex(device->os, device->kernel->hardware->recMutexPower, gcvINFINITE));
+
+ /*
+ FIXME:
+ current idle event has bug, which may not set GC to be idle
+ after early suspend. NotifyIdle here can temporarily solve this issue.
+ */
+ if(device->clkEnabled && (device->currentPMode != gcvPM_NORMAL))
+ {
+ gctBOOL isIdle;
+ gcmkONERROR(gckHARDWARE_QueryIdle(device->kernel->hardware, &isIdle));
+
+ if(isIdle)
+ {
+ if(device->kernel->command->idle == gcvFALSE)
+ {
+ device->kernel->command->idle = gcvTRUE;
+ gcmkONERROR(gckOS_NotifyIdle(device->os, gcvTRUE));
+ }
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(device->os, device->kernel->hardware->recMutexPower));
+
+ /* power off GC when idle */
+ if(device->powerOffWhenIdle)
+ {
+ gckOS_PowerOffWhenIdle(device->os, gcvTRUE);
+ }
+
+ /* */
+ gcmkONERROR(gckOS_Delay(device->os, delayTime));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_Delay(device->os, 10000));
+ /* schedule_timeout_interruptible(500); */
+ }
+ }
+
+ return 0;
+
+OnError:
+ gcmkPRINT("ERROR: %s has error \n",__func__);
+ return status;
+}
+#endif
+
+#if MRVL_GUARD_THREAD
+
+#if MRVL_PRINT_CMD_BUFFER
+extern void _PrintCmdBuffer(
+ gckCOMMAND Command,
+ gctUINT Address
+ );
+#endif
+
+int guard_thread(void *ctxt)
+{
+ gceSTATUS status;
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+ gctUINT32 captureAddr = GC_INVALID_PHYS_ADDR;
+ gctUINT32 currentAddr = GC_INVALID_PHYS_ADDR;
+ gctUINT32 delayTime = 300; /* should be the max time of once draw */
+ gctINT32 atomRefMark, ref;
+ gctBOOL isIdle;
+
+ while (1)
+ {
+ delayTime = device->profileStep;
+
+ if((device->os != gcvNULL)
+ && (device->kernel != gcvNULL)
+ && (device->kernel->command != gcvNULL)
+ && (device->kernel->atomClients > 0))
+ {
+ gckCOMMAND command = device->kernel->command;
+ gctBOOL needSilentReset = gcvFALSE;
+ static gctUINT count = 0;
+ gctUINT32 lastWaitLink = GC_INVALID_PHYS_ADDR;
+
+ /* hold guard thread if GC is off */
+ gcmkONERROR(gckOS_AcquireSemaphore(device->os, command->powerSemaphore));
+ gcmkVERIFY_OK(gckOS_ReleaseSemaphore(device->os, command->powerSemaphore));
+
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireRecMutex(device->os, device->kernel->hardware->recMutexPower, gcvINFINITE));
+
+ if(device->clkEnabled)
+ {
+ lastWaitLink = device->kernel->hardware->lastWaitLink;
+
+ /* Read the current FE address. */
+ gcmkONERROR(gckOS_ReadRegister(device->os,
+ 0x00664,
+ &currentAddr));
+
+ /* Test if address is outside the last WAIT/LINK sequence. */
+ if( (currentAddr == captureAddr)
+ && ((currentAddr < lastWaitLink) || (currentAddr >= lastWaitLink + 16)))
+ {
+ count++;
+
+ if(device->powerDebug)
+ {
+ gcmkPRINT("GPU stop at 0x%x for %d ms, lastWaitLink = 0x%08x\n",currentAddr,delayTime*count, lastWaitLink);
+ }
+
+ if (count == 1)
+ {
+ /* Acquire current event count at first time */
+ gckOS_AtomGet(device->os, device->kernel->event->atomEventRef, &atomRefMark);
+ }
+ else
+ {
+ /* Acquire event count again at second or third time */
+ gckOS_AtomGet(device->os, device->kernel->event->atomEventRef, &ref);
+
+ /* Event counts changed, that means some event successfully returned between
+ these two checking points which further indicates that GC hardware is still
+ working, so we clear "count" here and the capture address remains unchanged.*/
+ if (atomRefMark != ref)
+ {
+ count = 0;
+ }
+ }
+ }
+ else
+ {
+ captureAddr = currentAddr;
+ count = 0;
+ }
+
+ if(count >= 3)
+ {
+ if(device->powerDebug)
+ {
+ gcmkPRINT("GPU may hang, [captureAddr,currentAddr,lastWaitLink] = [0x%x,0x%x,0x%x]\n",
+ captureAddr,currentAddr,device->kernel->hardware->lastWaitLink);
+ }
+
+ needSilentReset = gcvTRUE;
+ count = 0;
+ }
+
+ /* GPU stop at the same address */
+ if(needSilentReset)
+ {
+#if MRVL_PRINT_CMD_BUFFER
+ if(device->kernel->command->dumpCmdBuf)
+ {
+ gctUINT i;
+ gctUINT32 idle;
+ gctUINT32 intAck;
+ gctUINT32 prevAddr = 0;
+ gctUINT32 currAddr;
+ gctBOOL changeDetected;
+
+ changeDetected = gcvFALSE;
+
+ /* IDLE */
+ gcmkONERROR(gckOS_ReadRegister(device->os, 0x0004, &idle));
+
+ /* INT ACK */
+ gcmkONERROR(gckOS_ReadRegister(device->os, 0x0010, &intAck));
+
+ /* DMA POS */
+ for (i = 0; i < 300; i += 1)
+ {
+ gcmkONERROR(gckOS_ReadRegister(device->os, 0x0664, &currAddr));
+
+ if ((i > 0) && (prevAddr != currAddr))
+ {
+ changeDetected = gcvTRUE;
+ }
+
+ prevAddr = currAddr;
+ }
+
+ gcmkPRINT("\n%s(%d):\n"
+ " idle = 0x%08X\n"
+ " int = 0x%08X\n"
+ " dma = 0x%08X (change=%d)\n",
+ __FUNCTION__, __LINE__,
+ idle,
+ intAck,
+ currAddr,
+ changeDetected
+ );
+
+ _PrintCmdBuffer(device->kernel->command, currAddr);
+
+ }
+#endif
+
+ gcmkONERROR(gckHARDWARE_QueryIdle(device->kernel->hardware, &isIdle));
+ /* gcmkPRINT("[galcore], timeout, isIdle=%d\n",isIdle); */
+
+ if(isIdle == gcvFALSE)
+ {
+ /* silent reset */
+ if(device->silentReset)
+ {
+ gcmkONERROR(gckOS_Reset(device->os));
+ }
+ }
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(device->os, device->kernel->hardware->recMutexPower));
+
+ /* */
+ gcmkONERROR(gckOS_Delay(device->os, delayTime));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_Delay(device->os, 10000));
+ /* schedule_timeout_interruptible(500); */
+ }
+ }
+
+ return 0;
+
+OnError:
+ gcmkPRINT("ERROR: %s has error \n",__func__);
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Setup_ISR
+**
+** Start the ISR routine.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Setup successfully.
+** gcvSTATUS_GENERIC_IO
+** Setup failed.
+*/
+gceSTATUS
+gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ gctINT ret;
+
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ if (Device->irqLine == 0)
+ {
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+ gc500_handle.dev_name = "galcore interrupt service";
+ gc500_handle.dev_id = Device;
+ gc500_handle.handler = isrRoutine;
+ gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
+ gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+ ret = dove_gpio_request (DOVE_GPIO0_7, &gc500_handle);
+#else
+ ret = request_irq(Device->irqLine,
+ isrRoutine,
+ IRQF_DISABLED,
+ "galcore interrupt service",
+ Device);
+#endif
+
+
+ if (ret != 0) {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Setup_ISR: "
+ "Could not register irq line->%d\n",
+ Device->irqLine);
+
+ Device->isrInitialized = gcvFALSE;
+
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ Device->isrInitialized = gcvTRUE;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Setup_ISR: "
+ "Setup the irq line->%d\n",
+ Device->irqLine);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Release_ISR
+**
+** Release the irq line.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ /* release the irq */
+ if (Device->isrInitialized)
+ {
+#ifdef FLAREON
+ dove_gpio_free (DOVE_GPIO0_7, "galcore interrupt service");
+#else
+ free_irq(Device->irqLine, Device);
+#endif
+ Device->isrInitialized = gcvFALSE;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start_Thread
+**
+** Start the daemon thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+** gcvSTATUS_GENERIC_IO
+** Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Thread(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ /* start the kernel thread */
+ Device->threadCtxt = kthread_run(threadRoutine,
+ Device,
+ "galcore daemon thread");
+
+ Device->threadInitialized = gcvTRUE;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Start_Thread: "
+ "Stat the daemon thread.\n");
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop_Thread
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop_Thread(
+ gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ /* stop the thread */
+ if (Device->threadInitialized)
+ {
+ Device->killThread = gcvTRUE;
+ up(&Device->sema);
+
+ kthread_stop(Device->threadCtxt);
+
+ Device->threadInitialized = gcvFALSE;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start
+**
+** Start the gal device, including the following actions: setup the isr routine
+** and start the daemoni thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+*/
+gceSTATUS
+gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ )
+{
+ /* start the daemon thread */
+ gcmkVERIFY_OK(gckGALDEVICE_Start_Thread(Device));
+
+ /* setup the isr routine */
+ gcmkVERIFY_OK(gckGALDEVICE_Setup_ISR(Device));
+
+ /*
+ gcvPOWER_SUSPEND will stop GC and disable 2D/3D clk.
+ Since frequency scaling is enabled, disable 2D/3D clk will gain little
+ but lead to potential issue. I prefer not change power state here.
+ */
+#if 0
+ /* Switch to SUSPEND power state. */
+ /* To simplify power state logic, temporarily use gcvPOWER_OFF instead*/
+ gcmkVERIFY_OK(
+ gckHARDWARE_SetPowerManagementState(Device->kernel->hardware,
+ gcvPOWER_SUSPEND_ATPOWERON));
+#endif
+
+#if MRVL_PROFILE_THREAD
+ Device->profilethread= kthread_run(profile_thread,
+ Device,
+ "galcore profile thread");
+#endif
+
+#if MRVL_GUARD_THREAD
+ Device->guardthread= kthread_run(guard_thread,
+ Device,
+ "galcore guard thread");
+#endif
+
+#if MRVL_TIMER
+ sema_init(&Device->timersema, 0);
+ init_timer(&Device->timer);
+
+ Device->timerthread = kthread_run(timer_thread,
+ Device,
+ "timer thread");
+
+ Device->timer.data = (unsigned long)Device;
+ Device->timer.function = timer_fn;
+ /* triggle per second */
+ Device->timer.expires = jiffies + HZ;
+ add_timer(&Device->timer);
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ /*
+ There is not need to change power state here
+ */
+#if 0
+ /* Switch to ON power state. */
+ gcmkVERIFY_OK(
+ gckHARDWARE_SetPowerManagementState(Device->kernel->hardware,
+ gcvPOWER_ON));
+#endif
+ if (Device->isrInitialized)
+ {
+ gckGALDEVICE_Release_ISR(Device);
+ }
+
+ if (Device->threadInitialized)
+ {
+ gckGALDEVICE_Stop_Thread(Device);
+ }
+
+#if MRVL_PROFILE_THREAD
+ kthread_stop(Device->profilethread);
+#endif
+
+#if MRVL_GUARD_THREAD
+ kthread_stop(Device->guardthread);
+#endif
+
+#if MRVL_TIMER
+ del_timer(&Device->timer);
+ kthread_stop(Device->timerthread);
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Construct
+**
+** Constructor.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gckGALDEVICE * Device
+** Pointer to a variable receiving the gckGALDEVICE object pointer on
+** success.
+*/
+gceSTATUS
+gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 BaseAddress,
+ IN gctINT Signal,
+ OUT gckGALDEVICE *Device
+ )
+{
+ gctUINT32 internalBaseAddress, internalAlignment;
+ gctUINT32 externalBaseAddress, externalAlignment;
+ gctUINT32 horizontalTileSize, verticalTileSize;
+ gctUINT32 physAddr;
+ gctUINT32 physical;
+ gckGALDEVICE device;
+ gceSTATUS status;
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Enter gckGALDEVICE_Construct\n");
+
+ gcmkPRINT("\n[galcore] registerBase =0x%08x, registerMemSize = 0x%08x, contiguousBase= 0x%08x, contiguousSize = 0x%08x\n",
+ (gctUINT32)RegisterMemBase, (gctUINT32)RegisterMemSize, (gctUINT32)ContiguousBase, (gctUINT32)ContiguousSize);
+ /* Allocate device structure. */
+ device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL);
+ if (!device)
+ {
+ gcmkLOG_ERROR_ARGS("Can't allocate memory for device.");
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Can't allocate memory.\n");
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ memset(device, 0, sizeof(struct _gckGALDEVICE));
+
+ device->clkEnabled = gcvTRUE;
+
+ physical = RegisterMemBase;
+
+ /* Set up register memory region */
+ if (physical != 0)
+ {
+ /* Request a region. */
+ request_mem_region(RegisterMemBase, RegisterMemSize, "galcore register region");
+ device->registerBase = (gctPOINTER) ioremap_nocache(RegisterMemBase,
+ RegisterMemSize);
+ if (!device->registerBase)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Unable to map location->0x%lX for size->%ld\n",
+ RegisterMemBase,
+ RegisterMemSize);
+ /* free device to avoid memory leakage*/
+ kfree(device);
+ device = gcvNULL;
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ physical += RegisterMemSize;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: "
+ "RegisterBase after mapping Address->0x%x is 0x%x\n",
+ (gctUINT32)RegisterMemBase,
+ (gctUINT32)device->registerBase);
+ }
+
+ device->baseAddress = BaseAddress;
+
+ /* construct the gckOS object */
+ gcmkONERROR(gckOS_Construct(device, &device->os));
+
+ /* construct the gckKERNEL object. */
+ gcmkONERROR(gckKERNEL_Construct(device->os, device, &device->kernel));
+
+ /* set fast clear. */
+ gcmkONERROR(gckHARDWARE_SetFastClear(device->kernel->hardware,
+ FastClear,
+ Compression));
+
+ /* query the ceiling of the system memory */
+ gcmkONERROR(gckHARDWARE_QuerySystemMemory(device->kernel->hardware,
+ &device->systemMemorySize,
+ &device->systemMemoryBaseAddress));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: "
+ "Will be trying to allocate contiguous memory of 0x%x bytes\n",
+ (gctUINT32)device->systemMemoryBaseAddress);
+
+#if COMMAND_PROCESSOR_VERSION == 1
+ /* start the command queue */
+ gcmkONERROR(gckCOMMAND_Start(device->kernel->command));
+#endif
+
+ /* initialize the thread daemon */
+ sema_init(&device->sema, 0);
+
+ device->threadInitialized = gcvFALSE;
+ device->killThread = gcvFALSE;
+
+ /* initialize the isr */
+ device->isrInitialized = gcvFALSE;
+ device->dataReady = gcvFALSE;
+ device->irqLine = IrqLine;
+
+ device->signal = Signal;
+
+ device->printPID = gcvFALSE;
+ device->silentReset = gcvTRUE;
+ device->powerOffWhenIdle = gcvTRUE;
+ device->profileStep = 300; /* profiling every 300 ms */
+ device->profileTimeSlice = 300; /* take recent 300 ms as profiling foundation */
+ /* for a 30 fps application, recent 33 ms idle means the app may be paused */
+ device->profileTailTimeSlice = 33;
+ device->powerDebug = gcvFALSE;
+ device->idleThreshold = 80; /* try to power off GC when idle time > 80% */
+ device->needPowerOff = gcvFALSE;
+
+#if SEPARATE_CLOCK_AND_POWER && KEEP_POWER_ON
+ device->clkOffOnly = gcvTRUE;
+#else
+ device->clkOffOnly = gcvFALSE;
+#endif
+
+ device->currentPMode = gcvPM_NORMAL;
+
+ device->enableLowPowerMode = gcvFALSE;
+ device->enableDVFM = gcvTRUE;
+
+ memset(device->profNode, 0, NUM_PROFILE_NODES*sizeof(struct _gckProfNode));
+ device->lastNodeIndex = 0;
+
+ device->memRandomFailRate = 0;
+
+ /* query the amount of video memory */
+ gcmkONERROR(gckHARDWARE_QueryMemory(device->kernel->hardware,
+ &device->internalSize,
+ &internalBaseAddress,
+ &internalAlignment,
+ &device->externalSize,
+ &externalBaseAddress,
+ &externalAlignment,
+ &horizontalTileSize,
+ &verticalTileSize));
+
+ /* set up the internal memory region */
+ if (device->internalSize > 0)
+ {
+ gceSTATUS status = gckVIDMEM_Construct(device->os,
+ internalBaseAddress,
+ device->internalSize,
+ internalAlignment,
+ 0,
+ &device->internalVidMem);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* error, remove internal heap */
+ device->internalSize = 0;
+ }
+ else
+ {
+ /* map internal memory */
+ device->internalPhysical = (gctPHYS_ADDR)physical;
+ device->internalLogical = (gctPOINTER)ioremap_nocache(
+ physical, device->internalSize);
+
+ gcmkASSERT(device->internalLogical != gcvNULL);
+
+ physical += device->internalSize;
+ }
+ }
+
+ if (device->externalSize > 0)
+ {
+ /* create the external memory heap */
+ gceSTATUS status = gckVIDMEM_Construct(device->os,
+ externalBaseAddress,
+ device->externalSize,
+ externalAlignment,
+ 0,
+ &device->externalVidMem);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* error, remove internal heap */
+ device->externalSize = 0;
+ }
+ else
+ {
+ /* map internal memory */
+ device->externalPhysical = (gctPHYS_ADDR)physical;
+ device->externalLogical = (gctPOINTER)ioremap_nocache(
+ physical, device->externalSize);
+
+ gcmkASSERT(device->externalLogical != gcvNULL);
+
+ physical += device->externalSize;
+ }
+ }
+
+ /* set up the contiguous memory */
+ device->contiguousSize = ContiguousSize;
+
+ if (ContiguousBase == 0)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+
+ while (device->contiguousSize > 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Will be trying to allocate contiguous memory of %ld bytes\n",
+ device->contiguousSize
+ );
+
+ /* allocate contiguous memory */
+ status = gckGALDEVICE_AllocateMemory(
+ device,
+ device->contiguousSize,
+ &device->contiguousBase,
+ &device->contiguousPhysical,
+ &physAddr
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Contiguous allocated size->0x%08X Virt->0x%08lX physAddr->0x%08X\n",
+ device->contiguousSize,
+ device->contiguousBase,
+ physAddr
+ );
+
+ status = gckVIDMEM_Construct(
+ device->os,
+ physAddr | device->systemMemoryBaseAddress,
+ device->contiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ device->contiguousMapped = gcvFALSE;
+
+ /* success, abort loop */
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Using %u bytes of contiguous memory.\n",
+ device->contiguousSize
+ );
+
+ break;
+ }
+
+ gcmkONERROR(gckGALDEVICE_FreeMemory(
+ device,
+ device->contiguousBase,
+ device->contiguousPhysical
+ ));
+
+ device->contiguousBase = gcvNULL;
+ }
+
+ if (device->contiguousSize <= (4 << 20))
+ {
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ device->contiguousSize -= (4 << 20);
+ }
+ }
+ }
+ else
+ {
+ /* Create the contiguous memory heap. */
+ status = gckVIDMEM_Construct(
+ device->os,
+ (ContiguousBase - device->baseAddress) | device->systemMemoryBaseAddress,
+ ContiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, roll back. */
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ /* Map the contiguous memory. */
+ request_mem_region(
+ ContiguousBase,
+ ContiguousSize,
+ "galcore managed memory"
+ );
+
+ device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
+ device->contiguousSize = ContiguousSize;
+// device->contiguousBase = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
+ device->contiguousBase = (gctPOINTER)ContiguousBase;
+ device->contiguousMapped = gcvTRUE;
+
+ if (device->contiguousBase == gcvNULL)
+ {
+ /* Error, roll back. */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(device->contiguousVidMem));
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ }
+ }
+ }
+
+ *Device = device;
+
+ gcmkPRINT("\n[galcore] real contiguouSize = 0x%08x \n", (gctUINT32)(device->contiguousSize));
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Initialized device->0x%p contiguous->%lu @ 0x%p (0x%08X)\n",
+ device,
+ device->contiguousSize,
+ device->contiguousBase,
+ device->contiguousPhysical);
+
+ /* Init GC memory profile. */
+ device->reservedMem = ContiguousSize;
+ device->vidMemUsage = 0;
+ device->contiguousMemUsage = 0;
+ device->virtualMemUsage = 0;
+
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Destroy
+**
+** Class destructor.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+ gckGALDEVICE Device)
+{
+ gcmkVERIFY_ARGUMENT(Device != gcvNULL);
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[ENTER] gckGALDEVICE_Destroy\n");
+
+ /* Destroy the gckKERNEL object. */
+ gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernel));
+ Device->kernel = gcvNULL;
+
+ if (Device->internalVidMem != gcvNULL)
+ {
+ /* destroy the internal heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+
+ Device->internalVidMem = gcvNULL;
+ /* unmap the internal memory */
+ iounmap(Device->internalLogical);
+ }
+
+ if (Device->externalVidMem != gcvNULL)
+ {
+ /* destroy the internal heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+
+ Device->externalVidMem = gcvNULL;
+ /* unmap the external memory */
+ iounmap(Device->externalLogical);
+ }
+
+ if (Device->contiguousVidMem != gcvNULL)
+ {
+ /* Destroy the contiguous heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+ Device->contiguousVidMem = gcvNULL;
+
+ if (Device->contiguousMapped)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Destroy: "
+ "Unmapping contiguous memory->0x%08lX\n",
+ Device->contiguousBase);
+
+ iounmap(Device->contiguousBase);
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Destroy: "
+ "Freeing contiguous memory->0x%08lX\n",
+ Device->contiguousBase);
+
+ gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(Device,
+ Device->contiguousBase,
+ Device->contiguousPhysical));
+ }
+ }
+
+ if (Device->registerBase)
+ {
+ iounmap(Device->registerBase);
+ }
+
+ /* Destroy the gckOS object. */
+ gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+ Device->os = gcvNULL;
+
+ kfree(Device);
+ Device = gcvNULL;
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Leave gckGALDEVICE_Destroy\n");
+
+ return gcvSTATUS_OK;
+}
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.h
new file mode 100644
index 0000000..b2d89a7
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_device.h
@@ -0,0 +1,225 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_device_h_
+#define __gc_hal_kernel_device_h_
+
+#define gcdkUSE_MEMORY_RECORD 1
+
+#ifdef ANDROID
+#define gcdkREPORT_VIDMEM_LEAK 0
+#else
+#define gcdkREPORT_VIDMEM_LEAK 1
+#endif
+
+/******************************************************************************\
+******************************* gckGALDEVICE Structure *******************************
+\******************************************************************************/
+typedef enum _gcePOWRE_MODE
+{
+ gcvPM_NORMAL,
+#if MRVL_CONFIG_ENABLE_EARLYSUSPEND
+ gcvPM_EARLY_SUSPEND,
+#endif
+ gcvPM_SUSPEND,
+}
+gcePOWER_MODE;
+
+typedef struct _gckProfNode
+{
+ gctBOOL idle;
+ gctUINT tick;
+}
+*gckProfNode;
+
+typedef struct _gckGALDEVICE
+{
+ /* Objects. */
+ gckOS os;
+ gckKERNEL kernel;
+
+ /* Attributes. */
+ gctSIZE_T internalSize;
+ gctPHYS_ADDR internalPhysical;
+ gctPOINTER internalLogical;
+ gckVIDMEM internalVidMem;
+ gctSIZE_T externalSize;
+ gctPHYS_ADDR externalPhysical;
+ gctPOINTER externalLogical;
+ gckVIDMEM externalVidMem;
+ gckVIDMEM contiguousVidMem;
+ gctPOINTER contiguousBase;
+ gctPHYS_ADDR contiguousPhysical;
+ gctSIZE_T contiguousSize;
+ gctBOOL contiguousMapped;
+ gctPOINTER contiguousMappedUser;
+ gctSIZE_T systemMemorySize;
+ gctUINT32 systemMemoryBaseAddress;
+ gctPOINTER registerBase;
+ gctSIZE_T registerSize;
+ gctUINT32 baseAddress;
+
+ /* IRQ management. */
+ gctINT irqLine;
+ gctBOOL isrInitialized;
+ gctBOOL dataReady;
+
+ /* Thread management. */
+ struct task_struct *threadCtxt;
+ struct semaphore sema;
+ gctBOOL threadInitialized;
+ gctBOOL killThread;
+
+ /* Signal management. */
+ gctINT signal;
+
+#if MRVL_CONFIG_ENABLE_DVFM
+ /* dvfm device index */
+ gctINT dvfm_dev_index;
+#endif
+
+ /* current power mode */
+ gcePOWER_MODE currentPMode;
+
+ /* do silent reset */
+ gctBOOL silentReset;
+ gctBOOL powerDebug;
+
+ /* power off GC when idle */
+ gctBOOL powerOffWhenIdle;
+ gctUINT32 profileStep;
+ gctUINT32 profileTimeSlice;
+ gctUINT32 profileTailTimeSlice;
+ gctUINT32 idleThreshold;
+ gctBOOL needPowerOff;
+ gctBOOL clkOffOnly;
+
+ /* print pid of the process that is using GC */
+ gctBOOL printPID;
+
+ /* enable/disable DVFM LPM by default */
+ gctBOOL enableDVFM;
+ gctBOOL enableLowPowerMode;
+
+ /* mark GC power and clk status */
+ gctBOOL clkEnabled;
+
+ /* profiling data */
+ struct _gckProfNode profNode[100];
+ gctUINT32 lastNodeIndex;
+
+#if MRVL_TIMER
+ /* the timer thread */
+ struct timer_list timer;
+ struct semaphore timersema;
+ struct task_struct *timerthread;
+#endif
+
+#if MRVL_PROFILE_THREAD
+ /* the profile thread */
+ struct task_struct *profilethread;
+#endif
+
+#if MRVL_GUARD_THREAD
+ /* the guard thread */
+ struct task_struct *guardthread;
+#endif
+
+ /* GC memory profile */
+ gctSIZE_T reservedMem;
+ gctINT32 vidMemUsage;
+ gctINT32 contiguousMemUsage;
+ gctINT32 virtualMemUsage;
+
+ /* simulate memory allocation random fail */
+ gctINT32 memRandomFailRate;
+}
+* gckGALDEVICE;
+
+#if gcdkUSE_MEMORY_RECORD
+typedef struct MEMORY_RECORD
+{
+ gcuVIDMEM_NODE_PTR node;
+
+ struct MEMORY_RECORD * prev;
+ struct MEMORY_RECORD * next;
+}
+MEMORY_RECORD, * MEMORY_RECORD_PTR;
+#endif
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+ gckGALDEVICE device;
+ gctPOINTER mappedMemory;
+ gctPOINTER contiguousLogical;
+
+#if gcdkUSE_MEMORY_RECORD
+ MEMORY_RECORD memoryRecordList;
+#endif
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start_Thread(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop_Thread(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 BaseAddress,
+ IN gctINT Signal,
+ OUT gckGALDEVICE *Device
+ );
+
+gceSTATUS gckGALDEVICE_Destroy(
+ IN gckGALDEVICE Device
+ );
+
+#endif /* __gc_hal_kernel_device_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_driver.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_driver.c
new file mode 100644
index 0000000..3792833
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_driver.c
@@ -0,0 +1,1262 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+#include <linux/device.h>
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_user_context.h"
+
+#ifdef ENABLE_GPU_CLOCK_BY_DRIVER
+#undef ENABLE_GPU_CLOCK_BY_DRIVER
+#endif
+
+#if (defined CONFIG_DOVE_GPU)
+#define ENABLE_GPU_CLOCK_BY_DRIVER 0
+#else
+#define ENABLE_GPU_CLOCK_BY_DRIVER 1
+#endif
+
+/* You can comment below line to use legacy driver model */
+#define USE_PLATFORM_DRIVER 1
+
+#if USE_PLATFORM_DRIVER
+#include <linux/platform_device.h>
+#endif
+
+#if MRVL_PLATFORM_MMP2
+#include <mach/cputype.h>
+#endif
+
+#if MRVL_CONFIG_ENABLE_DVFM
+#include <mach/dvfm.h>
+#endif
+
+MODULE_DESCRIPTION("Vivante Graphics Driver");
+MODULE_LICENSE("GPL");
+
+struct class *gpuClass;
+
+static gckGALDEVICE galDevice;
+
+static int major = 199;
+module_param(major, int, 0644);
+
+#ifdef CONFIG_MACH_CUBOX
+ int irqLine = 42;
+ long registerMemBase = 0xf1840000;
+ ulong contiguousBase = 0x8000000;
+#else
+ int irqLine = 8;
+ long registerMemBase = 0xc0400000;
+ ulong contiguousBase = 0;
+#endif
+
+module_param(irqLine, int, 0644);
+module_param(registerMemBase, long, 0644);
+
+ulong registerMemSize = 256 << 10;
+module_param(registerMemSize, ulong, 0644);
+
+
+long contiguousSize = 32 << 20;
+module_param(contiguousSize, long, 0644);
+module_param(contiguousBase, ulong, 0644);
+
+long bankSize = 32 << 20;
+module_param(bankSize, long, 0644);
+
+int fastClear = -1;
+module_param(fastClear, int, 0644);
+
+int compression = -1;
+module_param(compression, int, 0644);
+
+int signal = 48;
+module_param(signal, int, 0644);
+
+ulong baseAddress = 0;
+module_param(baseAddress, ulong, 0644);
+
+int showArgs = 1;
+module_param(showArgs, int, 0644);
+
+ulong gpu_frequency = 312;
+module_param(gpu_frequency, ulong, 0644);
+
+/******************************************************************************\
+* Create a data entry system using proc for GC
+\******************************************************************************/
+#define MRVL_CONFIG_PROC
+
+#ifdef MRVL_CONFIG_PROC
+#include <linux/proc_fs.h>
+
+#define GC_PROC_FILE "driver/gc"
+#define _GC_OBJ_ZONE gcvZONE_DRIVER
+
+static struct proc_dir_entry * gc_proc_file;
+
+/* cat /proc/driver/gc will print gc related msg */
+static ssize_t gc_proc_read(struct file *file,
+ char __user *buffer, size_t count, loff_t *offset)
+{
+ gceSTATUS status;
+ ssize_t len = 0;
+ char buf[1000];
+ gctUINT32 idle;
+ gctBOOL isIdle;
+ gctUINT32 clockControl;
+
+ len += sprintf(buf+len, "%s(%s)\n", _VENDOR_STRING_, _GC_VERSION_STRING_);
+#ifdef _DEBUG
+ len += sprintf(buf+len, "DEBUG VERSION\n");
+#else
+ len += sprintf(buf+len, "RELEASE VERSION\n");
+#endif
+
+ gcmkONERROR(gckHARDWARE_GetIdle(galDevice->kernel->hardware, gcvFALSE, &idle));
+ gcmkONERROR(gckHARDWARE_QueryIdle(galDevice->kernel->hardware, &isIdle));
+ len += sprintf(buf+len, "idle register: 0x%02x, hardware is %s\n", idle, (gcvTRUE == isIdle)?"idle":"busy");
+
+ gcmkONERROR(gckOS_ReadRegister(galDevice->os, 0x00000, &clockControl));
+ len += sprintf(buf+len, "clockControl register: 0x%02x\n", clockControl);
+
+ len += sprintf(buf+len, "print mode:\tPid(%d) Reset(%d) DumpCmdBuf(%d)\n",
+ galDevice->printPID, galDevice->silentReset, galDevice->kernel->command->dumpCmdBuf);
+
+ len += sprintf(buf+len, "GC memory usage profile:\n");
+
+ len += sprintf(buf+len, "Total reserved video memory: %ld KB\n", galDevice->reservedMem/1024);
+
+ len += sprintf(buf+len, "Used video mem: %d KB\tcontiguous: %d KB\tvirtual: %d KB\n", galDevice->vidMemUsage/1024,
+ galDevice->contiguousMemUsage/1024, galDevice->virtualMemUsage/1024);
+
+ if (galDevice->kernel->mmu)
+ len += sprintf(buf+len, "MMU Entries usage(PageCount): Total(%d), Used(%d)\n", galDevice->kernel->mmu->pageTableEntries,galDevice->kernel->mmu->pageTableUsedEntries);
+
+ return simple_read_from_buffer(buffer, count, offset, buf, len);
+
+OnError:
+ return 0;
+}
+
+#if MRVL_PRINT_CMD_BUFFER
+extern gceSTATUS
+_PrintAllCmdBuffer(
+ gckCOMMAND Command
+ );
+#endif
+
+/* echo xx > /proc/driver/gc set ... */
+static ssize_t gc_proc_write(struct file *file,
+ const char *buff, size_t len, loff_t *off)
+{
+ char messages[256];
+
+ if(len > 256)
+ len = 256;
+
+ if(copy_from_user(messages, buff, len))
+ return -EFAULT;
+
+ gcmkPRINT("\n");
+ if(strncmp(messages, "printPID", 8) == 0)
+ {
+ galDevice->printPID = galDevice->printPID ? gcvFALSE : gcvTRUE;
+ gcmkPRINT("==>Change printPID to %s\n", galDevice->printPID ? "gcvTRUE" : "gcvFALSE");
+ }
+ else if(strncmp(messages, "powerDebug", 10) == 0)
+ {
+ galDevice->powerDebug= galDevice->powerDebug ? gcvFALSE : gcvTRUE;
+ }
+ else if(strncmp(messages, "profile", 7) == 0)
+ {
+ sscanf(messages+7,"%d %d %d %d",
+ &galDevice->profileStep,&galDevice->profileTimeSlice,&galDevice->profileTailTimeSlice,&galDevice->idleThreshold);
+ gcmkPRINT("==>Change profling [step timeSlice tailTimeSlice threshold] to be [%d %d %d %d]\n",
+ galDevice->profileStep,galDevice->profileTimeSlice,galDevice->profileTailTimeSlice,galDevice->idleThreshold);
+ }
+ else if(strncmp(messages, "hang", 4) == 0)
+ {
+ galDevice->kernel->hardware->hang = galDevice->kernel->hardware->hang ? gcvFALSE : gcvTRUE;
+ }
+ else if(strncmp(messages, "reset2", 6) == 0)
+ {
+ gckOS_Reset(galDevice->os);
+ }
+ else if(strncmp(messages, "memFail", 7) == 0)
+ {
+ gctUINT32 para = 0xFFFFFFFF;
+ sscanf(messages+7, "%d", &para);
+ galDevice->memRandomFailRate = para;
+ gcmkPRINT("==>Change memory random fail rate to %d%\n", galDevice->memRandomFailRate);
+ }
+ else if(strncmp(messages, "irq", 3) == 0)
+ {
+ gctUINT32 enable = ~0U;
+
+ sscanf(messages+3, "%d", &enable);
+
+ switch (enable) {
+ case 0:
+ /* disable GC interrupt line */
+ gckOS_SuspendInterrupt(galDevice->os);
+ break;
+ case 1:
+ /* enable GC interrupt line */
+ gckOS_ResumeInterrupt(galDevice->os);
+ break;
+ default:
+ gcmkPRINT("[galcore] Usage: echo irq [0|1] > /proc/driver/gc");
+ }
+ }
+ else if(strncmp(messages, "log", 3) == 0)
+ {
+ gctUINT32 filter = _GFX_LOG_NONE_;
+ gctUINT32 level = _GFX_LOG_NONE_;
+ /*
+ @Description
+ Only deal with the lowest two bits of input value
+ so level 5(0x101) is functional equivalent to level 1(0x001)
+ @level Val Hex Description
+ 0 0x00 print nothing
+ 1 0x01 print error log only
+ 2 0x10 print warning log only
+ 3 0x11 print error and warning info
+ @Sample
+ echo log 0 > /proc/driver/gc # Disable error log print
+ echo log 3 > /proc/driver/gc # Enable error & warning log print
+ */
+ sscanf(messages+3, "%d", &level);
+
+ if ((level & _GFX_LOG_ERROR_) != _GFX_LOG_NONE_)
+ filter |= _GFX_LOG_ERROR_;
+ if ((level & _GFX_LOG_WARNING_) != _GFX_LOG_NONE_)
+ filter |= _GFX_LOG_WARNING_;
+ gckOS_SetLogFilter(filter);
+ gcmkPRINT("==>Change log level to %d", filter);
+ }
+ else if(strncmp(messages, "silentReset", 11) == 0)
+ {
+ gctUINT32 para = 0xFFFFFFFF;
+
+ sscanf(messages+11, "%d", &para);
+
+ switch(para)
+ {
+ case 0:
+ galDevice->silentReset = gcvFALSE;
+ gcmkPRINT("==>Change silentReset to %s\n", galDevice->silentReset ? "gcvTRUE" : "gcvFALSE");
+ break;
+ case 1:
+ galDevice->silentReset = gcvTRUE;
+ gcmkPRINT("==>Change silentReset to %s\n", galDevice->silentReset ? "gcvTRUE" : "gcvFALSE");
+ break;
+ default:
+ gcmkPRINT("usage: \n \
+ to enable silent reset: #echo silentReset 1 > /proc/driver/gc \n \
+ to disable silent reset: #echo silentReset 0 > /proc/driver/gc \n");
+ break;
+ }
+ }
+ else if(strncmp(messages, "dumpCmdBuf", 10) == 0)
+ {
+ gctUINT32 para = 0xFFFFFFFF;
+
+ sscanf(messages+10, "%d", &para);
+
+ switch(para)
+ {
+ case 0:
+ galDevice->kernel->command->dumpCmdBuf = gcvFALSE;
+ gcmkPRINT("==>Change dumpCmdBuf to %s\n", galDevice->kernel->command->dumpCmdBuf ? "gcvTRUE" : "gcvFALSE");
+ break;
+ case 1:
+ galDevice->kernel->command->dumpCmdBuf = gcvTRUE;
+ gcmkPRINT("==>Change dumpCmdBuf to %s\n", galDevice->kernel->command->dumpCmdBuf ? "gcvTRUE" : "gcvFALSE");
+ break;
+ default:
+ gcmkPRINT("usage: \n \
+ to enable dump cmd buffer #echo dumpCmdBuf 1 > /proc/driver/gc \n \
+ to disable dump cmd buffer #echo dumpCmdBuf 0 > /proc/driver/gc \n");
+ break;
+ }
+ }
+#if MRVL_PRINT_CMD_BUFFER
+ else if(strncmp(messages, "dumpall", 7) == 0)
+ {
+ _PrintAllCmdBuffer(galDevice->kernel->command);
+ }
+#endif
+ else if(strncmp(messages, "clkoffonly", 10) == 0)
+ {
+ galDevice->clkOffOnly= galDevice->clkOffOnly? gcvFALSE : gcvTRUE;
+ gcmkPRINT("==>Change clkOffOnly to %s\n", galDevice->clkOffOnly ? "gcvTRUE" : "gcvFALSE");
+ }
+ else if(strncmp(messages, "offidle", 7) == 0)
+ {
+ galDevice->powerOffWhenIdle = galDevice->powerOffWhenIdle? gcvFALSE : gcvTRUE;
+ gcmkPRINT("==>Change powerOffWhenIdle to %s\n", galDevice->powerOffWhenIdle ? "gcvTRUE" : "gcvFALSE");
+ }
+ else if(strncmp(messages, "su", 2) == 0)
+ {
+ /* gckOS_PowerOff(galDevice->os); */
+ }
+ else if(strncmp(messages, "re", 2) == 0)
+ {
+ /* gckOS_PowerOn(galDevice->os); */
+ }
+ else if(strncmp(messages, "stress", 6) == 0)
+ {
+ int i;
+ static int count = 0;
+
+ sscanf(messages+6,"%d", &count);
+ /* struct vmalloc_info vmi; */
+
+ /* {get_vmalloc_info(&vmi);gcmkPRINT("%s,%d,VmallocUsed: %8lu kB\n",__func__,__LINE__,vmi.used >> 10); } */
+
+#ifdef _DEBUG
+ gckOS_SetDebugLevel(gcvLEVEL_VERBOSE);
+ gckOS_SetDebugZone(1023);
+#endif
+
+ for(i=0;i<count;i++)
+ {
+ static int count = 0;
+
+ gcmkPRINT("count:%d\n",count++);
+ gcmkPRINT("!!!\t");
+ /* gckOS_PowerOff(galDevice->os); */
+ gcmkPRINT("@@@\t");
+ /* gckOS_PowerOn(galDevice->os); */
+ gcmkPRINT("###\n");
+ }
+
+ }
+ else if(strncmp(messages, "debug", 5) == 0)
+ {
+#ifdef _DEBUG
+ static int count = 0;
+ gctINT debugLevel = gcvLEVEL_NONE;
+ gctINT debugZone = 0;
+
+ sscanf(messages+5,"%d %d", &debugLevel,&debugZone);
+
+
+ /*
+ #define gcvLEVEL_NONE -1
+ #define gcvLEVEL_ERROR 0
+ #define gcvLEVEL_WARNING 1
+ #define gcvLEVEL_INFO 2
+ #define gcvLEVEL_VERBOSE 3
+ */
+
+ /*
+ #define gcvZONE_OS (1 << 0)
+ #define gcvZONE_HARDWARE (1 << 1)
+ #define gcvZONE_HEAP (1 << 2)
+
+ #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)
+ */
+
+ count++;
+ gckOS_SetDebugLevel(debugLevel);
+ gckOS_SetDebugZone(debugZone);
+ gcmkPRINT("==>Change Debuglevel to %s, DebugZone to %d, Count:%d\n",
+ (debugLevel == gcvLEVEL_VERBOSE) ? "gcvLEVEL_VERBOSE" : "gcvLEVEL_NONE",
+ debugZone,
+ count);
+#endif
+ }
+ else if(strncmp(messages, "16", 2) == 0)
+ {
+ gcmkPRINT("frequency change to 1/16\n");
+ /* frequency change to 1/16 */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x210));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x010));
+
+ }
+ else if(strncmp(messages, "32", 2) == 0)
+ {
+ gcmkPRINT("frequency change to 1/32\n");
+ /* frequency change to 1/32*/
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x208));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x008));
+
+ }
+ else if(strncmp(messages, "64", 2) == 0)
+ {
+ gcmkPRINT("frequency change to 1/64\n");
+ /* frequency change to 1/64 */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x204));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x004));
+
+ }
+ else if('1' == messages[0])
+ {
+ gcmkPRINT("frequency change to full speed\n");
+ /* frequency change to full speed */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x300));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x100));
+
+ }
+ else if('2' == messages[0])
+ {
+ gcmkPRINT("frequency change to 1/2\n");
+ /* frequency change to 1/2 */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x280));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x080));
+
+ }
+ else if('4' == messages[0])
+ {
+ gcmkPRINT("frequency change to 1/4\n");
+ /* frequency change to 1/4 */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x240));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x040));
+
+ }
+ else if('8' == messages[0])
+ {
+ gcmkPRINT("frequency change to 1/8\n");
+ /* frequency change to 1/8 */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x220));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(galDevice->os,0x00000,0x020));
+
+ }
+ else
+ {
+ gcmkPRINT("unknown echo\n");
+ }
+
+ return len;
+}
+
+static struct file_operations gc_proc_ops = {
+ .read = gc_proc_read,
+ .write = gc_proc_write,
+};
+
+static void create_gc_proc_file(void)
+{
+ gc_proc_file = create_proc_entry(GC_PROC_FILE, 0644, gcvNULL);
+ if (gc_proc_file) {
+ gc_proc_file->proc_fops = &gc_proc_ops;
+ } else
+ gcmkPRINT("[galcore] proc file create failed!\n");
+}
+
+static void remove_gc_proc_file(void)
+{
+ remove_proc_entry(GC_PROC_FILE, gcvNULL);
+}
+
+#endif
+
+/******************************************************************************\
+* Driver operations definition
+\******************************************************************************/
+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);
+
+struct file_operations driver_fops =
+{
+ .open = drv_open,
+ .release = drv_release,
+ .unlocked_ioctl = drv_ioctl,
+ .mmap = drv_mmap,
+};
+
+int drv_open(struct inode *inode, struct file* filp)
+{
+ gcsHAL_PRIVATE_DATA_PTR private;
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "Entering drv_open\n");
+
+ private = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL);
+
+ if (private == gcvNULL)
+ {
+ return -ENOTTY;
+ }
+
+ private->device = galDevice;
+ private->mappedMemory = gcvNULL;
+ private->contiguousLogical = gcvNULL;
+
+#if gcdkUSE_MEMORY_RECORD
+ private->memoryRecordList.prev = &private->memoryRecordList;
+ private->memoryRecordList.next = &private->memoryRecordList;
+#endif
+
+ /* A process gets attached. */
+ gcmkVERIFY_OK(
+ gckKERNEL_AttachProcess(galDevice->kernel, gcvTRUE));
+
+ if (!galDevice->contiguousMapped)
+ {
+ gcmkVERIFY_OK(gckOS_MapMemory(galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ &private->contiguousLogical));
+ }
+
+ filp->private_data = private;
+
+ return 0;
+}
+
+int drv_release(struct inode* inode, struct file* filp)
+{
+ gcsHAL_PRIVATE_DATA_PTR private;
+ gckGALDEVICE device;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Entering drv_close\n");
+
+ private = filp->private_data;
+ gcmkASSERT(private != gcvNULL);
+
+ device = private->device;
+
+#if gcdkUSE_MEMORY_RECORD
+ gcmkVERIFY_OK(gckCOMMAND_Stall(device->kernel->command));
+
+ FreeAllMemoryRecord(galDevice->os, &private->memoryRecordList);
+
+ gcmkVERIFY_OK(gckCOMMAND_Stall(device->kernel->command));
+#endif
+
+ if (private->contiguousLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapMemory(galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ private->contiguousLogical));
+ }
+
+ /* Free some uncleared resource when unnormal exit */
+ gckOS_FreeProcessResource(galDevice->os, current->tgid);
+
+ /* Print GC memory usage after every process exits. */
+ gcmkPRINT("PID=%d , name=%s exits\n", current->tgid, current->comm);
+ gcmkPRINT("GC memory usage profile:\n");
+ gcmkPRINT("Total reserved video memory: %ld KB\n", galDevice->reservedMem/1024);
+ gcmkPRINT("Used video mem: %d KB\tcontiguous: %d KB\tvirtual: %d KB\n", galDevice->vidMemUsage/1024,
+ galDevice->contiguousMemUsage/1024, galDevice->virtualMemUsage/1024);
+
+ /* A process gets detached. */
+ gcmkVERIFY_OK(
+ gckKERNEL_AttachProcess(galDevice->kernel, gcvFALSE));
+
+ kfree(private);
+ filp->private_data = gcvNULL;
+
+ return 0;
+}
+
+long drv_ioctl(struct file *filp,
+ unsigned int ioctlCode,
+ unsigned long arg)
+{
+ gcsHAL_INTERFACE iface;
+ gctUINT32 copyLen;
+ DRIVER_ARGS drvArgs;
+ gckGALDEVICE device;
+ gceSTATUS status;
+ gcsHAL_PRIVATE_DATA_PTR private;
+
+ private = filp->private_data;
+
+ if (private == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("private data is null");
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] drv_ioctl: private_data is gcvNULL\n");
+
+ return -ENOTTY;
+ }
+
+ device = private->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] drv_ioctl: device is gcvNULL\n");
+
+ return -ENOTTY;
+ }
+
+ if (ioctlCode != IOCTL_GCHAL_INTERFACE
+ && ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
+ {
+ /* Unknown command. Fail the I/O. */
+ return -ENOTTY;
+ }
+
+ /* Get the drvArgs to begin with. */
+ copyLen = copy_from_user(&drvArgs,
+ (void *) arg,
+ sizeof(DRIVER_ARGS));
+
+ if (copyLen != 0)
+ {
+ /* The input buffer is not big enough. So fail the I/O. */
+ return -ENOTTY;
+ }
+
+ /* Now bring in the gcsHAL_INTERFACE structure. */
+ if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
+ || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
+ )
+ {
+ gcmkPRINT("\n [galcore] data structure size in kernel and user do not match !\n");
+ return -ENOTTY;
+ }
+
+ copyLen = copy_from_user(&iface,
+ drvArgs.InputBuffer,
+ sizeof(gcsHAL_INTERFACE));
+
+ if (copyLen != 0)
+ {
+ /* The input buffer is not big enough. So fail the I/O. */
+ return -ENOTTY;
+ }
+ if(galDevice->printPID)
+ {
+ gcmkPRINT("--->pid=%d\tname=%s\tiface.command=%d.\n", current->pid, current->comm, iface.command);
+ }
+#if gcdkUSE_MEMORY_RECORD
+ if (iface.command == gcvHAL_EVENT_COMMIT)
+ {
+ MEMORY_RECORD_PTR mr;
+ gcsQUEUE_PTR queue = iface.u.Event.queue;
+
+ while (queue != gcvNULL)
+ {
+ gcsQUEUE_PTR record, next;
+
+ /* Map record into kernel memory. */
+ gcmkERR_BREAK(gckOS_MapUserPointer(device->os,
+ queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) &record));
+
+ switch (record->iface.command)
+ {
+ case gcvHAL_FREE_VIDEO_MEMORY:
+ mr = FindMemoryRecord(device->os,
+ &private->memoryRecordList,
+ record->iface.u.FreeVideoMemory.node);
+
+ if (mr != gcvNULL)
+ {
+ DestoryMemoryRecord(device->os, mr);
+ }
+ else
+ {
+ gcmkPRINT("*ERROR* Invalid video memory (0x%p) for free\n",
+ record->iface.u.FreeVideoMemory.node);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Next record in the queue. */
+ next = record->next;
+
+ /* Unmap record from kernel memory. */
+ gcmkERR_BREAK(gckOS_UnmapUserPointer(device->os,
+ queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ queue = next;
+ }
+ }
+#endif
+
+ status = gckKERNEL_Dispatch(device->kernel,
+ (ioctlCode == IOCTL_GCHAL_INTERFACE) , &iface);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+ "[galcore] gckKERNEL_Dispatch returned %d.\n",
+ status);
+ }
+
+ else if (gcmIS_ERROR(iface.status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+ "[galcore] IOCTL %d returned %d.\n",
+ iface.command,
+ iface.status);
+ }
+
+ /* See if this was a LOCK_VIDEO_MEMORY command. */
+ else if (iface.command == gcvHAL_LOCK_VIDEO_MEMORY)
+ {
+ /* Special case for mapped memory. */
+ if (private->mappedMemory != gcvNULL
+ && iface.u.LockVideoMemory.node->VidMem.memory->object.type
+ == gcvOBJ_VIDMEM)
+ {
+ /* Compute offset into mapped memory. */
+ gctUINT32 offset = (gctUINT8 *) iface.u.LockVideoMemory.memory
+ - (gctUINT8 *) device->contiguousBase;
+
+ /* Compute offset into user-mapped region. */
+ iface.u.LockVideoMemory.memory =
+ (gctUINT8 *) private->mappedMemory + offset;
+ }
+ }
+#if gcdkUSE_MEMORY_RECORD
+ else if (iface.command == gcvHAL_ALLOCATE_VIDEO_MEMORY)
+ {
+ CreateMemoryRecord(device->os,
+ &private->memoryRecordList,
+ iface.u.AllocateVideoMemory.node);
+ }
+ else if (iface.command == gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY)
+ {
+ CreateMemoryRecord(device->os,
+ &private->memoryRecordList,
+ iface.u.AllocateLinearVideoMemory.node);
+ }
+ else if (iface.command == gcvHAL_FREE_VIDEO_MEMORY)
+ {
+ MEMORY_RECORD_PTR mr;
+
+ mr = FindMemoryRecord(device->os,
+ &private->memoryRecordList,
+ iface.u.FreeVideoMemory.node);
+
+ if (mr != gcvNULL)
+ {
+ DestoryMemoryRecord(device->os, mr);
+ }
+ else
+ {
+ gcmkPRINT("*ERROR* Invalid video memory for free\n");
+ }
+ }
+#endif
+
+ /* Copy data back to the user. */
+ copyLen = copy_to_user(drvArgs.OutputBuffer,
+ &iface,
+ sizeof(gcsHAL_INTERFACE));
+
+ if (copyLen != 0)
+ {
+ /* The output buffer is not big enough. So fail the I/O. */
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+static int drv_mmap(struct file * filp, struct vm_area_struct * vma)
+{
+ gcsHAL_PRIVATE_DATA_PTR private = filp->private_data;
+ gckGALDEVICE device;
+ int ret;
+ unsigned long size = vma->vm_end - vma->vm_start;
+
+ if (private == gcvNULL)
+ {
+ return -ENOTTY;
+ }
+
+ device = private->device;
+
+ if (device == gcvNULL)
+ {
+ return -ENOTTY;
+ }
+
+#ifdef CONFIG_MACH_CUBOX
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+#else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+ vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND;
+ vma->vm_pgoff = 0;
+
+ if (device->contiguousMapped)
+ {
+ ret = io_remap_pfn_range(vma,
+ vma->vm_start,
+ (gctUINT32) device->contiguousPhysical >> PAGE_SHIFT,
+ size,
+ vma->vm_page_prot);
+
+ private->mappedMemory = (ret == 0) ? (gctPOINTER) vma->vm_start : gcvNULL;
+
+ return ret;
+ }
+ else
+ {
+ return -ENOTTY;
+ }
+}
+
+/******************************************************************************\
+* Driver initialization - cleanup and power management functions
+\******************************************************************************/
+
+#if !USE_PLATFORM_DRIVER
+static int __init drv_init(void)
+#else
+static int drv_init(void)
+#endif
+{
+ int ret;
+ gckGALDEVICE device;
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "Entering drv_init\n");
+ printk("\n[galcore] GC Version: %s\n", _GC_VERSION_STRING_);
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ gckOS_ClockOn(gcvNULL, gcvTRUE, gcvTRUE, gpu_frequency);
+#endif
+
+ if (showArgs)
+ {
+ printk("galcore options:\n");
+ printk(" irqLine = %d\n", irqLine);
+ printk(" registerMemBase = 0x%08lX\n", registerMemBase);
+ printk(" contiguousSize = %ld\n", contiguousSize);
+ printk(" contiguousBase = 0x%08lX\n", contiguousBase);
+ printk(" bankSize = 0x%08lX\n", bankSize);
+ printk(" fastClear = %d\n", fastClear);
+ printk(" compression = %d\n", compression);
+ printk(" signal = %d\n", signal);
+ printk(" baseAddress = 0x%08lX\n", baseAddress);
+ }
+
+ /* Create the GAL device. */
+ gcmkVERIFY_OK(gckGALDEVICE_Construct(irqLine,
+ registerMemBase,
+ registerMemSize,
+ contiguousBase,
+ contiguousSize,
+ bankSize,
+ fastClear,
+ compression,
+ baseAddress,
+ signal,
+ &device));
+ gcmkPRINT("\n[galcore] chipModel=0x%x,chipRevision=0x%x,chipFeatures=0x%x,chipMinorFeatures=0x%x\n",
+ device->kernel->hardware->chipModel, device->kernel->hardware->chipRevision,
+ device->kernel->hardware->chipFeatures, device->kernel->hardware->chipMinorFeatures0);
+
+#if MRVL_CONFIG_ENABLE_DVFM
+ /* register galcore as a dvfm device*/
+ if(dvfm_register("Galcore", &device->dvfm_dev_index))
+ {
+ gcmkPRINT("\n[galcore] fail to do dvfm_register\n");
+ }
+#endif
+ gckOS_SetConstraint(device->os, gcvTRUE, gcvTRUE);
+
+ /* Start the GAL device. */
+ if (gcmIS_ERROR(gckGALDEVICE_Start(device)))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Can't start the gal device.\n");
+
+ /* Roll back. */
+ gckGALDEVICE_Stop(device);
+ gckGALDEVICE_Destroy(device);
+
+ return -1;
+ }
+
+ /* Register the character device. */
+ ret = register_chrdev(major, DRV_NAME, &driver_fops);
+ if (ret < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Could not allocate major number for mmap.\n");
+
+ /* Roll back. */
+ gckGALDEVICE_Stop(device);
+ gckGALDEVICE_Destroy(device);
+
+ return -1;
+ }
+ else
+ {
+ if (major == 0)
+ {
+ major = ret;
+ }
+ }
+
+ galDevice = device;
+
+ gpuClass = class_create(THIS_MODULE, "v_graphics_class");
+ if (IS_ERR(gpuClass)) {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "Failed to create the class.\n");
+ return -1;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ device_create(gpuClass, gcvNULL, MKDEV(major, 0), gcvNULL, "galcore");
+#else
+ device_create(gpuClass, gcvNULL, MKDEV(major, 0), "galcore");
+#endif
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] irqLine->%ld, contiguousSize->%lu, memBase->0x%lX\n",
+ irqLine,
+ contiguousSize,
+ registerMemBase);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "[galcore] driver registered successfully.\n");
+
+ BSP_IDLE_PROFILE_INIT;
+ return 0;
+}
+
+#if !USE_PLATFORM_DRIVER
+static void __exit drv_exit(void)
+#else
+static void drv_exit(void)
+#endif
+{
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "[galcore] Entering drv_exit\n");
+
+ device_destroy(gpuClass, MKDEV(major, 0));
+ class_destroy(gpuClass);
+
+ unregister_chrdev(major, DRV_NAME);
+
+ gckGALDEVICE_Stop(galDevice);
+
+ gckOS_UnSetConstraint(galDevice->os, gcvTRUE, gcvTRUE);
+
+#if MRVL_CONFIG_ENABLE_DVFM
+ if(dvfm_unregister("Galcore", &galDevice->dvfm_dev_index))
+ {
+ gcmkPRINT("\n[galcore] fail to do dvfm_unregister\n");
+ }
+#endif
+
+ gckGALDEVICE_Destroy(galDevice);
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ gckOS_ClockOff(gcvNULL, gcvTRUE, gcvTRUE);
+#endif
+}
+
+#if !USE_PLATFORM_DRIVER
+module_init(drv_init);
+module_exit(drv_exit);
+#else /* USE_PLATFORM_DRIVER -- start */
+
+#define DEVICE_NAME "galcore"
+
+#if MRVL_CONFIG_ENABLE_EARLYSUSPEND
+static void gpu_early_suspend(struct early_suspend *h)
+{
+ gcmkPRINT("\n");
+ gcmkPRINT("[galcore]: %s, %d\n",__func__, __LINE__);
+
+ if(galDevice->printPID)
+ {
+ }
+ else
+ {
+#if MRVL_PLATFORM_MMP2
+ if (!cpu_is_mmp2_z0() && !cpu_is_mmp2_z1())
+#endif
+ gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF);
+ BSP_IDLE_PROFILE_CALC_IDLE_TIME;
+ }
+
+ galDevice->currentPMode = gcvPM_EARLY_SUSPEND;
+
+ gcmkPRINT("[galcore]: %s, %d\n\n",__func__, __LINE__);
+ gcmkPRINT("\n");
+
+ return;
+}
+
+static void gpu_late_resume(struct early_suspend *h)
+{
+ gcmkPRINT("\n");
+ gcmkPRINT("[galcore]: %s, %d\n",__func__, __LINE__);
+
+ galDevice->currentPMode = gcvPM_NORMAL;
+
+ if(galDevice->printPID)
+ {
+ }
+ else
+ {
+ /* NO need to add the time during early-suspend to idle-time */
+ BSP_IDLE_PROFILE_INIT;
+ }
+
+ gcmkPRINT("[galcore]: %s, %d\n\n",__func__, __LINE__);
+ gcmkPRINT("\n");
+
+ return;
+}
+
+static struct early_suspend gpu_early_suspend_desc = {
+ .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING + 200, /* make sure GC early_suspend after surfaceflinger stop drawing */
+ .suspend = gpu_early_suspend,
+ .resume = gpu_late_resume,
+};
+#endif /* MRVL_CONFIG_ENABLE_EARLYSUSPEND -- end */
+
+static int __devinit gpu_probe(struct platform_device *pdev)
+{
+ int ret = -ENODEV;
+ struct resource *res;
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,"gpu_irq");
+ if (!res) {
+ gcmkPRINT(KERN_ERR "%s: No irq line supplied.\n",__FUNCTION__);
+ goto gpu_probe_fail;
+ }
+ irqLine = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gpu_base");
+ if (!res) {
+ gcmkPRINT(KERN_ERR "%s: No register base supplied.\n",__FUNCTION__);
+ goto gpu_probe_fail;
+ }
+ registerMemBase = res->start;
+ registerMemSize = res->end - res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gpu_mem");
+ if (!res) {
+ gcmkPRINT(KERN_ERR "%s: No memory base supplied.\n",__FUNCTION__);
+ goto gpu_probe_fail;
+ }
+ contiguousBase = res->start;
+ contiguousSize = res->end-res->start;
+
+ ret = drv_init();
+ if(!ret) {
+ platform_set_drvdata(pdev,galDevice);
+#ifdef MRVL_CONFIG_PROC
+ create_gc_proc_file();
+#endif
+
+#if MRVL_CONFIG_ENABLE_EARLYSUSPEND
+ register_early_suspend(&gpu_early_suspend_desc);
+#endif
+ return ret;
+ }
+
+gpu_probe_fail:
+ gcmkPRINT(KERN_INFO "Failed to register gpu driver.\n");
+ return ret;
+}
+
+static int __devinit gpu_remove(struct platform_device *pdev)
+{
+ drv_exit();
+
+#ifdef MRVL_CONFIG_PROC
+ remove_gc_proc_file();
+#endif
+
+#if MRVL_CONFIG_ENABLE_EARLYSUSPEND
+ unregister_early_suspend(&gpu_early_suspend_desc);
+#endif
+ return 0;
+}
+
+static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state)
+{
+ gceSTATUS status;
+ gctUINT32 countRetry = 0;
+
+ gcmkPRINT("\n");
+ gcmkPRINT("[galcore]: %s, %d\n",__func__, __LINE__);
+
+ while((status = gckHARDWARE_SetPowerManagementState(galDevice->kernel->hardware, gcvPOWER_OFF)) != gcvSTATUS_OK)
+ {
+ countRetry++;
+ if(countRetry > 3)
+ {
+ countRetry = 0;
+ gcmkPRINT("%s, GC is not correctly powered off, abort..\n",__func__);
+ break;
+ }
+ }
+
+ galDevice->currentPMode = gcvPM_SUSPEND;
+
+ gcmkPRINT("[galcore]: %s, %d\n",__func__, __LINE__);
+ gcmkPRINT("\n");
+
+ return 0;
+}
+
+static int __devinit gpu_resume(struct platform_device *dev)
+{
+ gcmkPRINT("\n");
+ gcmkPRINT("[galcore]: %s, %d",__func__, __LINE__);
+
+
+#if MRVL_CONFIG_ENABLE_EARLYSUSPEND
+ galDevice->currentPMode = gcvPM_EARLY_SUSPEND;
+#else
+ galDevice->currentPMode = gcvPM_NORMAL;
+#endif
+
+ gcmkPRINT("[galcore]: %s, %d\n",__func__, __LINE__);
+ gcmkPRINT("\n");
+
+ return 0;
+}
+
+static struct platform_driver gpu_driver = {
+ .probe = gpu_probe,
+ .remove = gpu_remove,
+
+ .suspend = gpu_suspend,
+ .resume = gpu_resume,
+
+ .driver = {
+ .name = DEVICE_NAME,
+ }
+};
+
+#ifndef CONFIG_DOVE_GPU
+static struct resource gpu_resources[] = {
+ {
+ .name = "gpu_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "gpu_base",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "gpu_mem",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device * gpu_device;
+#endif
+
+static int __init gpu_init(void)
+{
+ int ret = 0;
+
+#ifndef CONFIG_DOVE_GPU
+ gpu_resources[0].start = gpu_resources[0].end = irqLine;
+
+ gpu_resources[1].start = registerMemBase;
+ gpu_resources[1].end = registerMemBase + registerMemSize;
+
+ gpu_resources[2].start = contiguousBase;
+ gpu_resources[2].end = contiguousBase + contiguousSize;
+
+ /* Allocate device */
+ gpu_device = platform_device_alloc(DEVICE_NAME, -1);
+ if (!gpu_device)
+ {
+ gcmkPRINT(KERN_ERR "galcore: platform_device_alloc failed.\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Insert resource */
+ ret = platform_device_add_resources(gpu_device, gpu_resources, 3);
+ if (ret)
+ {
+ gcmkPRINT(KERN_ERR "galcore: platform_device_add_resources failed.\n");
+ goto put_dev;
+ }
+
+ /* Add device */
+ ret = platform_device_add(gpu_device);
+ if (ret)
+ {
+ gcmkPRINT(KERN_ERR "galcore: platform_device_add failed.\n");
+ goto del_dev;
+ }
+#endif
+
+ ret = platform_driver_register(&gpu_driver);
+ if (!ret)
+ {
+ goto out;
+ }
+
+#ifndef CONFIG_DOVE_GPU
+del_dev:
+ platform_device_del(gpu_device);
+put_dev:
+ platform_device_put(gpu_device);
+#endif
+
+out:
+ return ret;
+
+}
+
+static void __exit gpu_exit(void)
+{
+ platform_driver_unregister(&gpu_driver);
+#ifndef CONFIG_DOVE_GPU
+ platform_device_unregister(gpu_device);
+#endif
+}
+
+module_init(gpu_init);
+module_exit(gpu_exit);
+
+#endif /* USE_PLATFORM_DRIVER -- end */
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.c
new file mode 100644
index 0000000..41a300c
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.c
@@ -0,0 +1,418 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_QueryVideoMemory
+**
+** Query the amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
+** the memory information.
+*/
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=0x%p", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Get internal memory size and physical address. */
+ Interface->u.QueryVideoMemory.internalSize = device->internalSize;
+ Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysical;
+
+ /* Get external memory size and physical address. */
+ Interface->u.QueryVideoMemory.externalSize = device->externalSize;
+ Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysical;
+
+ /* Get contiguous memory size and physical address. */
+ Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
+ Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysical;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_GetVideoMemoryPool
+**
+** Get the gckVIDMEM object belonging to the specified pool.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcePOOL Pool
+** Pool to query gckVIDMEM object for.
+**
+** OUTPUT:
+**
+** gckVIDMEM * VideoMemory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object belonging to the requested pool.
+*/
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ )
+{
+ gckGALDEVICE device;
+ gckVIDMEM videoMemory;
+
+ gcmkHEADER_ARG("Kernel=0x%p Pool=%d", Kernel, Pool);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(VideoMemory != gcvNULL);
+
+ /* 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 = gcvNULL;
+ }
+
+ /* Return pointer to the gckVIDMEM object. */
+ *VideoMemory = videoMemory;
+
+ /* Return status. */
+ gcmkFOOTER_ARG("*VideoMemory=0x%p", *VideoMemory);
+ return (videoMemory == gcvNULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapMemory
+**
+** Map video memory into the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the base address of the mapped
+** memory region.
+*/
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ return gckOS_MapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_UnmapMemory
+**
+** Unmap video memory from the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** gctPOINTER Logical
+** Base address of the mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ return gckOS_UnmapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapVideoMemory
+**
+** Get the logical address for a hardware specific memory address for the
+** current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE to map the memory into the user space.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ gckGALDEVICE device;
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ gcePOOL pool;
+ gctUINT32 offset, base;
+ gceSTATUS status;
+ gctPOINTER logical;
+
+ gcmkHEADER_ARG("Kernel=0x%p InUserSpace=%d Address=%08x",
+ Kernel, InUserSpace, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Split the memory address into a pool type and offset. */
+ gcmkONERROR(
+ gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset));
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ if (device->contiguousMapped)
+ {
+ logical = device->contiguousBase;
+ }
+ else
+ {
+ mdl = (PLINUX_MDL) device->contiguousPhysical;
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+ gcmkASSERT(mdlMap);
+ if (mdlMap)
+ {
+ logical = (gctPOINTER) mdlMap->vmaAddr;
+ }
+ else
+ {
+ /* FindMdlMap Fail, Invalid mdlMap. */
+ gcmkONERROR(gcvSTATUS_NOT_FOUND);
+ }
+ }
+
+ gcmkONERROR(
+ gckHARDWARE_SplitMemory(Kernel->hardware,
+ device->contiguousVidMem->baseAddress,
+ &pool,
+ &base));
+
+ offset -= base;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Build logical address of specified address. */
+ *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=0x%p", *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Retunn the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Notify
+**
+** This function iscalled by clients to notify the gckKERNRL object of an event.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gceNOTIFY Notification
+** Notification event.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+ IN gceNOTIFY Notification,
+ IN gctBOOL Data
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=0x%p Notification=%d Data=%d",
+ Kernel, Notification, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Dispatch on notifcation. */
+ switch (Notification)
+ {
+ case gcvNOTIFY_INTERRUPT:
+ /* Process the interrupt. */
+#if COMMAND_PROCESSOR_VERSION > 1
+ status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
+#else
+ status = gckHARDWARE_Interrupt(Kernel->hardware, Data);
+#endif
+ break;
+
+ default:
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=0x%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/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.h
new file mode 100644
index 0000000..d4c80ca
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_linux.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_linux_h_
+#define __gc_hal_kernel_linux_h_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#ifdef FLAREON
+# include <asm/arch-realview/dove_gpio_irq.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+
+#ifdef MODVERSIONS
+# include <linux/modversions.h>
+#endif
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <linux/clk.h>
+
+#define NTSTRSAFE_NO_CCH_FUNCTIONS
+#include "gc_hal.h"
+
+#if MRVL_CONFIG_ENABLE_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_kernel_os.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
+#else
+#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
+#endif
+
+#define _WIDE(string) L##string
+#define WIDE(string) _WIDE(string)
+
+#define countof(a) (sizeof(a) / sizeof(a[0]))
+
+#define DRV_NAME "galcore"
+
+#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+
+static inline gctINT
+GetOrder(
+ IN gctINT numPages
+ )
+{
+ gctINT order = 0;
+
+ while ((1 << order) < numPages) order++;
+
+ return order;
+}
+
+#endif /* __gc_hal_kernel_linux_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.c b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.c
new file mode 100644
index 0000000..f7be762
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -0,0 +1,7383 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+
+#include <linux/random.h>
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+#include <stdarg.h>
+
+#ifdef NO_DMA_COHERENT
+#include <linux/dma-mapping.h>
+#endif /* NO_DMA_COHERENT */
+#include <linux/slab.h>
+#include <linux/delay.h>
+#if MRVL_CONFIG_ENABLE_DVFM
+#include <mach/dvfm.h>
+#include <mach/hardware.h>
+/* MG1 dot32 kernel: gc_pwr function defined in pxa3xx_pm.h */
+#if MRVL_CONFIG_DVFM_MG1 && (defined CONFIG_PXA3xx_DVFM)
+#include <mach/pxa3xx_dvfm.h>
+#endif
+#endif
+
+/* MG1/TD dot 35 kernel move gc_pwr define to mach/pxaXXX_pm.h */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+#if MRVL_PLATFORM_MG1
+#include <mach/pxa95x_pm.h>
+#endif
+#if MRVL_PLATFORM_TD
+#include <mach/pxa910_pm.h>
+#endif
+#endif
+
+#if !USE_NEW_LINUX_SIGNAL
+#define USER_SIGNAL_TABLE_LEN_INIT 64
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#define MEMORY_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryLock, \
+ gcvINFINITE))
+
+#define MEMORY_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
+
+#define MEMORY_MAP_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryMapLock, \
+ gcvINFINITE))
+
+#define MEMORY_MAP_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
+
+#define CLOCK_VERIFY(clock) \
+ if (IS_ERR(clock)) \
+ { \
+ int retval = PTR_ERR(clock); \
+ gcmkPRINT("clk get error: %d\t@LINE:%d\n", retval, __LINE__); \
+ return retval; \
+ }
+
+static void _Print(
+ const char *Message,
+ va_list Arguments
+ )
+{
+ char buffer[1000];
+ int n;
+
+ /* Print message to buffer. */
+ n = vsnprintf(buffer, sizeof(buffer), Message, Arguments);
+ if ((n <= 0) || (buffer[n - 1] != '\n'))
+ {
+ /* Append new-line. */
+ strncat(buffer, "\n", sizeof(buffer));
+ }
+
+ /* Output to debugger. */
+ printk(buffer);
+}
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#define _DEBUGPRINT(Message) \
+{ \
+ va_list arguments; \
+ \
+ va_start(arguments, Message); \
+ _Print(Message, arguments); \
+ va_end(arguments); \
+}
+
+
+#if MRVL_ENABLE_API_LOG
+static gctUINT32 g_logFilter = _GFX_LOG_ALL_;
+#else
+# if MRVL_ENABLE_ERROR_LOG
+ static gctUINT32 g_logFilter = _GFX_LOG_ERROR_ | _GFX_LOG_WARNING_ | _GFX_LOG_NOTIFY_;
+# else
+ static gctUINT32 g_logFilter = _GFX_LOG_NONE_;
+# endif
+#endif
+
+void gckOS_Log(IN unsigned int filter, IN const char* msg,
+ ...
+ )
+{
+ if(filter & g_logFilter)
+ {
+ _DEBUGPRINT(msg);
+ }
+}
+
+void gckOS_SetLogFilter(IN unsigned int filter)
+{
+ g_logFilter = filter;
+}
+
+/********************************** Structures **********************************
+\******************************************************************************/
+
+struct _gckOS
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Heap. */
+ gckHEAP heap;
+
+ /* Pointer to device */
+ gckGALDEVICE device;
+
+ /* Memory management */
+ gctPOINTER memoryLock;
+ gctPOINTER memoryMapLock;
+
+ struct _LINUX_MDL *mdlHead;
+ struct _LINUX_MDL *mdlTail;
+
+ gctUINT32 baseAddress;
+
+ /* Kernel process ID. */
+ gctUINT32 kernelProcessID;
+
+#if !USE_NEW_LINUX_SIGNAL
+ /* Signal management. */
+ struct _signal {
+ /* Unused signal ID number. */
+ gctINT unused;
+
+ /* The pointer to the table. */
+ gctPOINTER * table;
+
+ /* Signal table length. */
+ gctINT tableLen;
+
+ /* The current unused signal ID. */
+ gctINT currentID;
+
+ /* Lock. */
+ gctPOINTER lock;
+ } signal;
+#endif
+
+ /* idle profiling mutex. */
+ gctPOINTER mutexIdleProfile;
+};
+
+#if !USE_NEW_LINUX_SIGNAL
+typedef struct _gcsSIGNAL
+{
+ /* Kernel sync primitive. */
+ struct completion event;
+
+ /* Manual reset flag. */
+ gctBOOL manualReset;
+
+ /* The reference counter. */
+ atomic_t ref;
+
+ /* The signal type */
+ gceSIGNAL_TYPE signalType;
+
+ /* The owner of the signal. */
+ gctHANDLE process;
+}
+gcsSIGNAL;
+
+typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
+#endif
+
+typedef struct _gcsPageInfo * gcsPageInfo_PTR;
+
+typedef struct _gcsPageInfo
+{
+ struct page **pages;
+ gctUINT32_PTR pageTable;
+}
+gcsPageInfo;
+
+static PLINUX_MDL
+_CreateMdl(
+ IN gctINT PID
+ )
+{
+ PLINUX_MDL mdl;
+
+ mdl = (PLINUX_MDL)kmalloc(sizeof(struct _LINUX_MDL), GFP_ATOMIC);
+ if (mdl == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("out of memory to create Mdl");
+ return gcvNULL;
+ }
+
+ mdl->pid = PID;
+ mdl->maps = gcvNULL;
+ mdl->prev = gcvNULL;
+ mdl->next = gcvNULL;
+
+ mdl->addr = gcvNULL;
+
+#ifdef NO_DMA_COHERENT
+#if !ALLOC_HIGHMEM
+ mdl->kaddr = gcvNULL;
+#endif
+#endif
+
+ mdl->numPages = 0;
+ mdl->pagedMem = 0;
+ mdl->contiguous = gcvTRUE;
+ mdl->dmaHandle = GC_INVALID_PHYS_ADDR;
+
+ return mdl;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap
+ );
+
+static gceSTATUS
+_DestroyMdl(
+ IN PLINUX_MDL Mdl
+ )
+{
+ PLINUX_MDL_MAP mdlMap, next;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
+
+ mdlMap = Mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ next = mdlMap->next;
+
+ gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
+
+ mdlMap = next;
+ }
+
+ kfree(Mdl);
+ Mdl = gcvNULL;
+
+ return gcvSTATUS_OK;
+}
+
+static PLINUX_MDL_MAP
+_CreateMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_ATOMIC);
+ if (mdlMap == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("out of memory to create MdlMap");
+ return gcvNULL;
+ }
+
+ mdlMap->pid = PID;
+ mdlMap->vmaAddr = gcvNULL;
+ mdlMap->vma = gcvNULL;
+
+ mdlMap->next = Mdl->maps;
+ Mdl->maps = mdlMap;
+
+ return mdlMap;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap
+ )
+{
+ PLINUX_MDL_MAP prevMdlMap;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
+ gcmkASSERT(Mdl->maps != gcvNULL);
+
+ if (Mdl->maps == MdlMap)
+ {
+ Mdl->maps = MdlMap->next;
+ }
+ else
+ {
+ prevMdlMap = Mdl->maps;
+
+ while (prevMdlMap->next != MdlMap)
+ {
+ prevMdlMap = prevMdlMap->next;
+
+ gcmkASSERT(prevMdlMap != gcvNULL);
+ }
+
+ prevMdlMap->next = MdlMap->next;
+ }
+
+ kfree(MdlMap);
+
+ return gcvSTATUS_OK;
+}
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ mdlMap = Mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if (mdlMap->pid == PID) return mdlMap;
+
+ mdlMap = mdlMap->next;
+ }
+
+ return gcvNULL;
+}
+
+void
+FreeProcessMemoryOnExit(
+ IN gckOS Os,
+ IN gckKERNEL Kernel
+ )
+{
+ PLINUX_MDL mdl, nextMdl;
+ PLINUX_MDL_MAP mdlMap;
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl != Os->mdlTail)
+ {
+ nextMdl = mdl->next;
+ }
+ else
+ {
+ nextMdl = gcvNULL;
+ }
+
+ if (mdl->pagedMem)
+ {
+ mdlMap = mdl->maps;
+
+ if (mdlMap != gcvNULL
+ && mdlMap->pid == current->tgid
+ && mdlMap->next == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(Os, mdl, mdl->numPages * PAGE_SIZE));
+
+ MEMORY_LOCK(Os);
+
+ nextMdl = Os->mdlHead;
+ }
+ }
+
+ mdl = nextMdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+}
+
+void
+PrintInfoOnExit(
+ IN gckOS Os,
+ IN gckKERNEL Kernel
+ )
+{
+ PLINUX_MDL mdl, nextMdl;
+ PLINUX_MDL_MAP mdlMap;
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl != Os->mdlTail)
+ {
+ nextMdl = mdl->next;
+ }
+ else
+ {
+ nextMdl = gcvNULL;
+ }
+
+ gcmkPRINT("Unfreed mdl: %p, pid: %d -> pagedMem: %s, addr: %p, dmaHandle: 0x%x, pages: %d",
+ mdl,
+ mdl->pid,
+ mdl->pagedMem? "true" : "false",
+ mdl->addr,
+ mdl->dmaHandle,
+ mdl->numPages);
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ gcmkPRINT("\tmap: %p, pid: %d -> vmaAddr: %p, vma: %p",
+ mdlMap,
+ mdlMap->pid,
+ mdlMap->vmaAddr,
+ mdlMap->vma);
+
+ mdlMap = mdlMap->next;
+ }
+
+ mdl = nextMdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+}
+
+void
+OnProcessExit(
+ IN gckOS Os,
+ IN gckKERNEL Kernel
+ )
+{
+ /* PrintInfoOnExit(Os, Kernel); */
+
+#ifdef ANDROID
+ FreeProcessMemoryOnExit(Os, Kernel);
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_Construct
+**
+** Construct a new gckOS object.
+**
+** INPUT:
+**
+** gctPOINTER Context
+** Pointer to the gckGALDEVICE class.
+**
+** OUTPUT:
+**
+** gckOS * Os
+** Pointer to a variable that will hold the pointer to the gckOS object.
+*/
+gceSTATUS
+gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+ /* Allocate the gckOS object. */
+ os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_ATOMIC);
+
+ if (os == gcvNULL)
+ {
+ /* Out of memory. */
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Zero the memory. */
+ gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
+
+ /* Initialize the gckOS object. */
+ os->object.type = gcvOBJ_OS;
+
+ /* Set device device. */
+ os->device = Context;
+
+ /* IMPORTANT! No heap yet. */
+ os->heap = gcvNULL;
+
+ /* Initialize the memory lock. */
+ gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
+
+ gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
+
+ /* Create the gckHEAP object. */
+ gcmkONERROR(gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
+
+ os->mdlHead = os->mdlTail = gcvNULL;
+
+ /* Find the base address of the physical memory. */
+ os->baseAddress = os->device->baseAddress;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "Physical base address set to 0x%08X.",
+ os->baseAddress);
+
+ /* Get the kernel process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
+
+#if !USE_NEW_LINUX_SIGNAL
+ /*
+ * Initialize the signal manager.
+ * It creates the signals to be used in
+ * the user space.
+ */
+
+ /* Initialize mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &os->signal.lock));
+
+ /* Initialize the signal table. */
+ os->signal.table =
+ kmalloc(gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT, GFP_KERNEL);
+
+ if (os->signal.table == gcvNULL)
+ {
+ /* Out of memory. */
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+ gckOS_ZeroMemory(os->signal.table,
+ gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
+
+ /* Set the signal table length. */
+ os->signal.tableLen = USER_SIGNAL_TABLE_LEN_INIT;
+
+ /* The table is empty. */
+ os->signal.unused = os->signal.tableLen;
+
+ /* Initial signal ID. */
+ os->signal.currentID = 0;
+#endif
+
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &os->mutexIdleProfile));
+
+ /* Return pointer to the gckOS object. */
+ *Os = os;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ if (os->mutexIdleProfile != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->mutexIdleProfile));
+ }
+
+#if !USE_NEW_LINUX_SIGNAL
+ /* Roll back any allocation. */
+ if (os->signal.table != gcvNULL)
+ {
+ kfree(os->signal.table);
+ os->signal.table = gcvNULL;
+ }
+
+ if (os->signal.lock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->signal.lock));
+ os->signal.lock = gcvNULL;
+ }
+#endif
+
+ if (os->heap != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckHEAP_Destroy(os->heap));
+ os->heap = gcvNULL;
+ }
+
+ if (os->memoryMapLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryMapLock));
+ os->memoryMapLock = gcvNULL;
+ }
+
+ if (os->memoryLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryLock));
+ os->memoryLock = gcvNULL;
+ }
+
+ kfree(os);
+
+ os = gcvNULL;
+
+ /* Return the error. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Destroy
+**
+** Destroy an gckOS object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ )
+{
+ gckHEAP heap = gcvNULL;
+ gctINT i = 0;
+ gctPOINTER *table = Os->signal.table;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ if (Os->mutexIdleProfile != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->mutexIdleProfile));
+ Os->mutexIdleProfile = gcvNULL;
+ }
+
+#if !USE_NEW_LINUX_SIGNAL
+ /* Destroy the mutex. */
+ if(Os->signal.lock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->signal.lock));
+ Os->signal.lock = gcvNULL;
+ }
+
+ /* Free remain signal left in table */
+ for (i = 0; i < Os->signal.tableLen; i++)
+ {
+ if(table[i] != gcvNULL)
+ {
+ kfree(table[i]);
+ table[i] = gcvNULL;
+ }
+ }
+
+ /* Free the signal table. */
+ kfree(Os->signal.table);
+ Os->signal.table = gcvNULL;
+ Os->signal.tableLen = 0;
+#endif
+
+ if (Os->heap != gcvNULL)
+ {
+ /* Mark gckHEAP as gone. */
+ heap = Os->heap;
+ Os->heap = gcvNULL;
+
+ /* Destroy the gckHEAP object. */
+ gcmkVERIFY_OK(
+ gckHEAP_Destroy(heap));
+ }
+
+ /* Destroy the memory lock. */
+ if(Os->memoryMapLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->memoryMapLock));
+ Os->memoryMapLock = gcvNULL;
+ }
+
+ if(Os->memoryLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->memoryLock));
+ Os->memoryLock = gcvNULL;
+ }
+
+ gcmkPRINT("$$FLUSH$$");
+
+ /* Mark the gckOS object as unknown. */
+ Os->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckOS object. */
+ kfree(Os);
+ Os = gcvNULL;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/* the first numbers must success, because we need make sure surfaceFlinger start*/
+#define MUST_SUCCESS_THREASHOLD 30
+
+static unsigned int cntMalloc = 0;
+static unsigned int failMalloc = 0;
+
+gctBOOL gckOS_ForceMemAllocFail(gckOS Os)
+{
+ unsigned int value = 0;
+
+ if(Os->device->memRandomFailRate == 0)
+ return gcvFALSE;
+
+ get_random_bytes(&value, sizeof(unsigned int));
+
+ cntMalloc ++;
+
+ if((value & 32767) < (gctUINT32)(Os->device->memRandomFailRate*327) && cntMalloc > MUST_SUCCESS_THREASHOLD)
+ {
+ failMalloc++;
+ gcmkPRINT("@@@@@@@@@@@@@@ total mem Malloc count: %d, fail Malloc count %d", cntMalloc, failMalloc);
+ return gcvTRUE;
+ }
+ else
+ {
+ return gcvFALSE;
+ }
+}
+/*******************************************************************************
+**
+** gckOS_Allocate
+**
+** Allocate memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gceSTATUS status;
+
+ /* gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes); */
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Do we have a heap? */
+ if (Os->heap != gcvNULL)
+ {
+ /* Allocate from the heap. */
+ gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
+ }
+
+ /* Success. */
+ /* gcmkFOOTER_ARG("*memory=0x%x", *Memory); */
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Free
+**
+** Free allocated memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gceSTATUS status;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* gcmkHEADER_ARG("Os=0x%x Memory=0x%x", Os, memory); */
+
+ /* Do we have a heap? */
+ if (Os->heap != gcvNULL)
+ {
+ /* Free from the heap. */
+ gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_FreeMemory(Os, Memory));
+ }
+
+ /* Success. */
+ /* gcmkFOOTER_NO(); */
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateMemory
+**
+** Allocate memory wrapper.
+**
+** INPUT:
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctPOINTER memory;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ memory = (gctPOINTER) kmalloc(Bytes, GFP_ATOMIC);
+
+ if (memory == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Return pointer to the memory allocation. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%p", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+
+ *Memory = gcvNULL;
+ 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%p", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Free the memory from the OS pool. */
+ kfree(Memory);
+ Memory = gcvNULL;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapMemory
+**
+** Map physical memory into the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the logical address of the
+** mapped memory.
+*/
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ if(((unsigned int)mdl->addr) & (ALLOC_ALIGN_BYTES -1 ))
+ {
+ gcmkPRINT("gckOS_MapMemory: physical address is %x, cannot satisfy alignment request! \n", (unsigned int)Physical);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ unsigned long ret = 0;
+ down_write(&current->mm->mmap_sem);
+
+ ret = do_mmap_pgoff(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ if (IS_ERR_VALUE(ret))
+ {
+ gcmkLOG_WARNING_ARGS("do_mmap_pgoff failure!");
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: do_mmap error");
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapMemory] mdl->numPages: %d",
+ "[gckOS_MapMemory] mdl->vmaAddr: 0x%x",
+ mdl->numPages,
+ mdlMap->vmaAddr
+ );
+
+ up_write(&current->mm->mmap_sem);
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ else
+ {
+ mdlMap->vmaAddr = (char *)ret;
+ }
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ if (!mdlMap->vma)
+ {
+ gcmkLOG_WARNING_ARGS("can't find vma: 0x%08x", (unsigned long)mdlMap->vmaAddr);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: find_vma error.");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ up_write(&current->mm->mmap_sem);
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+#ifndef NO_DMA_COHERENT
+ if (dma_mmap_coherent(gcvNULL,
+ mdlMap->vma,
+ mdl->addr,
+ mdl->dmaHandle,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ gcmkLOG_WARNING_ARGS("dma_mmap_coherent failure");
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: dma_mmap_coherent error.");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#else
+ mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+ mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
+ mdlMap->vma->vm_pgoff = 0;
+
+ if (remap_pfn_range(mdlMap->vma,
+ mdlMap->vma->vm_start,
+ mdl->dmaHandle >> PAGE_SHIFT,
+ mdl->numPages*PAGE_SIZE,
+ mdlMap->vma->vm_page_prot) < 0)
+ {
+ gcmkLOG_WARNING_ARGS("remap_pfn_range failure");
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: remap_pfn_range error.");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#endif
+
+ up_write(&current->mm->mmap_sem);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ *Logical = mdlMap->vmaAddr;
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
+ "gckOS_MapMemory: User Mapped address for 0x%x is 0x%x pid->%d",
+ (gctUINT32)mdl->addr,
+ (gctUINT32)*Logical,
+ mdlMap->pid);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapMemory
+**
+** Unmap physical memory out of the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ struct task_struct * task;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_UnmapMemory");
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_UnmapMemory Will be unmapping 0x%x mdl->0x%x",
+ (gctUINT32)Logical,
+ (gctUINT32)mdl);
+
+ MEMORY_LOCK(Os);
+
+ if (Logical)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_UnmapMemory] Logical: 0x%x",
+ Logical
+ );
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Get the current pointer for the task with stored pid. */
+ task = FIND_TASK_BY_PID(mdlMap->pid);
+
+ if (task != gcvNULL && task->mm != gcvNULL)
+ {
+ down_write(&task->mm->mmap_sem);
+ if(do_munmap(task->mm,
+ (unsigned long)Logical,
+ mdl->numPages*PAGE_SIZE) < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "Can't unmap the address %x",
+ (unsigned long)Logical);
+ }
+
+ up_write(&task->mm->mmap_sem);
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "Can't find the task with pid->%d. No unmapping",
+ mdlMap->pid);
+ }
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateNonPagedMemory
+**
+** Allocate a number of pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that holds the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** allocation.
+*/
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctSIZE_T bytes;
+ gctINT numPages;
+ gctBOOL reservepage = gcvFALSE;
+ PLINUX_MDL mdl = gcvNULL;
+ PLINUX_MDL_MAP mdlMap = gcvNULL;
+ gctSTRING addr = gcvNULL;
+ gceSTATUS status = gcvSTATUS_OK;
+
+#ifdef NO_DMA_COHERENT
+ struct page * page = gcvNULL;
+ long size = PAGE_SIZE, order;
+ gctPOINTER vaddr = gcvNULL;
+#endif
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT((Bytes != gcvNULL) && (*Bytes > 0));
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_AllocateNonPagedMemory");
+ if(gckOS_ForceMemAllocFail(Os))
+ return gcvSTATUS_OUT_OF_MEMORY;
+
+ /* Align number of bytes to page size. */
+ bytes = gcmALIGN(*Bytes, PAGE_SIZE);
+
+ /* Get total number of pages.. */
+ numPages = GetPageCount(bytes, 0);
+
+ MEMORY_LOCK(Os);
+
+ /* Allocate mdl+vector structure */
+ mdl = _CreateMdl(current->tgid);
+
+ if (mdl == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ mdl->pagedMem = 0;
+ mdl->numPages = numPages;
+
+#ifndef NO_DMA_COHERENT
+ addr = dma_alloc_coherent(gcvNULL,
+ mdl->numPages * PAGE_SIZE,
+ &mdl->dmaHandle,
+ GFP_ATOMIC);
+#else
+ size = mdl->numPages * PAGE_SIZE;
+ order = get_order(size);
+
+#if ALLOC_HIGHMEM
+ page = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, order);
+#else
+ page = alloc_pages(GFP_KERNEL | GFP_DMA, order);
+#endif
+
+ if (page == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Out of memory to alloc pages!");
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ vaddr = (gctPOINTER)page_address(page);
+
+#if ALLOC_HIGHMEM
+ addr = ioremap_nocache(page_to_pfn(page) << PAGE_SHIFT, size);
+ mdl->dmaHandle = page_to_pfn(page) << PAGE_SHIFT;
+#else
+ addr = ioremap_nocache(virt_to_phys(vaddr), size);
+ mdl->dmaHandle = virt_to_phys(vaddr);
+
+ mdl->kaddr = vaddr;
+#endif
+
+#if ENABLE_ARM_L2_CACHE
+ if (vaddr)
+ {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
+ dma_sync_single_for_cpu(gcvNULL, virt_to_phys(vaddr), size, DMA_FROM_DEVICE);
+#else
+ dma_cache_maint(vaddr, size, DMA_FROM_DEVICE);
+#endif
+ }
+#endif
+
+ if(size > 0)
+ {
+ reservepage = gcvTRUE;
+ }
+
+ while (size > 0)
+ {
+#if ALLOC_HIGHMEM
+ SetPageReserved(page);
+ page ++;
+#else
+ SetPageReserved(virt_to_page(vaddr));
+ vaddr += PAGE_SIZE;
+#endif
+ size -= PAGE_SIZE;
+ }
+#endif
+
+ if (addr == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("ioremap_nocache failure of allocating memory -> 0x%08x", (gctUINT32)bytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "galcore: Can't allocate memorry for size->0x%x",
+ (gctUINT32)bytes);
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ if ((Os->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
+ {
+ mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
+ | (Os->baseAddress & 0x80000000);
+ }
+
+ mdl->addr = addr;
+
+ /*
+ * We will not do any mapping from here.
+ * Mapping will happen from mmap method.
+ * mdl structure will be used.
+ */
+
+ /* Return allocated memory. */
+ *Bytes = bytes;
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ if (InUserSpace)
+ {
+ unsigned long ret = 0;
+ mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Only after mmap this will be valid. */
+
+ /* We need to map this to user space. */
+ down_write(&current->mm->mmap_sem);
+
+ ret = do_mmap_pgoff(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ if (IS_ERR_VALUE(ret))
+ {
+ gcmkLOG_WARNING_ARGS("do_mmap_pgoff failure!");
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "galcore: do_mmap error");
+
+ up_write(&current->mm->mmap_sem);
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+ else
+ {
+ mdlMap->vmaAddr = (gctSTRING)ret;
+ }
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ if (mdlMap->vma == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("can't find vma: 0x%08x", (unsigned long)mdlMap->vmaAddr);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "find_vma error");
+
+ 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)
+ {
+ gcmkLOG_WARNING_ARGS("dma_mmap_coherent failure");
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "dma_mmap_coherent error");
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+#else
+ mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+ mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
+ mdlMap->vma->vm_pgoff = 0;
+
+ if (remap_pfn_range(mdlMap->vma,
+ mdlMap->vma->vm_start,
+ mdl->dmaHandle >> PAGE_SHIFT,
+ mdl->numPages * PAGE_SIZE,
+ mdlMap->vma->vm_page_prot))
+ {
+ gcmkLOG_WARNING_ARGS("remap_pfn_range failure");
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "remap_pfn_range error");
+
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+#endif /* NO_DMA_COHERENT */
+
+ up_write(&current->mm->mmap_sem);
+
+ *Logical = mdlMap->vmaAddr;
+ }
+ else
+ {
+ *Logical = (gctPOINTER)mdl->addr;
+ }
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+
+ if (!Os->mdlHead)
+ {
+ /* Initialize the queue. */
+ Os->mdlHead = Os->mdlTail = mdl;
+ }
+ else
+ {
+ /* Add to the tail. */
+ mdl->prev = Os->mdlTail;
+ Os->mdlTail->next = mdl;
+ Os->mdlTail = mdl;
+ }
+
+ /* Update contiguous or virtual memory usage. */
+ if (mdl)
+ {
+ if (mdl->contiguous)
+ Os->device->contiguousMemUsage += bytes;
+ else
+ Os->device->virtualMemUsage += bytes;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocateNonPagedMemory: "
+ "Bytes->0x%x, Mdl->%p, Logical->0x%x dmaHandle->0x%x",
+ (gctUINT32)bytes,
+ mdl,
+ (gctUINT32)mdl->addr,
+ mdl->dmaHandle);
+
+ if (InUserSpace)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "vmaAddr->0x%x pid->%d",
+ (gctUINT32)mdlMap->vmaAddr,
+ mdlMap->pid);
+ }
+
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+
+ if(mdl)
+ {
+#ifndef NO_DMA_COHERENT
+ dma_free_coherent(gcvNULL,
+ mdl->numPages * PAGE_SIZE,
+ mdl->addr,
+ mdl->dmaHandle);
+#else
+
+ /* Clear the page reserve flag */
+ if(reservepage)
+ {
+ size = mdl->numPages * PAGE_SIZE;
+ while (size > 0)
+ {
+#if ALLOC_HIGHMEM
+ ClearPageReserved(page);
+ page ++;
+#else
+ ClearPageReserved(virt_to_page(vaddr));
+ vaddr += PAGE_SIZE;
+#endif
+ size -= PAGE_SIZE;
+ }
+ }
+
+ /* free pages allocated */
+#if ALLOC_HIGHMEM
+ if(mdl->dmaHandle)
+ {
+ page = pfn_to_page(mdl->dmaHandle >> PAGE_SHIFT);
+
+ __free_pages(page, get_order(mdl->numPages * PAGE_SIZE));
+
+ mdl->dmaHandle = gcvNULL;
+ }
+#else
+ if(mdl->kaddr)
+ {
+ free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
+
+ mdl->kaddr = gcvNULL;
+ }
+#endif
+
+ /* unmap the kernal space */
+ if(mdl->addr)
+ {
+ iounmap(mdl->addr);
+ mdl->addr = gcvNULL;
+ }
+
+ /* unmap from user space */
+ if(InUserSpace && mdlMap && mdlMap->vmaAddr)
+ {
+ if (do_munmap(current->mm,
+ (unsigned long)mdlMap->vmaAddr,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreeNonPagedMemory: "
+ "Unmap Failed ->Mdl->0x%x Logical->0x%x vmaAddr->0x%x",
+ (gctUINT32)mdl,
+ (gctUINT32)mdl->addr,
+ (gctUINT32)mdlMap->vmaAddr);
+ }
+
+ mdlMap->vmaAddr = gcvNULL;
+ }
+#endif
+ }
+ /* Destroy the mdlMap if necessary*/
+ if(mdlMap)
+ {
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ mdlMap = gcvNULL;
+ }
+
+ /* Destroy the mdl if necessary*/
+ if(mdl)
+ {
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+ mdl = gcvNULL;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeNonPagedMemory
+**
+** Free previously allocated and mapped pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes allocated.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocated memory.
+**
+** gctPOINTER Logical
+** Logical address of the allocated memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ struct task_struct * task;
+
+#ifdef NO_DMA_COHERENT
+ unsigned size;
+#if ALLOC_HIGHMEM
+ struct page *page;
+#else
+ gctPOINTER vaddr;
+#endif
+#endif /* NO_DMA_COHERENT */
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_FreeNonPagedMemory");
+
+ /* Convert physical address into a pointer to a MDL. */
+ mdl = (PLINUX_MDL) Physical;
+
+ MEMORY_LOCK(Os);
+
+ if (mdl)
+ {
+#ifndef NO_DMA_COHERENT
+ dma_free_coherent(gcvNULL,
+ mdl->numPages * PAGE_SIZE,
+ mdl->addr,
+ mdl->dmaHandle);
+#else
+ size = mdl->numPages * PAGE_SIZE;
+
+#if ALLOC_HIGHMEM
+ page = pfn_to_page(mdl->dmaHandle >> PAGE_SHIFT);
+#else
+ vaddr = mdl->kaddr;
+
+#endif
+
+
+ while (size > 0)
+ {
+#if ALLOC_HIGHMEM
+ ClearPageReserved(page);
+ page ++;
+#else
+ ClearPageReserved(virt_to_page(vaddr));
+ vaddr += PAGE_SIZE;
+#endif
+ size -= PAGE_SIZE;
+ }
+
+#if ALLOC_HIGHMEM
+ if(mdl->dmaHandle)
+ {
+ page = pfn_to_page(mdl->dmaHandle >> PAGE_SHIFT);
+ __free_pages(page, get_order(mdl->numPages * PAGE_SIZE));
+ mdl->dmaHandle = gcvNULL;
+ }
+#else
+ if(mdl->kaddr)
+ {
+ free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
+ mdl->kaddr = gcvNULL;
+ }
+#endif
+
+ if(mdl->addr)
+ {
+ iounmap(mdl->addr);
+ mdl->addr = gcvNULL;
+ }
+
+#endif /* NO_DMA_COHERENT */
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if (mdlMap->vmaAddr != gcvNULL)
+ {
+ /* Get the current pointer for the task with stored pid. */
+ task = FIND_TASK_BY_PID(mdlMap->pid);
+
+ if (task != gcvNULL && task->mm != gcvNULL)
+ {
+ down_write(&task->mm->mmap_sem);
+
+ if (do_munmap(task->mm,
+ (unsigned long)mdlMap->vmaAddr,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreeNonPagedMemory: "
+ "Unmap Failed ->Mdl->0x%x Logical->0x%x vmaAddr->0x%x",
+ (gctUINT32)mdl,
+ (gctUINT32)mdl->addr,
+ (gctUINT32)mdlMap->vmaAddr);
+ }
+
+ up_write(&task->mm->mmap_sem);
+ }
+
+ mdlMap->vmaAddr = gcvNULL;
+ }
+
+ mdlMap = mdlMap->next;
+ }
+
+ /* Remove the node from global list.. */
+ if (mdl == Os->mdlHead)
+ {
+ if ((Os->mdlHead = mdl->next) == gcvNULL)
+ {
+ Os->mdlTail = gcvNULL;
+ }
+ }
+ else
+ {
+ mdl->prev->next = mdl->next;
+ if (mdl == Os->mdlTail)
+ {
+ Os->mdlTail = mdl->prev;
+ }
+ else
+ {
+ mdl->next->prev = mdl->prev;
+ }
+ }
+ }
+
+ /* Update contiguous or virtual memory usage. */
+ if (mdl)
+ {
+ if (mdl->contiguous)
+ Os->device->contiguousMemUsage -= (mdl->numPages * PAGE_SIZE);
+ else
+ Os->device->virtualMemUsage -= (mdl->numPages * PAGE_SIZE);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreeNonPagedMemory: "
+ "Mdl->0x%x Logical->0x%x",
+ (gctUINT32)mdl,
+ (gctUINT32)mdl->addr);
+
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ mdl = gcvNULL;
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReadRegister
+**
+** Read data from a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** OUTPUT:
+**
+** gctUINT32 * Data
+** Pointer to a variable that receives the data read from the register.
+*/
+gceSTATUS gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ if(Os->device->kernel
+ && Os->device->kernel->hardware)
+ {
+ gcmkVERIFY_OK(gckOS_AcquireRecMutex(Os, Os->device->kernel->hardware->recMutexPower, gcvINFINITE));
+
+ if(Os->device->clkEnabled)
+ {
+ *Data = readl((gctUINT8 *)Os->device->registerBase + Address);
+ }
+ else
+ {
+ *Data = 0x0;
+ gcmkPRINT("(pid=%d,name=%s)GC is clk off, dont read register(0x%08x)\n",
+ current->pid, current->comm, Address);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(Os, Os->device->kernel->hardware->recMutexPower));
+ }
+ else
+ {
+ *Data = readl((gctUINT8 *)Os->device->registerBase + Address);
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DirectReadRegister
+**
+** Read data from a register directly without mutex protection
+**
+** 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_DirectReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ *Data = readl((gctUINT8 *)Os->device->registerBase + Address);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteRegister
+**
+** Write data to a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ if(Os->device->kernel
+ && Os->device->kernel->hardware)
+ {
+ gcmkVERIFY_OK(gckOS_AcquireRecMutex(Os, Os->device->kernel->hardware->recMutexPower, gcvINFINITE));
+
+ if(Os->device->clkEnabled)
+ {
+ writel(Data, (gctUINT8 *)Os->device->registerBase + Address);
+ }
+ else
+ {
+ gcmkPRINT("(pid=%d,name=%s)GC is clk off, dont write register(0x%08x)\n",
+ current->pid, current->comm, Address);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseRecMutex(Os, Os->device->kernel->hardware->recMutexPower));
+ }
+ else
+ {
+ writel(Data, (gctUINT8 *)Os->device->registerBase + Address);
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPageSize
+**
+** Get the system's page size.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * PageSize
+** Pointer to a variable that will receive the system's page size.
+*/
+gceSTATUS gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
+
+ /* Return the page size. */
+ *PageSize = (gctSIZE_T) PAGE_SIZE;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddressProcess
+**
+** Get the physical system address of a corresponding virtual address for a
+** given process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** gctUINT ProcessID
+** Procedd ID.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+gckOS_GetPhysicalAddressProcess(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT ProcessID,
+ OUT gctUINT32 * Address
+ )
+{
+ return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddress
+**
+** Get the physical system address of a corresponding virtual address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ )
+{
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /*
+ * Try to search the address in our list.
+ * This could be an mmaped memory.
+ * Search in our list.
+ */
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ /* Check for the logical address match. */
+ if (mdl->addr
+ && (gctUINT32)Logical >= (gctUINT32)mdl->addr
+ && (gctUINT32)Logical < ((gctUINT32)mdl->addr + mdl->numPages*PAGE_SIZE))
+ {
+ if (mdl->dmaHandle != GC_INVALID_PHYS_ADDR)
+ {
+ /* The memory was from coherent area. */
+ *Address = (gctUINT32)mdl->dmaHandle
+ + (gctUINT32)((gctUINT32)Logical - (gctUINT32)mdl->addr);
+ }
+ else if (mdl->pagedMem)
+ {
+ if (mdl->contiguous)
+ {
+ *Address = (gctUINT32)virt_to_phys(mdl->addr)
+ + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
+ }
+ else
+ {
+ *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
+ + ((gctUINT32)Logical - (gctUINT32)mdl->addr)));
+ }
+ }
+ else
+ {
+ *Address = (gctUINT32)virt_to_phys(mdl->kaddr)
+ + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
+ }
+ break;
+ }
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ /* Is the given address within that range. */
+ if (mdlMap != gcvNULL
+ && mdlMap->vmaAddr != gcvNULL
+ && Logical >= mdlMap->vmaAddr
+ && Logical < (mdlMap->vmaAddr + mdl->numPages * PAGE_SIZE))
+ {
+ if (mdl->dmaHandle != GC_INVALID_PHYS_ADDR)
+ {
+ /* The memory was from coherent area. */
+ *Address = (gctUINT32)mdl->dmaHandle
+ + (gctUINT32)((gctUINT32)Logical
+ - (gctUINT32)mdlMap->vmaAddr);
+ }
+ else if (mdl->pagedMem)
+ {
+ if (mdl->contiguous)
+ {
+ *Address = (gctUINT32)virt_to_phys(mdl->addr)
+ + (gctUINT32)(Logical - mdlMap->vmaAddr);
+ }
+ else
+ {
+ *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
+ + ((gctUINT32)Logical - (gctUINT32)mdlMap->vmaAddr)));
+ }
+ }
+ else
+ {
+ /* Return the kernel virtual pointer based on this. */
+ *Address = (gctUINT32)virt_to_phys(mdl->kaddr)
+ + (gctUINT32)(Logical - mdlMap->vmaAddr);
+ }
+ break;
+ }
+
+ mdl = mdl->next;
+ }
+
+ /* Subtract base address to get a GPU physical address. */
+ gcmkASSERT(*Address >= Os->baseAddress);
+ *Address -= Os->baseAddress;
+
+ MEMORY_UNLOCK(Os);
+
+ if (mdl == gcvNULL)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPhysical
+**
+** Map a physical address into kernel space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Physical
+** Physical address of the memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the base address of the mapped
+** memory.
+*/
+gceSTATUS gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctUINT32 OriginalLogical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctPOINTER logical;
+ PLINUX_MDL mdl;
+ gctUINT32 physical;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ MEMORY_LOCK(Os);
+
+ /* Compute true physical address (before subtraction of the baseAddress). */
+ physical = Physical + Os->baseAddress;
+
+ /* Go through our mapping to see if we know this physical address already. */
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl->dmaHandle != GC_INVALID_PHYS_ADDR)
+ {
+ if ((physical >= mdl->dmaHandle)
+ && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
+ )
+ {
+ *Logical = mdl->addr + (physical - mdl->dmaHandle);
+ break;
+ }
+ }
+
+ mdl = mdl->next;
+ }
+
+ if (mdl == gcvNULL)
+ {
+ /* Map memory as cached memory. */
+ request_mem_region(physical, Bytes, "MapRegion");
+ logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
+
+ if (logical == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "gckOS_MapMemory: Failed to ioremap");
+
+ MEMORY_UNLOCK(Os);
+
+ /* Out of resources. */
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Return pointer to mapped memory. */
+ *Logical = logical;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "gckOS_MapPhysical: "
+ "Physical->0x%X Bytes->0x%X Logical->0x%X MappingFound->%d",
+ (gctUINT32) Physical,
+ (gctUINT32) Bytes,
+ (gctUINT32) *Logical,
+ mdl ? 1 : 0);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapPhysical
+**
+** Unmap a previously mapped memory region from kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Pointer to the base address of the memory to unmap.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl->addr != gcvNULL)
+ {
+ if (Logical >= (gctPOINTER)mdl->addr
+ && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
+ {
+ break;
+ }
+ }
+
+ mdl = mdl->next;
+ }
+
+ if (mdl == gcvNULL)
+ {
+ /* Unmap the memory. */
+ iounmap(Logical);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_UnmapPhysical: "
+ "Logical->0x%x Bytes->0x%x MappingFound(?)->%d",
+ (gctUINT32)Logical,
+ (gctUINT32)Bytes,
+ mdl ? 1 : 0);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateMutex
+**
+** Create a new mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Mutex
+** Pointer to a variable that will hold a pointer to the mutex.
+*/
+gceSTATUS gckOS_CreateMutex(
+ IN gckOS Os,
+ OUT gctPOINTER * Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Allocate a FAST_MUTEX structure. */
+ *Mutex = (gctPOINTER)kmalloc(sizeof(struct semaphore), GFP_KERNEL);
+
+ if (*Mutex == gcvNULL)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Initialize the semaphore.. Come up in unlocked state. */
+ sema_init(*Mutex,1);
+// init_MUTEX(*Mutex);
+
+ /* Return status. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DeleteMutex
+**
+** Delete a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mute to be deleted.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Delete the fast mutex. */
+ kfree(Mutex);
+
+ Mutex = gcvNULL;
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireMutex
+**
+** Acquire a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be acquired.
+**
+** gctUINT32 Timeout
+** Timeout value specified in milliseconds.
+** Specify the value of gcvINFINITE to keep the thread suspended
+** until the mutex has been acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ if (Timeout == gcvINFINITE)
+ {
+ down((struct semaphore *) Mutex);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ while (gcvTRUE)
+ {
+ /* Try to acquire the fast mutex. */
+ if (!down_trylock((struct semaphore *) Mutex))
+ {
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ if (Timeout-- == 0) break;
+
+ /* Wait for 1 millisecond. */
+ gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+ }
+
+ /* Timeout. */
+ return gcvSTATUS_TIMEOUT;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseMutex
+**
+** Release an acquired mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Release the fast mutex. */
+ up((struct semaphore *) Mutex);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UpdateVidMemUsage
+**
+** Update video memory usage.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN gctBOOL IsAllocated
+** Specifies whether this call is following allocate or free memory.
+**
+** IN gctSIZE_T Bytes
+** Specifies the bytes to allocate or free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UpdateVidMemUsage(
+ IN gckOS Os,
+ IN gctBOOL IsAllocated,
+ IN gctSIZE_T Bytes
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Update memory usage. */
+ if (IsAllocated)
+ Os->device->vidMemUsage += Bytes;
+ else
+ Os->device->vidMemUsage -= Bytes;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Allocate the atom. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
+
+ /* Initialize the atom. */
+ atomic_set((atomic_t *) *Atom, 0);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Atom=0x%x", *Atom);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Free the atom. */
+ gcmkONERROR(gckOS_Free(Os, Atom));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Return the current value of atom. */
+ *Value = atomic_read((atomic_t *) Atom);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Increment the atom. */
+ *Value = atomic_inc_return((atomic_t *) Atom) - 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Decrement the atom. */
+ *Value = atomic_dec_return((atomic_t *) Atom) + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateRecMutex
+**
+** Create a new recursive mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gckRecursiveMutex * Mutex
+** Pointer to a variable that will hold a pointer to the mutex.
+*/
+gceSTATUS
+gckOS_CreateRecMutex(
+ IN gckOS Os,
+ OUT gckRecursiveMutex *Mutex
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Allocate a _gckRecursiveMutex structure. */
+ *Mutex = kmalloc(sizeof(struct _gckRecursiveMutex), GFP_KERNEL);
+ if (*Mutex)
+ {
+ (*Mutex)->accMutex = (*Mutex)->undMutex = gcvNULL;
+ gcmkONERROR(gckOS_CreateMutex(Os, &(*Mutex)->accMutex));
+ gcmkONERROR(gckOS_CreateMutex(Os, &(*Mutex)->undMutex));
+ (*Mutex)->nReference = 0;
+ (*Mutex)->pThread = -1;
+ }
+ else
+ status = gcvSTATUS_OUT_OF_MEMORY;
+
+ /* Return status. */
+ return status;
+
+OnError:
+ if (*Mutex)
+ {
+ /* Free the underlying mutex. */
+ if ((*Mutex)->accMutex)
+ gckOS_DeleteMutex(Os, (*Mutex)->accMutex);
+ if ((*Mutex)->undMutex)
+ gckOS_DeleteMutex(Os, (*Mutex)->undMutex);
+ /* free _gckRecursiveMutex structure. */
+ kfree(*Mutex);
+ *Mutex = gcvNULL;
+ }
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DeleteRecMutex
+**
+** Delete a recursive mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gckRecursiveMutex Mutex
+** Pointer to the mute to be deleted.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_DeleteRecMutex(
+ IN gckOS Os,
+ IN gckRecursiveMutex Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ /* Delete the underlying mutex. */
+ if (Mutex->accMutex)
+ gckOS_DeleteMutex(Os, Mutex->accMutex);
+ if (Mutex->undMutex)
+ gckOS_DeleteMutex(Os, Mutex->undMutex);
+ /* Delete _gckRecursiveMutex structure. */
+ kfree(Mutex);
+ Mutex = gcvNULL;
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireRecMutex
+**
+** Acquire a recursive mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gckRecursiveMutex 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_AcquireRecMutex(
+ IN gckOS Os,
+ IN gckRecursiveMutex Mutex,
+ IN gctUINT32 Timeout
+ )
+{
+ gceSTATUS status = gcvSTATUS_TIMEOUT;
+ gctUINT32 tid;
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ gckOS_AcquireMutex(Os, Mutex->accMutex, gcvINFINITE);
+ /* Get current thread ID. */
+ gckOS_GetThreadID(&tid);
+ /* Locked by itself. */
+ if (Mutex->pThread == tid)
+ {
+ Mutex->nReference++;
+ gckOS_ReleaseMutex(Os, Mutex->accMutex);
+ status = gcvSTATUS_OK;
+ }
+ else
+ {
+ gckOS_ReleaseMutex(Os, Mutex->accMutex);
+ /* Try lock. */
+ status = gckOS_AcquireMutex(Os, Mutex->undMutex, Timeout);
+ /* First time get the lock . */
+ if (status == gcvSTATUS_OK)
+ {
+ gckOS_AcquireMutex(Os, Mutex->accMutex, gcvINFINITE);
+ Mutex->pThread = tid;
+ Mutex->nReference = 1;
+ gckOS_ReleaseMutex(Os, Mutex->accMutex);
+ }
+
+ }
+
+ /* Timeout. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseRecMutex
+**
+** Release an acquired mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gckRecursiveMutex Mutex
+** Pointer to the mutex to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_ReleaseRecMutex(
+ IN gckOS Os,
+ IN gckRecursiveMutex Mutex
+ )
+{
+ gctUINT32 tid;
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ gckOS_AcquireMutex(Os, Mutex->accMutex, gcvINFINITE);
+
+ /* Get current thread ID. */
+ gckOS_GetThreadID(&tid);
+ /* Locked by itself. */
+ if (Mutex->pThread == tid)
+ {
+ Mutex->nReference--;
+ if(Mutex->nReference == 0)
+ {
+ Mutex->pThread = -1;
+ /* Unlock. */
+ gckOS_ReleaseMutex(Os, Mutex->undMutex);
+ }
+ }
+
+ gckOS_ReleaseMutex(Os, Mutex->accMutex);
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchange
+**
+** Atomically exchange a pair of 32-bit values.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctINT32_PTR Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctINT32 NewValue
+** Specifies a new value for the 32-bit value pointed to by Target.
+**
+** OUT gctINT32_PTR OldValue
+** The old value of the 32-bit value pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Exchange the pair of 32-bit values. */
+ *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchangePtr
+**
+** Atomically exchange a pair of pointers.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctPOINTER * Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctPOINTER NewValue
+** Specifies a new value for the pointer pointed to by Target.
+**
+** OUT gctPOINTER * OldValue
+** The old value of the pointer pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Exchange the pair of pointers. */
+ *OldValue = (gctPOINTER) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_Delay
+**
+** Delay execution of the current thread for a number of milliseconds.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Delay
+** Delay to sleep, specified in milliseconds.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ )
+{
+ struct timeval now;
+ unsigned long ticks;
+
+ if (Delay == 0)
+ {
+ /* Smallest delay possible. */
+ ticks = 1;
+ }
+ else
+ {
+ /* Convert milliseconds into seconds and microseconds. */
+ now.tv_sec = Delay / 1000;
+ now.tv_usec = (Delay % 1000) * 1000;
+
+ /* Convert Delay to jiffies. */
+ ticks = timeval_to_jiffies(&now);
+ }
+
+ /* Schedule timeout. */
+ schedule_timeout_interruptible(ticks);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS gckOS_Udelay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ )
+{
+ udelay(Delay);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MemoryBarrier
+**
+** Make sure the CPU has executed everything up to this point and the data got
+** written to the specified pointer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of memory that needs to be barriered.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ )
+{
+ /* Verify thearguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ mb();
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemory
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ return gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical);
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemoryEx
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL Contiguous
+** Need contiguous memory or not.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ gctINT numPages;
+ gctINT i;
+ PLINUX_MDL mdl;
+ gctSTRING addr;
+ gctSIZE_T bytes;
+
+ gcmkHEADER_ARG("Os=0x%0x Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ if(gckOS_ForceMemAllocFail(Os))
+ return gcvSTATUS_OUT_OF_MEMORY;
+
+ MEMORY_LOCK(Os);
+
+ if (Contiguous)
+ {
+ bytes = gcmALIGN(Bytes, PAGE_SIZE);
+ numPages = GetPageCount(bytes, 0);
+
+ addr = (char *)__get_free_pages(GFP_ATOMIC | GFP_DMA, GetOrder(numPages));
+ }
+ else
+ {
+ Bytes = gcmALIGN(Bytes, ALLOC_ALIGN_BYTES);
+ bytes = gcmALIGN(Bytes, PAGE_SIZE);
+ numPages = GetPageCount(bytes, 0);
+ addr = vmalloc(bytes);
+ }
+
+ if (!addr)
+ {
+ gcmkLOG_WARNING_ARGS("Cant's allocate memory for size 0x%08x", (gctUINT32)bytes);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocatePagedMemoryEx: "
+ "Can't allocate memorry for size->0x%x",
+ (gctUINT32)bytes);
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdl = _CreateMdl(current->tgid);
+
+ if (mdl == gcvNULL)
+ {
+ if (Contiguous)
+ {
+ free_pages((unsigned int) addr, GetOrder(numPages));
+ }
+ else
+ {
+ vfree(addr);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdl->dmaHandle = GC_INVALID_PHYS_ADDR;
+ mdl->numPages = numPages;
+ mdl->pagedMem = 1;
+ mdl->contiguous = Contiguous;
+
+ if(Contiguous)
+ {
+ mdl->addr = addr;
+ }
+ else
+ {
+ /* consider 64 byte align, adjust the head address pointer */
+ unsigned int alignByte = ((unsigned int) addr + ALLOC_ALIGN_BYTES - 1) % ALLOC_ALIGN_BYTES;
+ mdl->addr_free = addr;
+ mdl->addr = addr + ALLOC_ALIGN_BYTES - 1 - alignByte;
+ }
+
+ for (i = 0; i < mdl->numPages; i++)
+ {
+ struct page *page;
+
+ if (mdl->contiguous)
+ {
+ page = virt_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
+ }
+ else
+ {
+ page = vmalloc_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
+ }
+
+ SetPageReserved(page);
+ flush_dcache_page(page);
+ }
+
+ /* Return physical address. */
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+ if (!Os->mdlHead)
+ {
+ /* Initialize the queue. */
+ Os->mdlHead = Os->mdlTail = mdl;
+ }
+ else
+ {
+ /* Add to tail. */
+ mdl->prev = Os->mdlTail;
+ Os->mdlTail->next = mdl;
+ Os->mdlTail = mdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "%s: Bytes=%lu Mdl=0x%08x Logical=0x%08x",
+ __FUNCTION__, bytes, mdl, mdl->addr);
+
+ /* Update contiguous or virtual memory usage. */
+ if (Contiguous)
+ Os->device->contiguousMemUsage += bytes;
+ else
+ Os->device->virtualMemUsage += bytes;
+ /* Success. */
+ gcmkHEADER_ARG("*Physical=0x%08x", *Physical);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreePagedMemory
+**
+** Free memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gctSTRING addr;
+ gctINT i;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_FreePagedMemory");
+
+ addr = mdl->addr;
+
+ MEMORY_LOCK(Os);
+
+ for (i = 0; i < mdl->numPages; i++)
+ {
+ if (mdl->contiguous)
+ {
+ ClearPageReserved(virt_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
+ }
+ else
+ {
+ ClearPageReserved(vmalloc_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
+ }
+ }
+
+ if (mdl->contiguous)
+ {
+ free_pages((unsigned long)mdl->addr, GetOrder(mdl->numPages));
+
+ mdl->addr = gcvNULL;
+ }
+ else
+ {
+ /* vfree need free the real head pointer */
+ vfree(mdl->addr_free);
+
+ mdl->addr_free = gcvNULL;
+ }
+
+ /* 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;
+ }
+ }
+
+ /* Update contiguous or virtual memory usage. */
+ if (mdl)
+ {
+ if (mdl->contiguous)
+ Os->device->contiguousMemUsage -= (mdl->numPages * PAGE_SIZE);
+ else
+ Os->device->virtualMemUsage -= (mdl->numPages * PAGE_SIZE);
+ }
+ MEMORY_UNLOCK(Os);
+
+ /* Free the structure... */
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ mdl = gcvNULL;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreePagedMemory: Bytes->0x%x, Mdl->0x%x",
+ (gctUINT32)Bytes,
+ (gctUINT32)mdl);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_LockPages
+**
+** Lock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the address of the mapped
+** memory.
+**
+** gctSIZE_T * PageCount
+** Pointer to a variable that receives the number of pages required for
+** the page table according to the GPU page size.
+*/
+gceSTATUS gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ gctSTRING addr;
+ unsigned long start;
+ unsigned long pfn;
+ gctINT i;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_LockPages");
+
+ mdl = (PLINUX_MDL) Physical;
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ unsigned long ret = 0;
+ down_write(&current->mm->mmap_sem);
+
+ ret = do_mmap_pgoff(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: "
+ "vmaAddr->0x%x for phys_addr->0x%x",
+ (gctUINT32)mdlMap->vmaAddr,
+ (gctUINT32)mdl);
+
+ if (IS_ERR_VALUE(ret))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: do_mmap error");
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ else
+ {
+ mdlMap->vmaAddr = (gctSTRING)ret;
+ }
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ if (mdlMap->vma == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "find_vma error");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ mdlMap->vma->vm_flags |= VM_RESERVED;
+ /* Make this mapping non-cached. */
+ mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+
+ addr = mdl->addr;
+
+ /* Now map all the vmalloc pages to this user address. */
+ down_write(&current->mm->mmap_sem);
+
+ if (mdl->contiguous)
+ {
+ /* map kernel memory to user space.. */
+ if (remap_pfn_range(mdlMap->vma,
+ mdlMap->vma->vm_start,
+ virt_to_phys((gctPOINTER)mdl->addr) >> PAGE_SHIFT,
+ mdlMap->vma->vm_end - mdlMap->vma->vm_start,
+ mdlMap->vma->vm_page_prot) < 0)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: unable to mmap ret");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+ else
+ {
+ start = mdlMap->vma->vm_start;
+
+ for (i = 0; i < mdl->numPages; i++)
+ {
+ pfn = vmalloc_to_pfn(addr);
+
+ if (remap_pfn_range(mdlMap->vma,
+ start,
+ pfn,
+ PAGE_SIZE,
+ mdlMap->vma->vm_page_prot) < 0)
+ {
+ up_write(&current->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: "
+ "gctPHYS_ADDR->0x%x Logical->0x%x Unable to map addr->0x%x to start->0x%x",
+ (gctUINT32)Physical,
+ (gctUINT32)*Logical,
+ (gctUINT32)addr,
+ (gctUINT32)start);
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ start += PAGE_SIZE;
+ addr += PAGE_SIZE;
+ }
+ }
+
+ up_write(&current->mm->mmap_sem);
+ }
+
+ /* Convert pointer to MDL. */
+ *Logical = mdlMap->vmaAddr;
+
+ /* Return the page number according to the GPU page size. */
+ gcmkASSERT((PAGE_SIZE % 4096) == 0);
+ gcmkASSERT((PAGE_SIZE / 4096) >= 1);
+
+ *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: "
+ "gctPHYS_ADDR->0x%x Bytes->0x%x Logical->0x%x pid->%d",
+ (gctUINT32)Physical,
+ (gctUINT32)Bytes,
+ (gctUINT32)*Logical,
+ mdlMap->pid);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPages
+**
+** Map paged memory into a page table.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T PageCount
+** Number of pages required for the physical address.
+**
+** gctPOINTER PageTable
+** Pointer to the page table to fill in.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ )
+{
+ PLINUX_MDL mdl;
+ gctUINT32* table;
+ gctSTRING addr;
+ gctINT i = 0;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_MapPages");
+
+ /* Convert pointer to MDL. */
+ mdl = (PLINUX_MDL)Physical;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_MapPages: "
+ "Physical->0x%x PageCount->0x%x PagedMemory->?%d",
+ (gctUINT32)Physical,
+ (gctUINT32)PageCount,
+ mdl->pagedMem);
+
+ MEMORY_LOCK(Os);
+
+ table = (gctUINT32 *)PageTable;
+
+ /* Get all the physical addresses and store them in the page table. */
+
+ addr = mdl->addr;
+
+ if (mdl->pagedMem)
+ {
+ /* Try to get the user pages so DMA can happen. */
+ while (PageCount-- > 0)
+ {
+ if (mdl->contiguous)
+ {
+ *table++ = virt_to_phys(addr);
+ }
+ else
+ {
+ *table++ = page_to_phys(vmalloc_to_page(addr));
+ }
+
+ addr += 4096;
+ i++;
+ }
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "We should not get this call for Non Paged Memory!");
+
+ while (PageCount-- > 0)
+ {
+ *table++ = (gctUINT32)virt_to_phys(addr);
+ addr += 4096;
+ }
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnlockPages
+**
+** Unlock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** gctPOINTER Logical
+** Address of the mapped memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ struct task_struct * task;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Make sure there is already a mapping...*/
+ gcmkVERIFY_ARGUMENT(mdl->addr != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_UnlockPages");
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if (mdlMap->vmaAddr != gcvNULL)
+ {
+ /* Get the current pointer for the task with stored pid. */
+ task = FIND_TASK_BY_PID(mdlMap->pid);
+
+ if (task != gcvNULL && task->mm != gcvNULL)
+ {
+ down_write(&task->mm->mmap_sem);
+ if( do_munmap(task->mm,
+ (unsigned long)Logical,
+ mdl->numPages*PAGE_SIZE) < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "Can't unmap the address %x",
+ (unsigned long)Logical);
+ }
+ up_write(&task->mm->mmap_sem);
+ }
+
+ mdlMap->vmaAddr = gcvNULL;
+ }
+
+ mdlMap = mdlMap->next;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_AllocateContiguous
+**
+** Allocate memory from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that receives the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the logical address of the
+** memory allocation.
+*/
+gceSTATUS gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ /* Same as non-paged memory for now. */
+ return gckOS_AllocateNonPagedMemory(Os,
+ InUserSpace,
+ Bytes,
+ Physical,
+ Logical
+ );
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeContiguous
+**
+** Free memory allocated from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctPOINTER Logical
+** Logicval address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ /* Same of non-paged memory for now. */
+ return gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical);
+}
+
+/******************************************************************************
+**
+** gckOS_GetKernelLogical
+**
+** Return the kernel logical pointer that corresponods to the specified
+** hardware address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Hardware physical address.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the pointer in kernel address space.
+*/
+gceSTATUS
+gckOS_GetKernelLogical(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gckGALDEVICE device;
+ gckKERNEL kernel;
+ gcePOOL pool;
+ gctUINT32 offset;
+ gctPOINTER logical;
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Os->device;
+
+ /* Kernel shortcut. */
+ kernel = device->kernel;
+
+ /* Split the memory address into a pool type and offset. */
+ gcmkERR_BREAK(gckHARDWARE_SplitMemory(
+ kernel->hardware, Address, &pool, &offset
+ ));
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ logical = device->contiguousBase;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Build logical address of specified address. */
+ * KernelPointer = ((gctUINT8_PTR) logical) + offset;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapUserPointer
+**
+** Map a pointer from the user process into the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be mapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be mapped.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the mapped pointer in kernel address
+** space.
+*/
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+#if NO_USER_DIRECT_ACCESS_FROM_KERNEL
+ gctPOINTER buf = gcvNULL;
+ gctUINT32 len;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+ buf = kmalloc(Size, GFP_KERNEL);
+ if (buf == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Failed to allocate memory at line %d in %s.",
+ __LINE__, __FILE__
+ );
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ len = copy_from_user(buf, Pointer, Size);
+ if (len != 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Failed to copy data from user at line %d in %s.",
+ __LINE__, __FILE__
+ );
+
+ if (buf != gcvNULL)
+ {
+ kfree(buf);
+ }
+
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ *KernelPointer = buf;
+#else
+ *KernelPointer = Pointer;
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserPointer
+**
+** Unmap a user process pointer from the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be unmapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be unmapped.
+**
+** gctPOINTER KernelPointer
+** Pointer in kernel address space that needs to be unmapped.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ )
+{
+#if NO_USER_DIRECT_ACCESS_FROM_KERNEL
+ gctUINT32 len;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+ len = copy_to_user(Pointer, KernelPointer, Size);
+
+ kfree(KernelPointer);
+
+ if (len != 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Failed to copy data to user at line %d in %s.",
+ __LINE__, __FILE__
+ );
+ return gcvSTATUS_GENERIC_IO;
+ }
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteMemory
+**
+** Write data to a memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of the memory to write to.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Write memory. */
+ writel(Data, (gctUINT8 *)Address);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateSignal
+**
+** Create a new signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctSIGNAL * Signal
+** Pointer to a variable receiving the created gctSIGNAL.
+*/
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ )
+{
+#if USE_NEW_LINUX_SIGNAL
+ return gcvSTATUS_NOT_SUPPORTED;
+#else
+ gcsSIGNAL_PTR signal;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Create an event structure. */
+ signal = (gcsSIGNAL_PTR)kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL);
+
+ if (signal == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Out of memory to create signal.");
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ signal->manualReset = ManualReset;
+
+ signal->signalType = gcvSIGNAL_NOPE;
+
+ init_completion(&signal->event);
+
+ atomic_set(&signal->ref, 1);
+
+ *Signal = (gctSIGNAL) signal;
+
+ return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySignal
+**
+** Destroy a signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+#if USE_NEW_LINUX_SIGNAL
+ return gcvSTATUS_NOT_SUPPORTED;
+#else
+ gcsSIGNAL_PTR signal;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcsSIGNAL_PTR) Signal;
+
+ if (atomic_dec_and_test(&signal->ref))
+ {
+ /* Free the sgianl. */
+ kfree(Signal);
+ Signal = gcvNULL;
+
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Failed to destroy signal, it was not unmampped \n"
+ );
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_Signal
+**
+** Set a state of the specified signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ )
+{
+#if USE_NEW_LINUX_SIGNAL
+ return gcvSTATUS_NOT_SUPPORTED;
+#else
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x State=%d", Os, Signal, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcsSIGNAL_PTR) Signal;
+
+ /* Set the new state of the event. */
+ if (signal->manualReset)
+ {
+ if (State)
+ {
+ /* Set the event to a signaled state. */
+ complete_all(&signal->event);
+ }
+ else
+ {
+ /* Set the event to an unsignaled state. */
+ INIT_COMPLETION(signal->event);
+ }
+ }
+ else
+ {
+ if (State)
+ {
+ /* Set the event to a signaled state. */
+ complete(&signal->event);
+
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#endif
+}
+
+#if USE_NEW_LINUX_SIGNAL
+/*******************************************************************************
+**
+** gckOS_UserSignal
+**
+** Set the specified signal which is owned by a process to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+ struct task_struct * task;
+ struct siginfo info;
+
+ task = FIND_TASK_BY_PID((pid_t) Process);
+
+ if (task != gcvNULL)
+ {
+ /* Fill in the siginfo structure. */
+ info.si_signo = Os->device->signal;
+ info.si_errno = 0;
+ info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
+ info.si_ptr = Signal;
+
+ /* Send the signal. */
+ if ((result = send_sig_info(Os->device->signal, &info, task)) < 0)
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "%s(%d): send_sig_info failed.",
+ __FUNCTION__, __LINE__);
+ }
+ else
+ {
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "%s(%d): find_task_by_pid failed.",
+ __FUNCTION__, __LINE__);
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignal
+**
+** Wait for a signal to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapSignal
+**
+** Map a signal in to the current process space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to tha gctSIGNAL to map.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** gctSIGNAL * MappedSignal
+** Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+gceSTATUS
+gckOS_UnMapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL MappedSignal
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+#else
+
+/*******************************************************************************
+**
+** gckOS_UserSignal
+**
+** Set the specified signal which is owned by a process to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctSIGNAL signal = gcvNULL;
+ gctBOOL sigMapped = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=%d Process=0x%x",
+ Os, (gctINT) Signal, Process);
+
+ /* Map the signal into kernel space. */
+ gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
+ sigMapped = gcvTRUE;
+
+ /* Signal. */
+ gcmkONERROR(gckOS_Signal(Os, signal, gcvTRUE));
+
+ /* UnMap the signal */
+ gcmkONERROR(gckOS_UnMapSignal(Os, signal));
+
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, sigMapped=%d", status, sigMapped);
+ if (sigMapped == gcvTRUE)
+ {
+ gcmkVERIFY_OK(gckOS_UnMapSignal(Os, signal));
+ }
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignal
+**
+** Wait for a signal to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctUINT timeout;
+ gctUINT rc;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x Wait=%u", Os, Signal, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcsSIGNAL_PTR) Signal;
+
+ /* Convert wait to milliseconds. */
+ timeout = (Wait == gcvINFINITE) ? MAX_SCHEDULE_TIMEOUT : Wait*HZ/1000;
+
+ /* Linux bug ? */
+ if (!signal->manualReset && timeout == 0) timeout = 1;
+
+ rc = wait_for_completion_interruptible_timeout(&signal->event, timeout);
+ status = ((rc == 0) && !signal->event.done) ? gcvSTATUS_TIMEOUT
+ : gcvSTATUS_OK;
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignalNoInterruptible
+**
+** 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_WaitSignalNoInterruptible(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctUINT timeout;
+ gctUINT rc;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x Wait=%u", Os, Signal, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcsSIGNAL_PTR) Signal;
+
+ /* Convert wait to milliseconds. */
+ timeout = (Wait == gcvINFINITE) ? MAX_SCHEDULE_TIMEOUT : Wait*HZ/1000;
+
+ /* Linux bug ? */
+ if (!signal->manualReset && timeout == 0) timeout = 1;
+
+ rc = wait_for_completion_timeout(&signal->event, timeout);
+ status = ((rc == 0) && !signal->event.done) ? gcvSTATUS_TIMEOUT
+ : gcvSTATUS_OK;
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapSignal
+**
+** Map a signal in to the current process space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to tha gctSIGNAL to map.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** gctSIGNAL * MappedSignal
+** Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ )
+{
+ gctINT signalID;
+ gcsSIGNAL_PTR signal;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x Process=0x%x", Os, Signal, Process);
+
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+ gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
+
+ signalID = (gctINT) Signal - 1;
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (signalID >= 0 && signalID < Os->signal.tableLen)
+ {
+ /* It is a user space signal. */
+ signal = Os->signal.table[signalID];
+
+ if (signal == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ }
+ else
+ {
+ /* It is a kernel space signal structure. */
+ signal = (gcsSIGNAL_PTR) Signal;
+ }
+
+ if (atomic_inc_return(&signal->ref) <= 1)
+ {
+ gcmkLOG_WARNING_ARGS("Signal has been deleted before.");
+ /* The previous value is 0, it has been deleted. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+ *MappedSignal = (gctSIGNAL) signal;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*MappedSignal=0x%x", *MappedSignal);
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+
+/*******************************************************************************
+**
+** gckOS_UnMapSignal
+**
+** UnMap a signal .
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to that gctSIGNAL mapped.
+*/
+gceSTATUS
+gckOS_UnMapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL MappedSignal
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctBOOL acquired = gcvFALSE;
+ gcsSIGNAL_PTR signal = (gcsSIGNAL_PTR)MappedSignal;
+
+ gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (atomic_dec_return(&signal->ref) < 1)
+ {
+ /* The previous value is less than 1, it hasn't been mapped. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateUserSignal
+**
+** Create a new signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctINT * SignalID
+** Pointer to a variable receiving the created signal's ID.
+*/
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ IN gceSIGNAL_TYPE SignalType,
+ OUT gctINT * SignalID
+ )
+{
+ gcsSIGNAL_PTR signal;
+ gctINT unused, currentID, tableLen;
+ gctPOINTER * table;
+ gctINT i;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%0x ManualReset=%d", Os, ManualReset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(SignalID != gcvNULL);
+
+ /* Lock the table. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ if (Os->signal.unused < 1)
+ {
+ /* Enlarge the table. */
+ table = (gctPOINTER *) kmalloc(
+ sizeof(gctPOINTER) * (Os->signal.tableLen + USER_SIGNAL_TABLE_LEN_INIT),
+ GFP_KERNEL);
+
+ if (table == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Oops, out of memory to create signal table!");
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ memset(table + Os->signal.tableLen, 0, sizeof(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
+ memcpy(table, Os->signal.table, sizeof(gctPOINTER) * Os->signal.tableLen);
+
+ /* Release the old table. */
+ kfree(Os->signal.table);
+
+ /* Update the table. */
+ Os->signal.table = table;
+ Os->signal.currentID = Os->signal.tableLen;
+ Os->signal.tableLen += USER_SIGNAL_TABLE_LEN_INIT;
+ Os->signal.unused += USER_SIGNAL_TABLE_LEN_INIT;
+ }
+
+ table = Os->signal.table;
+ currentID = Os->signal.currentID;
+ tableLen = Os->signal.tableLen;
+ unused = Os->signal.unused;
+
+ /* Create a new signal. */
+ gcmkONERROR(
+ gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
+
+ /* Save the process ID. */
+ signal->process = (gctHANDLE) current->tgid;
+
+ /* Save the signal type. */
+ signal->signalType = SignalType;
+
+ table[currentID] = signal;
+
+ /* Plus 1 to avoid gcvNULL claims. */
+ *SignalID = currentID + 1;
+
+ /* Update the currentID. */
+ if (--unused > 0)
+ {
+ for (i = 0; i < tableLen; i++)
+ {
+ if (++currentID >= tableLen)
+ {
+ /* Wrap to the begin. */
+ currentID = 0;
+ }
+
+ if (table[currentID] == gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ Os->signal.table = table;
+ Os->signal.currentID = currentID;
+ Os->signal.tableLen = tableLen;
+ Os->signal.unused = unused;
+
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+ gcmkFOOTER_ARG("*SignalID=%d", gcmOPT_VALUE(SignalID));
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroyUserSignal
+**
+** Destroy a signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** The signal's ID.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x SignalID=%d", Os, SignalID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkONERROR(
+ gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ if (SignalID < 1 || SignalID > Os->signal.tableLen)
+ {
+ gcmkLOG_WARNING_ARGS("invalid signalID {%d} to destroy", (gctINT) SignalID);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: invalid signal->%d.",
+ (gctINT) SignalID
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ SignalID -= 1;
+
+ signal = Os->signal.table[SignalID];
+
+ if (signal == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Error -> signal is gcvNULL");
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: signal is gcvNULL."
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Check to see if the process is the owner of the signal. */
+ if (signal->process != (gctHANDLE) current->tgid)
+ {
+ gcmkLOG_WARNING_ARGS("signal->process: %d NOT equal to current->tgid: %d",
+ signal->process, current->tgid);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: process id doesn't match. ",
+ "signal->process: %d, current->tgid: %d",
+ signal->process,
+ current->tgid);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ gcmkONERROR(
+ gckOS_DestroySignal(Os, signal));
+
+ /* Update the table. */
+ Os->signal.table[SignalID] = gcvNULL;
+ if (Os->signal.unused++ == 0)
+ {
+ Os->signal.currentID = SignalID;
+ }
+
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitUserSignal
+**
+** Wait for a signal used in the user mode to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** Signal ID.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+ gctUINT thread;
+ gctUINT count = 1;
+
+ gcmkHEADER_ARG("Os=0x%x SignalID=%d Wait=%u", Os, SignalID, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (SignalID < 1 || SignalID > Os->signal.tableLen)
+ {
+ gcmkLOG_WARNING_ARGS("invalid signalID {%d} to destroy", (gctINT) SignalID);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitSignal: invalid signal.",
+ SignalID
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ SignalID -= 1;
+
+ signal = Os->signal.table[SignalID];
+
+ gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+ acquired = gcvFALSE;
+
+ if (signal == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Signal is gcvNULL");
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitSignal: signal is gcvNULL."
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ gckOS_GetThreadID(&thread);
+
+ if (signal->process != (gctHANDLE) current->tgid)
+ {
+ gcmkLOG_WARNING_ARGS("signal->process: %d NOT equal to current->tgid: %d",
+ signal->process, current->tgid);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitUserSignal: process id doesn't match. "
+ "signal->process: %d, current->tgid: %d",
+ signal->process,
+ current->tgid);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ do {
+ #define MAX_WAIT_PERIOD_MSEC 10000
+ #define MAX_FORCE_RETURN_NPER 5
+
+ /* Split gcvINFINITE into slices, each slice is MAX_WAIT_PERIOD_MSEC millisecondes */
+ status = gckOS_WaitSignal(Os, signal, Wait == gcvINFINITE? MAX_WAIT_PERIOD_MSEC: Wait);
+
+ if (status == gcvSTATUS_TIMEOUT && Wait == gcvINFINITE)
+ {
+ gcmkPRINT("%s : %d\t<pid=%4d> [t=%d] SignalID: %4d, ProcessID: %4d, Type: %2x, index: %2d",
+ __FUNCTION__,
+ __LINE__,
+ thread,
+ count,
+ SignalID + 1,
+ signal->process,
+ signal->signalType & 0x0000FFFF,
+ (signal->signalType & 0xFFFF0000) >> gcmSIGNAL_OFFSET
+ );
+ }
+
+ /* Force waitUserSignal to return after MAX_FORCE_RETURN_NPER times trying. */
+ if (count++ >= MAX_FORCE_RETURN_NPER)
+ {
+ gcmkPRINT("%s : %d\t<pid=%d> Warning: force waitUserSignal to return.",
+ __FUNCTION__, __LINE__, thread);
+
+ status = gcvSTATUS_OK;
+ break;
+ }
+ }while(status == gcvSTATUS_TIMEOUT && Wait == gcvINFINITE);
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_SignalUserSignal
+**
+** Set a state of the specified signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** SignalID.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x SignalID=%d State=%d", Os, SignalID, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if ((SignalID < 1)
+ || (SignalID > Os->signal.tableLen)
+ )
+ {
+ gcmkLOG_WARNING_ARGS("invalid signalID {%d} to destroy", (gctINT) SignalID);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
+ "gckOS_WaitSignal: invalid signal->%d.", SignalID);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ SignalID -= 1;
+
+ signal = Os->signal.table[SignalID];
+
+ gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+ acquired = gcvFALSE;
+
+ if (signal == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("Error -> signal is gcvNULL");
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitSignal: signal is gcvNULL."
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+
+ if (signal->process != (gctHANDLE) current->tgid)
+ {
+ gcmkLOG_WARNING_ARGS("signal->process: %d NOT equal to current->tgid: %d",
+ signal->process, current->tgid);
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: process id doesn't match. ",
+ "signal->process: %d, current->tgid: %d",
+ signal->process,
+ current->tgid);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ status = gckOS_Signal(Os, signal, State);
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_CleanProcessSignal(
+ gckOS Os,
+ gctHANDLE Process
+ )
+{
+ gctINT signal;
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
+ Os->signal.lock,
+ gcvINFINITE
+ ));
+
+ if (Os->signal.unused == Os->signal.tableLen)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
+ Os->signal.lock
+ ));
+
+ return gcvSTATUS_OK;
+ }
+
+ for (signal = 0; signal < Os->signal.tableLen; signal++)
+ {
+ if (Os->signal.table[signal] != gcvNULL &&
+ ((gcsSIGNAL_PTR)Os->signal.table[signal])->process == Process)
+ {
+ gckOS_DestroySignal(Os, Os->signal.table[signal]);
+
+ /* Update the signal table. */
+ Os->signal.table[signal] = gcvNULL;
+ if (Os->signal.unused++ == 0)
+ {
+ Os->signal.currentID = signal;
+ }
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
+ Os->signal.lock
+ ));
+
+ return gcvSTATUS_OK;
+}
+
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/*******************************************************************************
+**
+** gckOS_MapUserMemory
+**
+** Lock down a user buffer and return an DMA'able address to be used by the
+** hardware to access it.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to lock down.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to lock down.
+**
+** OUTPUT:
+**
+** gctPOINTER * Info
+** Pointer to variable receiving the information record required by
+** gckOS_UnmapUserMemory.
+**
+** gctUINT32_PTR Address
+** Pointer to a variable that will receive the address DMA'able by the
+** hardware.
+*/
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T pageCount, i, j;
+ gctUINT32_PTR pageTable;
+ gctUINT32 address;
+ gctUINT32 start, end, memory;
+ gctINT result = 0;
+
+ gcsPageInfo_PTR info = gcvNULL;
+ struct page **pages = gcvNULL;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] enter."
+ );
+
+ /* If logic address cannot satisfy alignment, physical also cannot align */
+ if((unsigned int)Memory & (ALLOC_ALIGN_BYTES - 1))
+ {
+ gcmkPRINT("gckOS_MapUserMemory: address is %x, cannot satisfy alignment request! \n", (unsigned int)Memory);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ do
+ {
+ memory = (gctUINT32) Memory;
+
+ /* Get the number of required pages. */
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = memory >> PAGE_SHIFT;
+ pageCount = end - start;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] pageCount: %d.",
+ pageCount
+ );
+
+ /* Invalid argument. */
+ if (pageCount == 0)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Overflow. */
+ if ((memory + Size) < memory)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ MEMORY_MAP_LOCK(Os);
+
+ /* Allocate the Info struct. */
+ info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL);
+
+ if (info == gcvNULL)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ break;
+ }
+
+ /* Allocate the array of page addresses. */
+ pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL);
+
+ if (pages == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("out of memory to allocate page");
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ break;
+ }
+
+ /* Get the user pages. */
+ down_read(&current->mm->mmap_sem);
+ result = get_user_pages(current,
+ current->mm,
+ memory & PAGE_MASK,
+ pageCount,
+ 1,
+ 0,
+ pages,
+ gcvNULL
+ );
+ up_read(&current->mm->mmap_sem);
+
+ if (result <=0 || result < pageCount)
+ {
+ struct vm_area_struct *vma;
+
+ vma = find_vma(current->mm, memory);
+
+ if (vma && (vma->vm_flags & VM_PFNMAP) )
+ {
+ do
+ {
+ pte_t * pte;
+ spinlock_t * ptl;
+ unsigned long pfn;
+
+ pgd_t * pgd = pgd_offset(current->mm, memory);
+ pud_t * pud = pud_alloc(current->mm, pgd, memory);
+ if (pud)
+ {
+ pmd_t * pmd = pmd_alloc(current->mm, pud, memory);
+ if (pmd)
+ {
+ pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
+ if (!pte)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ pfn = pte_pfn(*pte);
+ *Address = ((pfn << PAGE_SHIFT) | (((unsigned long)Memory) & ~PAGE_MASK))
+ - Os->baseAddress;
+ *Info = gcvNULL;
+
+ pte_unmap_unlock(pte, ptl);
+
+ /* Release page info struct. */
+ if (info != gcvNULL)
+ {
+ /* Free the page info struct. */
+ kfree(info);
+ }
+
+ if (pages != gcvNULL)
+ {
+ /* Free the page table. */
+ kfree(pages);
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ *Address = ~0;
+ *Info = gcvNULL;
+
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+ else
+ {
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+ }
+
+ for (i = 0; i < pageCount; i++)
+ {
+ /* Flush the data cache. */
+#ifdef ANDROID
+ dma_map_page(gcvNULL, pages[i], 0, PAGE_SIZE, DMA_TO_DEVICE);
+#else
+ flush_dcache_page(pages[i]);
+#endif
+ }
+
+ /* Allocate pages inside the page table. */
+ gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernel->mmu,
+ pageCount * (PAGE_SIZE/4096),
+ (gctPOINTER *) &pageTable,
+ &address));
+
+ /* Fill the page table. */
+ for (i = 0; i < pageCount; i++)
+ {
+ /* Get the physical address from page struct. */
+ pageTable[i * (PAGE_SIZE/4096)] = page_to_phys(pages[i]);
+
+ for (j = 1; j < (PAGE_SIZE/4096); j++)
+ {
+ pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] pages[%d]: 0x%x, pageTable[%d]: 0x%x.",
+ i, pages[i],
+ i, pageTable[i]);
+ }
+
+ /* Save pointer to page table. */
+ info->pageTable = pageTable;
+ info->pages = pages;
+
+ *Info = (gctPOINTER) info;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] info->pages: 0x%x, info->pageTable: 0x%x, info: 0x%x.",
+ info->pages,
+ info->pageTable,
+ info
+ );
+
+ /* Return address. */
+ *Address = address + (memory & ~PAGE_MASK);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] Address: 0x%x.",
+ *Address
+ );
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkLOG_ERROR_STATUS();
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error occured: %d.",
+ status
+ );
+
+ *Address = 0;
+ *Info = gcvNULL;
+
+ /* Release page array. */
+ if (result > 0 && pages != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error: page table is freed."
+ );
+
+ for (i = 0; i < result; i++)
+ {
+ if (pages[i] == gcvNULL)
+ {
+ break;
+ }
+#ifdef ANDROID
+ dma_map_page(gcvNULL, pages[i], 0, PAGE_SIZE, DMA_TO_DEVICE);
+#endif
+ page_cache_release(pages[i]);
+ }
+ }
+
+ if (pages != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error: pages is freed."
+ );
+
+ /* Free the page table. */
+ kfree(pages);
+ info->pages = gcvNULL;
+ }
+
+ /* Release page info struct. */
+ if (info != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error: info is freed."
+ );
+
+ /* Free the page info struct. */
+ kfree(info);
+ }
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] leave."
+ );
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserMemory
+**
+** Unlock a user buffer and that was previously locked down by
+** gckOS_MapUserMemory.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to unlock.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to unlock.
+**
+** gctPOINTER Info
+** Information record returned by gckOS_MapUserMemory.
+**
+** gctUINT32_PTR Address
+** The address returned by gckOS_MapUserMemory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ )
+{
+ gceSTATUS status;
+ gctUINT32 memory, start, end;
+ gcsPageInfo_PTR info;
+ gctSIZE_T pageCount, i;
+ struct page **pages;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] enter."
+ );
+
+ do
+ {
+ info = (gcsPageInfo_PTR) Info;
+
+ if (info == gcvNULL)
+ {
+ return gcvSTATUS_OK;
+ }
+
+ pages = info->pages;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] info: 0x%x, pages: 0x%x.",
+ info,
+ pages
+ );
+
+ /* Invalid page array. */
+ if (pages == gcvNULL)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ memory = (gctUINT32) Memory;
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = memory >> PAGE_SHIFT;
+ pageCount = end - start;
+
+ /* Overflow. */
+ if ((memory + Size) < memory)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Invalid argument. */
+ if (pageCount == 0)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] memory: 0x%x, pageCount: %d, pageTable: 0x%x.",
+ memory,
+ pageCount,
+ info->pageTable
+ );
+
+ MEMORY_MAP_LOCK(Os);
+
+ /* Free the pages from the MMU. */
+ gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernel->mmu,
+ info->pageTable,
+ pageCount * (PAGE_SIZE/4096)
+ ));
+
+ /* Release the page cache. */
+ for (i = 0; i < pageCount; i++)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] pages[%d]: 0x%x.",
+ i,
+ pages[i]
+ );
+
+ if (!PageReserved(pages[i]))
+ {
+ SetPageDirty(pages[i]);
+ }
+
+#ifdef ANDROID
+ dma_map_page(gcvNULL, pages[i], 0, PAGE_SIZE, DMA_TO_DEVICE);
+#endif
+ page_cache_release(pages[i]);
+ }
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ if (info != gcvNULL)
+ {
+ /* Free the page array. */
+ if (info->pages != gcvNULL)
+ {
+ kfree(info->pages);
+ info->pages = gcvNULL;
+ }
+
+ kfree(info);
+
+ info = gcvNULL;
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetBaseAddress
+**
+** Get the base address for the physical memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR BaseAddress
+** Pointer to a variable that will receive the base address.
+*/
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Return base address. */
+ *BaseAddress = Os->baseAddress;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ disable_irq(Os->device->irqLine);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ enable_irq(Os->device->irqLine);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ClockOff(
+ IN gckOS Os,
+ IN gctBOOL disableClk,
+ IN gctBOOL disablePwr
+ )
+{
+
+#if SEPARATE_CLOCK_AND_POWER
+ if(disablePwr)
+ {
+ gc_pwr(0);
+ /* gcmkPRINT("[galcore]: pwr disable\n"); */
+ }
+#endif
+
+ if(disableClk)
+ {
+ static gctUINT count = 0;
+#if MRVL_CONFIG_AXICLK_CONTROL
+ static struct clk * clkAXI = gcvNULL;
+#endif
+ static struct clk * clkGC = gcvNULL;
+
+ if(count == 0)
+ {
+ clkGC = clk_get(gcvNULL, "GCCLK");
+ CLOCK_VERIFY(clkGC);
+ }
+ clk_disable(clkGC);
+
+ if(Os && Os->device)
+ {
+ Os->device->clkEnabled = gcvFALSE;
+ }
+
+#if MRVL_CONFIG_AXICLK_CONTROL
+ if(count == 0)
+ {
+ clkAXI = clk_get(gcvNULL, "AXICLK");
+ CLOCK_VERIFY(clkAXI);
+ }
+ /* decrease AXICLK count in kernel */
+ clk_disable(clkAXI);
+#endif
+ count++;
+ }
+
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ClockOn(
+ IN gckOS Os,
+ IN gctBOOL enableClk,
+ IN gctBOOL enablePwr,
+ IN gctUINT64 Frequency
+ )
+{
+ if(enableClk)
+ {
+ static gctUINT count = 0;
+#if MRVL_CONFIG_AXICLK_CONTROL
+ static struct clk * clkAXI = gcvNULL;
+#endif
+ static struct clk * clkGC = gcvNULL;
+
+#if MRVL_CONFIG_AXICLK_CONTROL
+ if(count == 0)
+ {
+ clkAXI = clk_get(gcvNULL, "AXICLK");
+ CLOCK_VERIFY(clkAXI);
+ }
+ /* increase AXICLK count in kernel */
+ clk_enable(clkAXI);
+#endif
+ if(count == 0)
+ {
+ clkGC = clk_get(gcvNULL, "GCCLK");
+ CLOCK_VERIFY(clkGC);
+ }
+ if(Frequency != 0)
+ {
+ /* APMU_GC_156M, APMU_GC_624M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently */
+ gcmkPRINT("\n[galcore] clk input = %dM Hz; running on %dM Hz\n",(int)Frequency, (int)Frequency/2);
+ if (clk_set_rate(clkGC, Frequency*1000*1000))
+ {
+ gcmkLOG_ERROR_ARGS("Set gpu core clock rate error.");
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Can't set core clock.");
+ return -EAGAIN;
+ }
+ }
+
+ clk_enable(clkGC);
+
+ if(Os && Os->device)
+ {
+ Os->device->clkEnabled = gcvTRUE;
+ }
+ /* gcmkPRINT("[galcore]: clk enable\n"); */
+ count++;
+ }
+
+#if SEPARATE_CLOCK_AND_POWER
+ if(enablePwr)
+ {
+ gc_pwr(1);
+ /* gcmkPRINT("[galcore]: pwr enable\n"); */
+ }
+#endif
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_PowerOff(
+ IN gckOS Os
+ )
+{
+ return gcvSTATUS_OK;
+}
+gceSTATUS
+gckOS_PowerOffWhenIdle(
+ IN gckOS Os,
+ IN gctBOOL needProfile
+ )
+{
+ gceSTATUS status;
+ static gctUINT32 countDelay = 0;
+ gckHARDWARE hardware = Os->device->kernel->hardware;
+ gctUINT32 idleTime, timeSlice, tailTimeSlice, tailIdleTime;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ timeSlice = Os->device->profileTimeSlice;
+ tailTimeSlice = Os->device->profileTailTimeSlice;
+
+ /* before the first time profiling, delay to make sure the profiling data is valid */
+ if(countDelay++ == 0)
+ gckOS_Delay(Os, timeSlice);
+
+ if(needProfile)
+ {
+ gcmkONERROR(gckOS_IdleProfile(Os, &timeSlice,
+ &idleTime, gcvNULL));
+
+ if(Os->device->powerDebug)
+ {
+ gcmkPRINT("idle:total [%d, %d]\n",idleTime, timeSlice);
+ }
+
+ gcmkONERROR(gckOS_IdleProfile(Os, &tailTimeSlice,
+ &tailIdleTime, gcvNULL));
+
+ if(Os->device->powerDebug)
+ {
+ gcmkPRINT("idle:total [%d, %d]\n", tailIdleTime, tailTimeSlice);
+ }
+ if( (idleTime * 100 > timeSlice * Os->device->idleThreshold)
+ && (tailIdleTime == tailTimeSlice) )
+ {
+ Os->device->needPowerOff = gcvTRUE;
+ }
+ else
+ {
+ Os->device->needPowerOff = gcvFALSE;
+ }
+ }
+
+ if(Os->device->needPowerOff
+ && (Os->device->currentPMode != gcvPM_NORMAL))
+ {
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF));
+
+ BSP_IDLE_PROFILE_CALC_IDLE_TIME;
+ }
+
+ gcmkFOOTER_NO();
+
+ return gcvSTATUS_OK;
+
+OnError:
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_Reset(
+ IN gckOS Os
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gckHARDWARE hardware = Os->device->kernel->hardware;
+ gckEVENT event = Os->device->kernel->event;
+ gckCOMMAND command = Os->device->kernel->command;
+ static gctUINT resetCount;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ if(Os->device->powerDebug)
+ {
+ gcmkPRINT("[galcore] %s, need to reset, chipPowerState=%d\n", __func__, hardware->chipPowerState);
+ }
+
+ /* Stop the command parser. */
+ /* gckCOMMAND_Stop may delay on "wait for idle"
+ use gckHARDWARE_End to stop GC directly
+ */
+ if (command->running)
+ {
+ /* Replace last WAIT with END. */
+ gcmkONERROR(
+ gckHARDWARE_End(hardware,
+ command->wait,
+ &command->waitSize));
+
+ /* Command queue is no longer running. */
+ command->running = gcvFALSE;
+ }
+
+ gcmkONERROR(gckOS_SuspendInterrupt(Os));
+ gcmkONERROR(gckOS_ClockOff(Os, gcvTRUE, gcvTRUE));
+
+ gcmkONERROR(gckOS_ClockOn(Os, gcvTRUE, gcvTRUE, 0));
+ gcmkONERROR(gckOS_ResumeInterrupt(Os));
+
+ /* Initialize hardware. */
+ gcmkONERROR(
+ gckHARDWARE_InitializeHardware(hardware));
+
+ gcmkONERROR(
+ gckHARDWARE_SetFastClear(hardware,
+ hardware->allowFastClear,
+ hardware->allowCompression));
+
+ /* Force the command queue to reload the next context. */
+ command->currentContext = 0;
+
+ /* Sleep for 1000us, to make sure everything is powered on. */
+ gckOS_Udelay(Os, 1000);
+
+ /* Start the command processor. */
+ gcmkONERROR(gckCOMMAND_Start(command));
+
+ /* trigger any commited event */
+ gcmkONERROR(gckEVENT_Interrupt(event, 0x7FFFFFFF));
+ gcmkONERROR(gckEVENT_Notify(event, 1));
+
+ if(Os->device->powerDebug)
+ {
+ gcmkPRINT("[galcore] %s : resetCount=%d \n", __func__, resetCount++);
+ }
+
+ gcmkFOOTER();
+ return status;
+
+
+OnError:
+ gcmkPRINT("ERROR: %s has error \n",__func__);
+ return status;
+
+}
+
+gceSTATUS
+gckOS_SetConstraint(
+ IN gckOS Os,
+ IN gctBOOL enableDVFM,
+ IN gctBOOL enableLPM
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+#if 0 /*MRVL_CONFIG_DVFM_MMP2*/
+ if(enableDVFM)
+ {
+ /* disable OP0(100M), OP4(1001M) on mmp2 */
+ dvfm_disable_op_name("Ultra Low MIPS", Os->device->dvfm_dev_index);
+ dvfm_disable_op_name("Super H MIPS", Os->device->dvfm_dev_index);
+ }
+#endif
+
+#if MRVL_CONFIG_DVFM_MG1
+
+#if 0
+ if(enableDVFM)
+ {
+ /* disable LPM and OP1 - OP5 on PV2 evb */
+ dvfm_disable(Os->device->dvfm_dev_index);
+ }
+#else
+ if(enableLPM)
+ {
+ /* gcmkPRINT("\n Idle = false, disable low power mode\n"); */
+ /* Disable D0CS */
+ dvfm_disable_op_name("D0CS", Os->device->dvfm_dev_index);
+ /* Disable Low power mode */
+ dvfm_disable_op_name("D1", Os->device->dvfm_dev_index);
+ dvfm_disable_op_name("D2", Os->device->dvfm_dev_index);
+ /* Disable CG */
+ if(cpu_is_pxa95x())
+ {
+ dvfm_disable_op_name("CG", Os->device->dvfm_dev_index);
+ }
+ }
+
+ if(enableDVFM)
+ {
+
+ /* Disable OP1 - OP7 on PV2 evb */
+ dvfm_disable_op_name("156M", Os->device->dvfm_dev_index);
+ /* dvfm_disable_op_name("208M", Os->device->dvfm_dev_index); */
+ dvfm_disable_op_name("156M_HF", Os->device->dvfm_dev_index);
+ /* dvfm_disable_op_name("208M_HF", Os->device->dvfm_dev_index); */
+ /* dvfm_disable_op_name("416M", Os->device->dvfm_dev_index); */
+ /* dvfm_disable_op_name("624M", Os->device->dvfm_dev_index); */
+ /* dvfm_disable_op_name("832M", Os->device->dvfm_dev_index); */
+ /* dvfm_disable(Os->device->dvfm_dev_index); */
+ }
+#endif
+
+#endif
+
+ gcmkFOOTER_NO();
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_UnSetConstraint(
+ IN gckOS Os,
+ IN gctBOOL enableDVFM,
+ IN gctBOOL enableLPM
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+#if 0 /*MRVL_CONFIG_DVFM_MMP2*/
+ if(enableDVFM)
+ {
+ /* enable OP0(100M), OP4(1001M) on mmp2 */
+ dvfm_enable_op_name("Ultra Low MIPS", Os->device->dvfm_dev_index);
+ dvfm_enable_op_name("Super H MIPS", Os->device->dvfm_dev_index);
+ }
+#endif
+
+#if MRVL_CONFIG_DVFM_MG1
+
+#if 0
+ if(enableDVFM)
+ {
+ /* enable LPM and OP1 - OP5 on PV2 evb */
+ dvfm_enable(Os->device->dvfm_dev_index);
+ }
+#else
+ if(enableLPM)
+ {
+ /* gcmkPRINT("\n Idle = true, enable low power mode\n"); */
+ /* Enable D0CS */
+ dvfm_enable_op_name("D0CS", Os->device->dvfm_dev_index);
+ /* Enable Low power mode */
+ dvfm_enable_op_name("D1", Os->device->dvfm_dev_index);
+ dvfm_enable_op_name("D2", Os->device->dvfm_dev_index);
+ /* Enable CG */
+ if(cpu_is_pxa95x())
+ {
+ dvfm_enable_op_name("CG", Os->device->dvfm_dev_index);
+ }
+ }
+
+ if(enableDVFM)
+ {
+
+ /* Enable OP1 - OP7 on PV2 evb */
+ dvfm_enable_op_name("156M", Os->device->dvfm_dev_index);
+ /* dvfm_enable_op_name("208M", Os->device->dvfm_dev_index); */
+ dvfm_enable_op_name("156M_HF", Os->device->dvfm_dev_index);
+ /* dvfm_enable_op_name("208M_HF", Os->device->dvfm_dev_index); */
+ /* dvfm_enable_op_name("416M", Os->device->dvfm_dev_index); */
+ /* dvfm_enable_op_name("624M", Os->device->dvfm_dev_index); */
+ /* dvfm_enable_op_name("832M", Os->device->dvfm_dev_index); */
+ /* dvfm_enable(Os->device->dvfm_dev_index); */
+ }
+#endif
+
+#endif
+
+ gcmkFOOTER_NO();
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_AddProfNode(
+ IN gckOS Os,
+ IN gctBOOL Idle
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Grab the mutex. */
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Os, Os->mutexIdleProfile, gcvINFINITE));
+
+
+ Os->device->lastNodeIndex = (Os->device->lastNodeIndex + 1) % NUM_PROFILE_NODES;
+ Os->device->profNode[Os->device->lastNodeIndex].idle = Idle;
+ Os->device->profNode[Os->device->lastNodeIndex].tick = gckOS_GetTicks();
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->mutexIdleProfile));
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_NotifyIdle(
+ IN gckOS Os,
+ IN gctBOOL Idle
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Idle=%d", Os, Idle);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gckOS_AddProfNode(Os, Idle);
+
+ /* gcmkPRINT("[galcore] %s:\n",Idle?"Idle,freq scale to 1/64":"Running"); */
+ if(Idle)
+ {
+ /* GC changes from run to idle, start profiling */
+ BSP_IDLE_PROFILE_CALC_BUSY_TIME;
+
+#if MRVL_PLATFORM_MG1
+ gckHARDWARE_SetPowerManagementState(Os->device->kernel->hardware, gcvPOWER_SUSPEND);
+#else
+#if MRVL_ENABLE_FREQ_SCALING
+ /* frequence change to 1/64 */
+ gcmkVERIFY_OK(gckOS_WriteRegister(Os,0x00000,0x204));
+ /* Loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(Os,0x00000,0x004));
+
+ gckOS_UnSetConstraint(Os,
+ Os->device->enableDVFM,
+ Os->device->enableLowPowerMode);
+#endif
+#endif
+ }
+ else
+ {
+#if MRVL_PLATFORM_MG1
+#else
+#if MRVL_ENABLE_FREQ_SCALING
+ /* Write the clock control register. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(Os, 0x00000, 0x300));
+ /* Done loading the frequency scaler. */
+ gcmkVERIFY_OK(gckOS_WriteRegister(Os, 0x00000, 0x100));
+
+ gckOS_SetConstraint(Os,
+ Os->device->enableDVFM,
+ Os->device->enableLowPowerMode);
+#endif
+#endif
+ /* GC changes from idle to run, end profiling */
+ BSP_IDLE_PROFILE_CALC_IDLE_TIME;
+ }
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gctUINT32
+gckOS_GetTicks(
+ void
+ )
+{
+ struct timeval tv;
+ unsigned int tickcount = 0;
+ do_gettimeofday(&tv);
+ tickcount = (tv.tv_sec*1000 + tv.tv_usec/1000);
+ return tickcount;
+}
+
+gceSTATUS
+gckOS_IdleProfile(
+ IN gckOS Os,
+ IN OUT gctUINT32* Timeslice,
+ OUT gctUINT32* IdleTime,
+ OUT gctUINT32* StateSwitchTimes
+ )
+{
+ gctUINT i;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctUINT currentTick;
+ gckProfNode firstNode;
+ gckProfNode lastNode;
+ gckProfNode iterNode; /* first node in the time slice */
+ gckProfNode nextNode; /* the next node of iterNode */
+ gctUINT firstIndex, lastIndex, iterIndex;
+ gctUINT idleTime = 0;
+
+ gcmkHEADER_ARG("Os=0x%x Timeslice=0x%x IdleTime=0x%x", Os, Timeslice, IdleTime);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Timeslice != gcvNULL);
+ gcmkVERIFY_ARGUMENT(IdleTime != gcvNULL);
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Os,
+ Os->mutexIdleProfile,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ currentTick = gckOS_GetTicks();
+ lastIndex = Os->device->lastNodeIndex;
+ iterIndex = lastIndex;
+ firstIndex = (Os->device->lastNodeIndex + 1) % NUM_PROFILE_NODES;
+ firstNode = &Os->device->profNode[firstIndex];
+ lastNode = &Os->device->profNode[lastIndex];
+
+ /* gcmkPRINT("@@@@@@[first last] [%d, %d]\n",firstIndex,lastIndex); */
+
+ /* no node in the time slice */
+ if(currentTick - lastNode->tick >= *Timeslice)
+ {
+ if(lastNode->idle)
+ {
+ idleTime += *Timeslice;
+ /* gcmkPRINT("line %d, idletime : %d",__LINE__, idleTime); */
+ }
+ }
+ else
+ {
+ /* find first node in the time slice */
+ if(currentTick - firstNode->tick < *Timeslice)
+ {
+ /* */
+ *Timeslice = currentTick - firstNode->tick;
+
+ iterIndex = firstIndex;
+ iterNode = &Os->device->profNode[iterIndex];
+ }
+ else
+ {
+ for(i = 0; i < NUM_PROFILE_NODES; i++)
+ {
+ iterIndex = (firstIndex + i) % NUM_PROFILE_NODES;
+ iterNode = &Os->device->profNode[iterIndex];
+ if(currentTick - iterNode->tick < *Timeslice)
+ {
+ break;
+ }
+ }
+ }
+ /* gcmkPRINT("line %d, iterIndex : %d\n",__LINE__, iterIndex); */
+
+ if(StateSwitchTimes != gcvNULL)
+ {
+ *StateSwitchTimes = (lastIndex - iterIndex + NUM_PROFILE_NODES) % NUM_PROFILE_NODES + 1;
+ }
+
+ /* startTick to first node time */
+ if(!iterNode->idle)
+ {
+ idleTime += iterNode->tick - (currentTick - *Timeslice);
+ /* gcmkPRINT("line %d, idletime : %d\n",__LINE__, idleTime); */
+ }
+
+ /* last node to currentTick time */
+ if(lastNode->idle)
+ {
+ idleTime += currentTick - lastNode->tick;
+ /* gcmkPRINT("line %d, idletime : %d\n",__LINE__, idleTime); */
+ }
+
+ /* first node to last node time */
+ for(i = 0; i < NUM_PROFILE_NODES; i++ )
+ {
+ if(iterIndex == lastIndex)
+ break;
+
+ if(iterNode->idle)
+ {
+ nextNode = &Os->device->profNode[(iterIndex + 1) % NUM_PROFILE_NODES];
+ idleTime += nextNode->tick - iterNode->tick;
+ /* gcmkPRINT("line %d, idletime : %d\n",__LINE__, idleTime); */
+ }
+ iterIndex = (iterIndex + 1) % NUM_PROFILE_NODES;
+ iterNode = &Os->device->profNode[iterIndex];
+ }
+
+ }
+
+ *IdleTime = idleTime;
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->mutexIdleProfile));
+
+ gcmkFOOTER_NO();
+
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_ARGS("status=%d, acquired=%d", status, acquired);
+ if (acquired)
+ {
+ /* Release command queue mutex on error. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->mutexIdleProfile));
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+
+}
+
+gceSTATUS gckOS_DumpToFile(
+ IN gckOS Os,
+ IN gctCONST_STRING filename,
+ IN gctPOINTER logical,
+ IN gctSIZE_T size
+ )
+{
+ struct file *file = gcvNULL;
+ mm_segment_t old_fs = get_fs();
+ set_fs(get_ds());
+
+ file = filp_open(filename, O_WRONLY|O_CREAT, 0);
+ if ((file != gcvNULL ) && (file->f_op->read != gcvNULL))
+ {
+ if(logical != gcvNULL)
+ {
+ file->f_op->write(file, logical, size, &file->f_pos);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+ filp_close(file, gcvNULL);
+
+ return gcvSTATUS_NOT_SUPPORTED;
+ }
+
+ set_fs(old_fs);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Source != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memcpy(Destination, Source, Bytes);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkHEADER_ARG("Memory=0x%x Bytes=%lu", Memory, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memset(Memory, 0, Bytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdkUSE_MEMORY_RECORD
+MEMORY_RECORD_PTR
+CreateMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ )
+{
+ MEMORY_RECORD_PTR mr;
+
+ mr = (MEMORY_RECORD_PTR)kmalloc(sizeof(struct MEMORY_RECORD), GFP_ATOMIC);
+ if (mr == gcvNULL)
+ {
+ gcmkLOG_WARNING_ARGS("out of memory to create MemoryRecord");
+ return gcvNULL;
+ }
+
+ MEMORY_LOCK(Os);
+
+ mr->node = Node;
+
+ mr->prev = List->prev;
+ mr->next = List;
+ List->prev->next = mr;
+ List->prev = mr;
+
+ MEMORY_UNLOCK(Os);
+
+ return mr;
+}
+
+void
+DestoryMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR Mr
+ )
+{
+ MEMORY_LOCK(Os);
+
+ Mr->prev->next = Mr->next;
+ Mr->next->prev = Mr->prev;
+
+ MEMORY_UNLOCK(Os);
+
+ kfree(Mr);
+
+ Mr = gcvNULL;
+}
+
+MEMORY_RECORD_PTR
+FindMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ )
+{
+ MEMORY_RECORD_PTR mr;
+
+ MEMORY_LOCK(Os);
+
+ mr = List->next;
+
+ while (mr != List)
+ {
+ if (mr->node == Node)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return mr;
+ }
+
+ mr = mr->next;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvNULL;
+}
+
+void
+FreeAllMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List
+ )
+{
+ MEMORY_RECORD_PTR mr;
+ gctUINT i = 0;
+
+ MEMORY_LOCK(Os);
+
+ while (List->next != List)
+ {
+ mr = List->next;
+
+ mr->prev->next = mr->next;
+ mr->next->prev = mr->prev;
+
+ i++;
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Unfreed %s memory: node: %p",
+ (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)?
+ "video" : (mr->node->Virtual.contiguous)?
+ "contiguous" : "virtual",
+ mr->node);
+
+ while (gcvTRUE)
+ {
+ if (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ if (mr->node->VidMem.locked == 0) break;
+ }
+ else
+ {
+ if (mr->node->Virtual.locked == 0) break;
+ }
+
+ gckVIDMEM_Unlock(mr->node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
+ }
+
+ gckVIDMEM_Free(mr->node);
+
+ kfree(mr);
+
+ mr = gcvNULL;
+
+ MEMORY_LOCK(Os);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ if (i > 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "======== Total %d unfreed video/contiguous/virtual memory ========", i);
+ }
+}
+#endif
+
+/*******************************************************************************
+** gckOS_CacheFlush
+**
+** Flush the cache for the specified addresses. The GPU is going to need the
+** data. If the system is allocating memory as non-cachable, this function can
+** be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctHANDLE Process
+** Process handle Logical belongs to or gcvNULL if Logical belongs to
+** the kernel.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheFlush(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** gckOS_CacheInvalidate
+**
+** Flush the cache for the specified addresses and invalidate the lines as
+** well. The GPU is going to need and modify the data. If the system is
+** allocating memory as non-cachable, this function can be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctHANDLE Process
+** Process handle Logical belongs to or gcvNULL if Logical belongs to
+** the kernel.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheInvalidate(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Broadcasting *********************************
+*******************************************************************************/
+#if VIVANTE_POWER_MANAGE
+/*******************************************************************************
+**
+** gckOS_Broadcast
+**
+** System hook for broadcast events from the kernel driver.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gceBROADCAST Reason
+** Reason for the broadcast. Can be one of the following values:
+**
+** gcvBROADCAST_GPU_IDLE
+** Broadcasted when the kernel driver thinks the GPU might be
+** idle. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_COMMIT
+** Broadcasted when any client process commits a command
+** buffer. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_STUCK
+** Broadcasted when the kernel driver hits the timeout waiting
+** for the GPU.
+**
+** gcvBROADCAST_FIRST_PROCESS
+** First process is trying to connect to the kernel.
+**
+** gcvBROADCAST_LAST_PROCESS
+** Last process has detached from the kernel.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle = 0, dma = 0, axi = 0, read0 = 0, read1 = 0, write = 0;
+
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Reason=%d", Os, Hardware, Reason);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ switch (Reason)
+ {
+ case gcvBROADCAST_FIRST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
+ break;
+
+ case gcvBROADCAST_LAST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
+
+ break;
+
+ case gcvBROADCAST_GPU_IDLE:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
+ break;
+
+ case gcvBROADCAST_GPU_COMMIT:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
+ break;
+
+ case gcvBROADCAST_GPU_STUCK:
+ gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
+ gcmkPRINT("!!FATAL!! GPU Stuck");
+ gcmkPRINT(" idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
+
+ if (Hardware->chipFeatures & (1 << 4))
+ {
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
+ gcmkPRINT(" read0=0x%08X read1=0x%08X write=0x%08X",
+ read0, read1, write);
+ }
+
+ gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+ break;
+
+ case gcvBROADCAST_AXI_BUS_ERROR:
+ gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
+ gcmkPRINT("!!FATAL!! AXI Bus Error");
+ gcmkPRINT(" idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
+
+ if (Hardware->chipFeatures & (1 << 4))
+ {
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
+ gcmkPRINT(" read0=0x%08X read1=0x%08X write=0x%08X",
+ read0, read1, write);
+ }
+
+ gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+********************************** Semaphores **********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_CreateSemaphore
+**
+** Create a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Semaphore
+** Pointer to the variable that will receive the created semaphore.
+*/
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ )
+{
+ gceSTATUS status;
+ struct semaphore *sem;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Allocate the semaphore structure. */
+ gcmkONERROR(
+ gckOS_Allocate(Os, gcmSIZEOF(struct semaphore), (gctPOINTER *) &sem));
+
+ /* Initialize the semaphore. */
+ sema_init(sem, 1);
+
+ /* Return to caller. */
+ *Semaphore = (gctPOINTER) sem;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireSemaphore
+**
+** Acquire a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Acquire the semaphore. */
+ if (down_interruptible((struct semaphore *) Semaphore))
+ {
+ gcmkONERROR(gcvSTATUS_TIMEOUT);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseSemaphore
+**
+** Release a previously acquired semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Release the semaphore. */
+ up((struct semaphore *) Semaphore);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySemaphore
+**
+** Destroy a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Free the sempahore structure. */
+ gcmkONERROR(gckOS_Free(Os, Semaphore));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkLOG_ERROR_STATUS();
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ )
+{
+ gcmkHEADER();
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(ProcessID != gcvNULL);
+
+ /* Get process ID. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ *ProcessID = task_tgid_vnr(current);
+#else
+ *ProcessID = current->tgid;
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ProcessID=%u", *ProcessID);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeProcessResource
+**
+** Free process resource when application exit normall or unnormal
+**
+** INPUT:
+**
+** os,pid.
+**
+** OUTPUT:
+**
+** None
+*/
+gceSTATUS gckOS_FreeProcessResource(IN gckOS Os, gctUINT32 pid)
+{
+ PLINUX_MDL pNext, mdl = Os->mdlHead;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ while(mdl)
+ {
+ pNext = mdl->next;
+
+ if(mdl->pid == pid)
+ {
+ gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(Os,
+ PAGE_SIZE, (gctPHYS_ADDR) mdl, (gctPOINTER) mdl));
+ }
+
+ mdl = pNext;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ )
+{
+ gcmkHEADER();
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(ThreadID != gcvNULL);
+
+ /* Get thread ID. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ *ThreadID = task_pid_vnr(current);
+#else
+ *ThreadID = current->pid;
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ThreadID=%u", *ThreadID);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.?
+**
+** gctBOOL Clock
+** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Clock=%d Power=%d", Os, Clock, Power);
+
+ /* TODO: Put your code here. */
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.h b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.h
new file mode 100644
index 0000000..dc583b2
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/hal/os/linux/kernel/gc_hal_kernel_os.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_os_h_
+#define __gc_hal_kernel_os_h_
+
+/*
+* Allocate video memory from low memory back when ALLOC_HIGHMEM set to 0
+* Allocate video memory from hight memory back when ALLOC_HIGHMEM set to 1
+*
+* When we can not reserve physical continious memory (video memory), please
+* set ALLOC_HIGHMEM set to 1 and Allocate video memory from hight memory back.
+*/
+#define ALLOC_HIGHMEM 0
+
+#define ALLOC_ALIGN_BYTES 64
+
+#define GC_INVALID_PHYS_ADDR ~0U
+
+typedef struct _LINUX_MDL_MAP
+{
+ gctINT pid;
+ gctPOINTER vmaAddr;
+ struct vm_area_struct * vma;
+ struct _LINUX_MDL_MAP * next;
+}
+LINUX_MDL_MAP, *PLINUX_MDL_MAP;
+
+typedef struct _LINUX_MDL
+{
+ gctINT pid;
+ char * addr;
+ char * addr_free; /* Alighment used, really allocated memory pointer, for free use.*/
+
+#ifdef NO_DMA_COHERENT
+#if !ALLOC_HIGHMEM
+ gctPOINTER kaddr;
+#endif
+#endif /* NO_DMA_COHERENT */
+
+ gctINT numPages;
+ gctINT pagedMem;
+ gctBOOL contiguous;
+ dma_addr_t dmaHandle;
+ PLINUX_MDL_MAP maps;
+ struct _LINUX_MDL * prev;
+ struct _LINUX_MDL * next;
+}
+LINUX_MDL, *PLINUX_MDL;
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ );
+
+typedef struct _DRIVER_ARGS
+{
+ gctPOINTER InputBuffer;
+ gctUINT32 InputBufferSize;
+ gctPOINTER OutputBuffer;
+ gctUINT32 OutputBufferSize;
+}
+DRIVER_ARGS;
+
+/* Cleanup the signal table. */
+gceSTATUS
+gckOS_CleanProcessSignal(
+ gckOS Os,
+ gctHANDLE Process
+ );
+
+#ifdef gcdkUSE_MEMORY_RECORD
+MEMORY_RECORD_PTR
+CreateMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ );
+
+void
+DestoryMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR Mr
+ );
+
+MEMORY_RECORD_PTR
+FindMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ );
+
+void
+FreeAllMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List
+ );
+#endif
+
+#endif /* __gc_hal_kernel_os_h_ */
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/init_ko.sh b/kernel_drivers/gc600_driver_dove/galcore_ko_src/init_ko.sh
new file mode 100644
index 0000000..b416c00
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/init_ko.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+export MARVELL_GCC=1
+
+if [ "$MARVELL_GCC" = "1" ];then
+export CROSS_COMPILE=arm-marvell-linux-gnueabi-
+export LIB_DIR=/usr/local/arm-marvell-linux-gnueabi/arm-marvell-linux-gnueabi/lib
+export PATH=/usr/local/arm-marvell-linux-gnueabi/bin:$PATH
+else
+export CROSS_COMPILE=arm-linux-
+export LIB_DIR=/usr/local/arm-linux-4.1.1/arm-iwmmxt-linux-gnueabi/lib
+export PATH=/usr/local/arm-linux-4.1.1/bin:$PATH
+fi
+
+export ARCH=arm
+export AQROOT=$PWD
+export AQARCH=$PWD/arch/XAQ2
+export TOOL_DIR=$AQROOT/../resource
+export KERNEL_DIR=$TOOL_DIR/linux-2.6.28
+
+
+
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/linux b/kernel_drivers/gc600_driver_dove/galcore_ko_src/linux
new file mode 100644
index 0000000..96ba076
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/linux
@@ -0,0 +1 @@
+/vobs/clone/avd1 \ No newline at end of file
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile b/kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile
new file mode 100644
index 0000000..5fdf14f
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile
@@ -0,0 +1,35 @@
+PWD := $(shell pwd)
+
+ARCH=arm
+CROSS_COMPILE ?= /usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linux-gnueabi-
+GPU_TYPE = unified
+KERNEL_DIR ?= /usr/local/tools/linux
+
+DEBUG = 0
+ABI = aapcs-linux
+ENABLE_ARM_L2_CACHE = 1
+NO_DMA_COHERENT = 1
+CONFIG_DOVE_GPU = 1
+ANDROID = 0
+ENABLE_GPU_CLOCK_BY_DRIVER = 0
+
+BUILD_OPTIONS = DEBUG=${DEBUG}
+BUILD_OPTIONS += ABI=${ABI}
+BUILD_OPTIONS += ENABLE_ARM_L2_CACHE=${ENABLE_ARM_L2_CACHE}
+BUILD_OPTIONS += NO_DMA_COHERENT=${NO_DMA_COHERENT}
+BUILD_OPTIONS += CONFIG_DOVE_GPU=${CONFIG_DOVE_GPU}
+BUILD_OPTIONS += ANDROID=${ANDROID}
+BUILD_OPTIONS += ENABLE_GPU_CLOCK_BY_DRIVER=${ENABLE_GPU_CLOCK_BY_DRIVER}
+
+GCX00_COMPILE_ENV = ${BUILD_OPTIONS} ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE}\
+ AQROOT=${PWD} AQARCH=${PWD}/arch/${GPU_TYPE} KERNEL_DIR=${KERNEL_DIR}
+
+all:
+ make ${GCX00_COMPILE_ENV} -C ${PWD} -f Kbuild
+ cp $(PWD)/hal/driver/galcore.ko .
+
+clean:
+ make ${GCX00_COMPILE_ENV} -C ${PWD} -f Kbuild clean
+
+
+
diff --git a/kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile.linux.def b/kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile.linux.def
new file mode 100644
index 0000000..2057760
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/galcore_ko_src/makefile.linux.def
@@ -0,0 +1,358 @@
+##############################################################################
+#
+# Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+#
+# The material in this file is confidential and contains trade secrets
+# of Vivante Corporation. This is proprietary information owned by
+# Vivante Corporation. No part of this work may be disclosed,
+# reproduced, copied, transmitted, or used in any way for any purpose,
+# without the express written permission of Vivante Corporation.
+#
+##############################################################################
+#
+#
+##############################################################################
+
+
+#
+# Common inlude file for Linux build.
+#
+
+################################################################
+# Arch.
+
+ARCH_TYPE ?= arm
+CPU_TYPE ?= arm920
+CPU_ARCH ?= 0
+STATIC_LINK ?= 0
+EGL_API_FB ?= 0
+USE_VDK ?= 0
+USE_PROFILER ?= 0
+USE_SW_FB ?= 0
+USE_3D_VG =1
+ABI ?= 0
+ANDROID ?= 0
+EGL_API_ANDROID ?= 0
+ANDROID_VERSION_ECLAIR ?= 0
+ENUM_WORKAROUND ?= 0
+ENDIANNESS ?=
+QNX ?= 0
+LINUX_OABI ?= 0
+USE_ARMCC ?= 0
+
+ifeq ($(LINUX_OABI), 1)
+ABI ?= 0
+else
+ABI ?= aapcs-linux
+endif
+
+################################################################
+# Toolchain.
+
+ifeq ($(USE_ARMCC),1)
+ ARM_BASE ?= /home/software/ARM
+ ARM_VERSION ?= 4.0/650
+ CROSS_COMPILE ?= $(ARM_BASE)/RVCT/Programs/$(ARM_VERSION)/linux-pentium/arm
+ CFLAGS += -I$(ARM_BASE)/RVCT/Data/$(ARM_VERSION)/include/unix
+ CC := $(CROSS_COMPILE)cc
+ CXX := $(CROSS_COMPILE)cc
+ AR := $(CROSS_COMPILE)ar
+ AS := $(CROSS_COMPILE)as
+ LD := $(CROSS_COMPILE)link
+else
+ CROSS_COMPILE ?= arm-none-linux-gnueabi-
+ CC := $(CROSS_COMPILE)gcc
+ CXX := $(CROSS_COMPILE)g++
+ AR := $(CROSS_COMPILE)ar
+ AS := $(CROSS_COMPILE)as
+ LD := $(CROSS_COMPILE)ld
+ RANLIB := $(CROSS_COMPILE)ranlib
+ STRIP := $(CROSS_COMPILE)strip
+endif
+
+################################################################
+# Make command.
+
+MAKE = make --makefile=makefile.linux
+DRV_MAKE ?= make --makefile=Kbuild
+
+################################################################
+# Resource.
+
+TOOL_DIR ?= /home/software/Linux
+ANDROID_HOME ?=
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+X11_ARM_DIR ?= $(TOOL_DIR)/X11_ARM
+
+################################################################
+# Target directory.
+
+ifeq ($(DEBUG), 1)
+OBJ_DIR ?= bin_d
+else
+OBJ_DIR ?= bin_r
+endif
+
+################################################################
+# Force to use the new compiler.
+
+SC2X_NEW ?= 1
+ES11_NEW ?= 1
+
+################################################################
+# Release directory.
+
+SDK_DIR ?= $(AQROOT)/build/sdk
+VIVANTE_SDK_DIR ?= $(SDK_DIR)
+VIVANTE_SDK_INC ?= $(VIVANTE_SDK_DIR)/include
+VIVANTE_SDK_LIB ?= $(VIVANTE_SDK_DIR)/drivers
+
+################################################################
+# Force to use dma_coherent_* stuff.
+
+NO_DMA_COHERENT ?= 0
+
+################################################################
+# Set this value to 1 if you are using ARM L2 cache.
+
+ENABLE_ARM_L2_CACHE ?= 0
+
+################################################################
+# Set this value to 1 if you are using DOVE board.
+CONFIG_DOVE_GPU ?= 0
+
+###############################################################
+# Common CFLAGS.
+
+ifeq ($(USE_ARMCC), 1)
+ CFLAGS += --c99 #--strict
+else
+ifeq ($(ABI), 0)
+else
+ CFLAGS += -mabi=$(ABI)
+endif
+
+ifneq ($(ENDIANNESS),)
+ CFLAGS += $(ENDIANNESS)
+ LFLAGS += $(ENDIANNESS)
+ PFLAGS += $(ENDIANNESS)
+endif
+endif
+
+ifeq ($(ANDROID), 1)
+ USE_VDK = 0
+
+ ifeq ($(ARCH_TYPE), arm)
+ CFLAGS += -I$(ANDROID_HOME)/bionic/libstdc++/include -I$(ANDROID_HOME)/bionic/libc/arch-arm/include -I$(ANDROID_HOME)/bionic/libc/include -I$(ANDROID_HOME)/bionic/libc/kernel/common/ -I$(ANDROID_HOME)/bionic/libc/kernel/arch-arm -I$(ANDROID_HOME)/bionic/libm/include -I$(ANDROID_HOME)/bionic/libm/include/arch/arm -I$(ANDROID_HOME)/bionic/libthread_db/include -I$(ANDROID_HOME)/system/core/include -I$(ANDROID_HOME)/frameworks/base/include
+ CFLAGS += -DANDROID -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -fno-short-enums
+ endif
+
+ ifeq ($(ARCH_TYPE), xburst)
+ CFLAGS += -I$(ANDROID_HOME)/bionic/libstdc++/include -I$(ANDROID_HOME)/bionic/libc/arch-xburst/include -I$(ANDROID_HOME)/bionic/libc/include -I$(ANDROID_HOME)/bionic/libc/kernel/common/ -I$(ANDROID_HOME)/bionic/libc/kernel/arch-xburst -I$(ANDROID_HOME)/bionic/libm/include -I$(ANDROID_HOME)/bionic/libm/include/mips -I$(ANDROID_HOME)/bionic/libthread_db/include
+ endif
+
+ ifeq ($(EGL_API_ANDROID), 1)
+ CFLAGS += -DEGL_API_ANDROID
+ endif
+
+ ifeq ($(ANDROID_VERSION_ECLAIR), 1)
+ CFLAGS += -DANDROID_VERSION_ECLAIR
+ endif
+
+ ifeq ($(ANDROID_VERSION_GINGERBREAD), 1)
+ CFLAGS += -I$(ANDROID_HOME)/frameworks/base/native/include -DANDROID_VERSION_GINGERBREAD
+ endif
+endif
+
+ifeq ($(QNX), 1)
+ CFLAGS += -D__QNXNTO__
+else
+ ifneq ($(USE_ARMCC),1)
+ CFLAGS += -DLINUX
+ endif
+endif
+
+ifeq ($(LINUX_OABI), 1)
+ CFLAGS += -DLINUX_OABI
+endif
+
+ifneq ($(USE_ARMCC), 1)
+CFLAGS += -Wall -D_REENTRANT -fno-strict-aliasing
+
+ifeq ($(CPU_TYPE), 0)
+else
+ CFLAGS += -mcpu=$(CPU_TYPE)
+ AFLAGS += -mcpu=$(CPU_TYPE)
+endif
+
+ifeq ($(CPU_ARCH), 0)
+else
+ CFLAGS += -march=$(CPU_ARCH)
+ AFLAGS += -march=$(CPU_ARCH)
+endif
+endif
+
+ifeq ($(DEBUG), 1)
+ CFLAGS += -g -fPIC -O0 -DDEBUG -D_DEBUG
+else
+ CFLAGS += -O2 -fPIC
+endif
+
+ifeq ($(EGL_API_FB), 1)
+ CFLAGS += -DEGL_API_FB
+endif
+
+ifeq ($(STATIC_LINK), 1)
+ CFLAGS += -DSTATIC_LINK
+endif
+
+ifeq ($(USE_VDK), 1)
+ CFLAGS += -DUSE_VDK=1 -DUSE_SW_FB=$(USE_SW_FB)
+else
+ CFLAGS += -DUSE_VDK=0 -DUSE_SW_FB=$(USE_SW_FB)
+endif
+ifeq ($(MRVL_NATIVE_IMAGE_KHR_FOR_CHROME),1)
+ CFLAGS += -DMRVL_NATIVE_IMAGE_KHR_FOR_CHROME=1
+else
+ CFLAGS += -DMRVL_NATIVE_IMAGE_KHR_FOR_CHROME=0
+endif
+
+ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
+ CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
+endif
+
+ifneq ($(USE_ARMCC), 1)
+CXXFLAGS += -fno-short-enums
+endif
+
+ifneq (,$(EGL_APPENDIX))
+CFLAGS += -D_EGL_APPENDIX=$(EGL_APPENDIX)
+endif
+ifneq (,$(GL_11_APPENDIX))
+CFLAGS += -D_GL_11_APPENDIX=$(GL_11_APPENDIX)
+endif
+ifneq (,$(GL_2_APPENDIX))
+CFLAGS += -D_GL_2_APPENDIX=$(GL_2_APPENDIX)
+endif
+ifneq (,$(VG_APPENDIX))
+CFLAGS += -D_VG_APPENDIX=$(VG_APPENDIX)
+endif
+
+CFLAGS += -DgcdREGISTER_ACCESS_FROM_USER=1
+
+################################################################################
+# Build with profiler
+ifeq ($(USE_PROFILER),1)
+ CFLAGS += -DVIVANTE_PROFILER=1
+else
+ CFLAGS += -DVIVANTE_PROFILER=0
+endif
+
+ifeq ($(USE_MRVL_PROFILER),1)
+ CFLAGS += -DMRVL_BENCH=1
+else
+ CFLAGS += -DMRVL_BENCH=0
+endif
+
+
+################################################################
+# Module directories.
+
+# drivers
+GAL_DIR := $(AQROOT)/hal
+ifeq ($(ES11_NEW), 1)
+GLES11_DIR := $(AQROOT)/driver/openGL/libGLESv11
+else
+GLES11_DIR := $(AQROOT)/driver/openGL/es11/driver
+endif
+EGL_DIR := $(AQROOT)/driver/openGL/egl
+GLES2X_DIR := $(AQROOT)/driver/openGL/libGLESv2x
+ifeq ($(USE_3D_VG), 1)
+VG11_DIR := $(AQROOT)/driver/openVG/vg11
+OVG11_DIR := $(AQROOT)/driver/openVG/vg11/driver
+else
+VG11_DIR := $(AQROOT)/driver/openGL/libOpenVG
+OVG11_DIR := $(AQROOT)/driver/openGL/libOpenVG
+endif
+GFX_DIR := $(AQROOT)/driver/gfx
+
+ifeq ($(SC2X_NEW), 1)
+SC2X_LIB_DIR := $(GLES2X_DIR)/compiler/libGLESv2SC/entry
+else
+SC2X_LIB_DIR := $(GLES2X_DIR)/slc/glslang/MachineIndependent/compiler
+endif
+
+ifeq ($(ANDROID), 1)
+GCU_DIR := $(AQROOT)/gcu/proj/android
+else
+GCU_DIR := $(AQROOT)/gcu/proj/linux
+endif
+
+VIVANTE_LIB_DIR := $(AQROOT)/sdk/vivante
+
+# applications
+EGL_TEST_DIR := $(AQROOT)/test/egl
+ES11_TEST_DIR := $(AQROOT)/test/es11/Linux
+ES2X_TEST_DIR := $(AQROOT)/test/es20
+ES2X_EXTERN_DIR := $(AQROOT)/test/es20/extern
+ES20_TEST_DIR := $(AQROOT)/sdk/samples/es20
+
+ifeq ($(USE_VDK), 0)
+TUTORIAL_DIR := $(ES11_TEST_DIR)
+endif
+VDK_TEST_DIR := $(AQROOT)/sdk/samples/vdk
+HAL_TEST_DIR := $(AQROOT)/sdk
+HAL_CUSTOM_DIR := $(AQROOT)/test/hal/Linux/custom
+CHIPINFO_DIR := $(AQROOT)/test/hal/common/chipinfo
+VDK_DIR := $(AQROOT)/sdk/vdk
+
+ifeq ($(USE_VDK), 1)
+CONFORM_DIR := $(AQROOT)/test/es11/conform
+else
+# old es11 conformce test was removed
+# $(AQROOT)/driver/openGL/es11/test/conform
+CONFORM_DIR :=
+endif
+
+GLBES11_DIR := $(AQROOT)/test/es11/GLBenchmark_ES1.1v2
+GLBES20_DIR := $(AQROOT)/test/es20/GLBenchmark2_RC2
+GLBESNAVI11_DIR := $(AQROOT)/test/es11/GLBenchmark_Navi_Beta2/es11
+GLBESNAVI20_DIR := $(AQROOT)/test/es11/GLBenchmark_Navi_Beta2/es20
+GTF_DIR := $(AQROOT)/test/es20/conform/GTF_ES/glsl/GTF
+VGMARK_DIR := $(AQROOT)/test/vg/common/VGMark_10_src
+VGMARK11_DIR := $(AQROOT)/test/vg11/VGMark11/VGMark11_addendum
+VGCTS_DIR := $(AQROOT)/test/vg/ovg_1.0.1_cts_rc10
+VGCTS11_DIR := $(AQROOT)/test/vg/ovg_1.1_cts_rc10
+ifeq ($(USE_VDK), 1)
+MM06_DIR := $(AQROOT)/test/es11/common/3DMarkMobile06/configuration/vdk
+else
+MM06_DIR := $(ES11_TEST_DIR)/3DMarkMobile06
+endif
+MM07_DIR := $(ES2X_TEST_DIR)/3DMarkMobileES2_RC_src
+MM07U_DIR := $(ES2X_TEST_DIR)/3DMarkMobileES2_Update
+SM20_DIR := $(AQROOT)/test/es20/SimulationMark_ES_2.0
+KANZI_DIR := $(AQROOT)/test/es20/Kanzi_UI_demo/Kanzi_UI_src
+AB20_DIR := $(ES2X_TEST_DIR)/Automotive
+JRC_DIR := $(ES2X_TEST_DIR)/JRC
+GFX_TEST_DIR := $(AQROOT)/test/gfx
+ES20_GEARS_DIR := $(AQROOT)/test/es20/gles2-cm-gears
+ES11_UNIT_DIR := $(AQROOT)/test/es11/common/UnitTest
+ES11_EXTERN_DIR := $(AQROOT)/test/es11/extern
+ES11_EXTENSION_DIR := $(AQROOT)/test/es11/Extension
+ES11_GEARS_DIR := $(AQROOT)/test/es11/gles1-cm-gears
+VG11_UNIT_DIR := $(AQROOT)/test/vg11/UnitTest
+VG11_EXTERN_DIR := $(AQROOT)/test/vg11/extern
+
+# third party resources
+DFB_DIR ?= $(TOOL_DIR)/dfb
+
+TEXTURE5_DIR := $(ES2X_TEST_DIR)/texture5
+TEXTURE7_DIR := $(ES2X_TEST_DIR)/texture7
+
+ACTINIUM_DIR := $(ES2X_TEST_DIR)/actinium
+VVLAUNCHER_DIR := $(ES2X_TEST_DIR)/vv_launcher
+
+VIDEOCUBE_DIR := $(AQROOT)/test/es11/extern/VideoCube
+
+
+
diff --git a/kernel_drivers/gc600_driver_dove/readme b/kernel_drivers/gc600_driver_dove/readme
new file mode 100644
index 0000000..fb554cc
--- /dev/null
+++ b/kernel_drivers/gc600_driver_dove/readme
@@ -0,0 +1,79 @@
+ Dove Graphics Driver for Generic Linux
+ Ver0.8.0.1123
+
+1. Introduction
+ This package contains Dove unified graphics driver for
+ generic linux and some documents.
+ This document is used to describe the package contents, how to build
+ kernel mode driver and how to install the driver binaries to device.
+
+2. Revision History
+ Ver0.8.0.1123
+ 1. Add texture generation support
+ 2. Workaround the YUV texture quality issue.
+ 3. Merge 2009.9 vivante driver.
+
+
+3. Package Contents
+ --/ -- Package root directory
+ galcroe_ko_src -- GC source code needed to build kernel mode driver
+ libgfx
+ bin/ -- GC driver binaries
+ include/ -- GC sdk header files
+ samples/ -- GC sample codes
+
+
+4. Build and Installation
+4.1 System Requirement
+ Host PC :
+ Operating system -- Ubuntu 8.04 or newer
+ Toolchain -- arm-marvell-linux-gnueabi
+ Target Device:
+ Platform -- PXA950 processor EVB platform
+ PXA968 processor EVB platform
+ ARMADA 610 processor EVB platform
+ Operation system -- Linux kernel 2.6.29 or newer
+
+4.2 Build Kernel Mode Driver
+ Enter ~/galcore_ko_src, modify the "Makefile" according to your system:
+ 1) Modify "CROSS_COMPILE" to your toolchain directory with prefix
+ (path_to_your_marvelltoolchain_dir/bin/arm-marvell-linux-gnueabi-);
+ 2) Modify "KERNEL_DIR" to point to your linux kernel tree.
+ Build kernel mode driver by commands:
+ #make clean
+ #make
+ If no error, the build result galcore.ko will be placed on current directory.
+
+4.3 Build Samples
+ 1) Enter the ~/libgfx/samples, modify the Makefile according to your system;
+ 2) Modify "CC" point to your toolchain gcc compiler;
+ 3) Build samples by commands:
+ #make clean
+ #make
+
+4.4 Installation
+ Copy galcore.ko to device /lib/modules directory:
+ #cp ~/galcore.ko /lib/modules/
+ Copy *.so to device /usr/lib directory:
+ #cp ~/bin/libGAL.so /usr/lib/
+ #cp ~/bin/libEGL.so /usr/lib/
+ #cp ~/bin/libGLES_CM.so /usr/lib/
+ #cp ~/bin/libOpenVG.so /usr/lib/
+ #cp ~/bin/libGLESv2x.so /usr/lib/
+ #cp ~/bin/libGLESv2SC.so /usr/lib/
+ #cp ~/bin/libVDK.so /usr/lib/
+ Make sure the system startup script already contains the command to load kernel mode driver,
+ For example, you can add a init script in /ect/init.d/galcore.sh like:
+ #!/bin/sh
+ insmod /lib/modules/galcore.ko registerMemBase=0xf1840000 irqLine=48 contiguousBase=0x8000000 contiguousSize=0x2000000
+ mknod /dev/galcore c 199 0
+ chmod 777 /dev/galcore
+
+5. FAQ
+ 1. "We can't find the arm-marvell-linux-gnueabi toolchain".
+ Contact your Marvell representative to get arm-marvell-linux-gnueabi toolchain.
+
+6. Known Issues
+ Problem : The OpenVG implementation does not enable anti-alias by default.
+ Workaround: Choose the EGL configuration with EGL_SAMPLES = 4.
+