source "drivers/staging/rk2818/rk1000_control/Kconfig"
source "drivers/staging/rk2818/rk2818_power/Kconfig"
+
+source "drivers/staging/rk29/vivante/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
obj-$(CONFIG_RK1000_CONTROL) += rk2818/rk1000_control/
obj-$(CONFIG_RK1000_TVOUT) += rk2818/rk1000_tv/
obj-$(CONFIG_RK2818_POWER) += rk2818/rk2818_power/
+obj-$(CONFIG_VIVANTE) += rk29/vivante/
--- /dev/null
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+#
+# Linux build file for kernel HAL driver.
+#
+
+include $(AQROOT)/config
+
+DRIVER_OUT_DIR = hal/driver
+KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR := hal/os/linux/kernel
+ARCH_KERNEL_DIR := arch/$(notdir $(AQARCH))/hal/kernel
+HAL_KERNEL_DIR := hal/kernel
+
+EXTRA_CFLAGS += -Werror
+
+OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_debug.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_os.o
+
+ifeq ($(USE_3D_VG), 1)
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
+
+else
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o \
+ $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_command.o
+
+endif
+
+ifeq ($(KERNELRELEASE), )
+
+.PHONY: all clean install
+
+# Define targets.
+all:
+ @mkdir -p $(DRIVER_OUT_DIR)
+ @make V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+
+clean:
+ @rm -rf $(OBJS)
+ @rm -rf $(DRIVER_OUT_DIR)
+ @rm -rf modules.order Module.symvers
+
+install: all
+ @mkdir -p $(SDK_DIR)/drivers
+ @cp $(DRIVER_OUT_DIR)/galcore.ko $(SDK_DIR)/drivers
+
+else
+
+
+EXTRA_CFLAGS += -DLINUX -DDRIVER
+
+ifeq ($(ENUM_WORKAROUND), 1)
+EXTRA_CFLAGS += -DENUM_WORKAROUND=1
+else
+EXTRA_CFLAGS += -DENUM_WORKAROUND=0
+endif
+
+ifeq ($(FLAREON),1)
+EXTRA_CFLAGS += -DFLAREON
+endif
+
+ifeq ($(DEBUG), 1)
+EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
+else
+EXTRA_CFLAGS += -DDBG=0
+endif
+
+ifeq ($(NO_DMA_COHERENT), 1)
+EXTRA_CFLAGS += -DNO_DMA_COHERENT
+endif
+
+ifeq ($(ENABLE_ARM_L2_CACHE), 1)
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=1
+else
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=0
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifeq ($(gcdNO_POWER_MANAGEMENT), 1)
+EXTRA_CFLAGS += -DgcdNO_POWER_MANAGEMENT=1
+else
+EXTRA_CFLAGS += -DgcdNO_POWER_MANAGEMENT=0
+endif
+
+ifneq ($(USE_PLATFORM_DRIVER), 0)
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
+else
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
+endif
+
+ifeq ($(USE_PROFILER), 1)
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
+else
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=0
+endif
+
+ifeq ($(ANDROID), 1)
+EXTRA_CFLAGS += -DANDROID=1
+endif
+
+ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
+else
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
+endif
+
+ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
+else
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
+endif
+
+ifeq ($(NO_USER_DIRECT_ACCESS_FROM_KERNEL), 1)
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=1
+else
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=0
+endif
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/cmodel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/user
+
+obj-m = $(DRIVER_OUT_DIR)/galcore.o
+
+$(DRIVER_OUT_DIR)/galcore-objs = $(OBJS)
+
+endif
--- /dev/null
+menu "GPU Vivante"
+config VIVANTE
+ tristate "ROCKCHIP Vivante GPU"
+ default y
+ help
+ Vivante GPU module.
+endmenu
--- /dev/null
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+#
+# Linux build file for kernel HAL driver.
+#
+
+################################################################
+# Arch.
+
+ARCH_TYPE ?= arm
+CPU_TYPE ?= arm920
+CPU_ARCH ?= 0
+STATIC_LINK ?= 0
+EGL_API_FB ?= 0
+USE_VDK ?= 0
+USE_PROFILER ?= 0
+USE_SW_FB ?= 0
+USE_3D_VG =1
+ABI ?= 0
+ANDROID ?= 0
+EGL_API_ANDROID ?= 0
+ENUM_WORKAROUND ?= 0
+ENDIANNESS ?=
+QNX ?= 0
+LINUX_OABI ?= 0
+USE_ARMCC ?= 0
+
+ifeq ($(LINUX_OABI), 1)
+ABI ?= 0
+else
+ABI ?= aapcs-linux
+endif
+
+################################################################
+# Force to use dma_coherent_* stuff.
+
+NO_DMA_COHERENT ?= 0
+
+################################################################
+# Set this value to 1 if you are using ARM L2 cache.
+
+ENABLE_ARM_L2_CACHE = 0
+
+################################################################
+# Set this value to 1 if you are using DOVE board.
+CONFIG_DOVE_GPU = 0
+
+
+ENABLE_GPU_CLOCK_BY_DRIVER = 0
+
+
+AQROOT ?= drivers/staging/rk29/vivante
+AQARCH ?= $(AQROOT)/arch/XAQ2
+
+#include $(AQROOT)/config
+ARCH_TYPE ?= arm
+SDK_DIR ?= $(AQROOT)/build/sdk
+USE_3D_VG = 1
+
+DEBUG = 1
+
+#DRIVER_OUT_DIR = hal/driver
+#KERNEL_DIR ?= $(TOOL_DIR)/kernel
+
+OS_KERNEL_DIR := hal/os/linux/kernel
+ARCH_KERNEL_DIR := arch/XAQ2/hal/kernel
+HAL_KERNEL_DIR := hal/kernel
+
+EXTRA_CFLAGS += -Werror
+
+OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_debug.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
+ $(OS_KERNEL_DIR)/gc_hal_kernel_os.o
+
+ifeq ($(USE_3D_VG), 1)
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
+
+else
+
+OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_interrupt.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
+ $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o
+
+OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o \
+ $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware_command.o
+
+endif
+
+
+EXTRA_CFLAGS += -DLINUX -DDRIVER
+
+ifeq ($(ENUM_WORKAROUND), 1)
+EXTRA_CFLAGS += -DENUM_WORKAROUND=1
+else
+EXTRA_CFLAGS += -DENUM_WORKAROUND=0
+endif
+
+ifeq ($(FLAREON),1)
+EXTRA_CFLAGS += -DFLAREON
+endif
+
+ifeq ($(DEBUG), 1)
+EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
+else
+EXTRA_CFLAGS += -DDBG=0
+endif
+
+ifeq ($(NO_DMA_COHERENT), 1)
+EXTRA_CFLAGS += -DNO_DMA_COHERENT
+endif
+
+ifeq ($(ENABLE_ARM_L2_CACHE), 1)
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=1
+else
+EXTRA_CFLAGS += -DENABLE_ARM_L2_CACHE=0
+endif
+
+ifeq ($(CONFIG_DOVE_GPU), 1)
+EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
+endif
+
+ifeq ($(gcdNO_POWER_MANAGEMENT), 1)
+EXTRA_CFLAGS += -DgcdNO_POWER_MANAGEMENT=1
+else
+EXTRA_CFLAGS += -DgcdNO_POWER_MANAGEMENT=0
+endif
+
+ifneq ($(USE_PLATFORM_DRIVER), 0)
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
+else
+EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
+endif
+
+ifeq ($(USE_PROFILER), 1)
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
+else
+EXTRA_CFLAGS += -DVIVANTE_PROFILER=0
+endif
+
+ifeq ($(ANDROID), 1)
+EXTRA_CFLAGS += -DANDROID=1
+endif
+
+ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
+else
+EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
+endif
+
+ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
+else
+EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
+endif
+
+ifeq ($(NO_USER_DIRECT_ACCESS_FROM_KERNEL), 1)
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=1
+else
+EXTRA_CFLAGS += -DNO_USER_DIRECT_ACCESS_FROM_KERNEL=0
+endif
+
+EXTRA_CFLAGS += -I$(AQROOT)/hal/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/hal/kernel
+EXTRA_CFLAGS += -I$(AQARCH)/cmodel/inc
+EXTRA_CFLAGS += -I$(AQROOT)/hal/user
+
+obj-$(CONFIG_VIVANTE) += galcore.o
+galcore-objs := $(OBJS)
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal.h"
+#include "gc_hal_kernel.h"
+
+#define _GC_OBJ_ZONE gcvZONE_HARDWARE
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+static gceSTATUS
+_IdentifyHardware(
+ IN gckOS Os,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32_PTR ChipRevision,
+ OUT gctUINT32_PTR ChipFeatures,
+ OUT gctUINT32_PTR ChipMinorFeatures0,
+ OUT gctUINT32_PTR ChipMinorFeatures1
+ )
+{
+ gceSTATUS status;
+ gctUINT32 chipIdentity;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x00018, &chipIdentity));
+
+ /* Special case for older graphic cores. */
+ if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
+ {
+ *ChipModel = gcv500;
+ *ChipRevision = ( ((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
+ }
+
+ else
+ {
+ /* Read chip identity register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os,
+ 0x00020,
+ (gctUINT32_PTR) ChipModel));
+
+ /* !!!! HACK ALERT !!!! */
+ /* Because people change device IDs without letting software know
+ ** about it - here is the hack to make it all look the same. Only
+ ** for GC400 family. Next time - TELL ME!!! */
+ if ((*ChipModel & 0xFF00) == 0x0400)
+ {
+ *ChipModel &= 0x0400;
+ }
+
+ /* Read CHIP_REV register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x00024, ChipRevision));
+
+ if ((*ChipModel == gcv300)
+ && (*ChipRevision == 0x2201)
+ )
+ {
+ gctUINT32 date, time;
+
+ /* Read date and time registers. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x00028, &date));
+
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x0002C, &time));
+
+ if ((date == 0x20080814) && (time == 0x12051100))
+ {
+ /* This IP has an ECO; put the correct revision in it. */
+ *ChipRevision = 0x1051;
+ }
+ }
+ }
+
+ /* Read chip feature register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os, 0x0001C, ChipFeatures));
+
+ /* Disable fast clear on GC700. */
+ if (*ChipModel == gcv700)
+ {
+ *ChipFeatures = ((((gctUINT32) (*ChipFeatures)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ if (((*ChipModel == gcv500) && (*ChipRevision < 2))
+ || ((*ChipModel == gcv300) && (*ChipRevision < 0x2000))
+ )
+ {
+ /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these registers. */
+ *ChipMinorFeatures0 = 0;
+ *ChipMinorFeatures1 = 0;
+ }
+ else
+ {
+ /* Read chip minor feature register #0. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os,
+ 0x00034,
+ ChipMinorFeatures0));
+
+ /* Disable fast clear flush on some specific cores. */
+ if (((*ChipModel == gcv600) && (*ChipRevision == 0x4302))
+ )
+ {
+ *ChipMinorFeatures0 = ((((gctUINT32) (*ChipMinorFeatures0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
+ }
+
+ if (((((gctUINT32) (*ChipMinorFeatures0)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))))
+ )
+ {
+ /* Read chip minor featuress register #1. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Os,
+ 0x00074,
+ ChipMinorFeatures1));
+ }
+ else
+ {
+ /* Chip doesn't has minor features register #1. */
+ *ChipMinorFeatures1 = 0;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ChipModel=%x *ChipRevision=%x *ChipFeatures=%08x "
+ "*ChipMinorFeatures0=%08X *ChipMinorFeatures1=%08x",
+ *ChipModel, *ChipRevision, *ChipFeatures,
+ *ChipMinorFeatures0, *ChipMinorFeatures1);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_GetChipSpecs(
+ IN gckHARDWARE Hardware
+ )
+{
+ gctUINT32 streamCount = 0;
+ gctUINT32 registerMax = 0;
+ gctUINT32 threadCount = 0;
+ gctUINT32 shaderCoreCount = 0;
+ gctUINT32 vertexCacheSize = 0;
+ gctUINT32 vertexOutputBufferSize = 0;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ if (((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
+ {
+ gctUINT32 specs;
+
+ /* Read gcChipSpecs register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os, 0x00048, &specs));
+
+ /* Handy macro to improve reading. */
+#define gcmSPEC_FIELD(field) \
+ ( ((((gctUINT32) (specs)) >> (0 ? GC_CHIP_SPECS_field)) & ((gctUINT32) ((((1 ? GC_CHIP_SPECS_field) - (0 ? GC_CHIP_SPECS_field) + 1) == 32) ? ~0 : (~(~0 << ((1 ? GC_CHIP_SPECS_field) - (0 ? GC_CHIP_SPECS_field) + 1)))))) )
+
+ /* Extract the fields. */
+ streamCount = ( ((((gctUINT32) (specs)) >> (0 ? 3:0)) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1)))))) );
+ registerMax = ( ((((gctUINT32) (specs)) >> (0 ? 7:4)) & ((gctUINT32) ((((1 ? 7:4) - (0 ? 7:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:4) - (0 ? 7:4) + 1)))))) );
+ threadCount = ( ((((gctUINT32) (specs)) >> (0 ? 11:8)) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1)))))) );
+ shaderCoreCount = ( ((((gctUINT32) (specs)) >> (0 ? 24:20)) & ((gctUINT32) ((((1 ? 24:20) - (0 ? 24:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:20) - (0 ? 24:20) + 1)))))) );
+ vertexCacheSize = ( ((((gctUINT32) (specs)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
+ vertexOutputBufferSize = ( ((((gctUINT32) (specs)) >> (0 ? 31:28)) & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1)))))) );
+ }
+
+ /* Get the stream count. */
+ Hardware->streamCount = (streamCount != 0)
+ ? streamCount
+ : (Hardware->chipModel >= gcv1000) ? 4 : 1;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: streamCount=%u%s",
+ Hardware->streamCount,
+ (streamCount == 0) ? " (default)" : "");
+
+ /* Get the vertex output buffer size. */
+ Hardware->vertexOutputBufferSize = (vertexOutputBufferSize != 0)
+ ? 1 << vertexOutputBufferSize
+ : (Hardware->chipModel == gcv400)
+ ? (Hardware->chipRevision < 0x4000) ? 512
+ : (Hardware->chipRevision < 0x4200) ? 256
+ : 128
+ : (Hardware->chipModel == gcv530)
+ ? (Hardware->chipRevision < 0x4200) ? 512
+ : 128
+ : 512;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: vertexOutputBufferSize=%u%s",
+ Hardware->vertexOutputBufferSize,
+ (vertexOutputBufferSize == 0) ? " (default)" : "");
+
+ /* Get the maximum number of threads. */
+ Hardware->threadCount = (threadCount != 0)
+ ? 1 << threadCount
+ : (Hardware->chipModel == gcv400) ? 64
+ : (Hardware->chipModel == gcv500) ? 128
+ : (Hardware->chipModel == gcv530) ? 128
+ : 256;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: threadCount=%u%s",
+ Hardware->threadCount,
+ (threadCount == 0) ? " (default)" : "");
+
+ /* Get the number of shader cores. */
+ Hardware->shaderCoreCount = (shaderCoreCount != 0)
+ ? shaderCoreCount
+ : (Hardware->chipModel >= gcv1000) ? 2
+ : 1;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: shaderCoreCount=%u%s",
+ Hardware->shaderCoreCount,
+ (shaderCoreCount == 0) ? " (default)" : "");
+
+ /* Get the vertex cache size. */
+ Hardware->vertexCacheSize = (vertexCacheSize != 0)
+ ? vertexCacheSize
+ : 8;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: vertexCacheSize=%u%s",
+ Hardware->vertexCacheSize,
+ (vertexCacheSize == 0) ? " (default)" : "");
+
+ /* Get the maximum number of temporary registers. */
+ Hardware->registerMax = (registerMax != 0)
+ ? 1 << registerMax
+ : (Hardware->chipModel == gcv400) ? 32
+ : 64;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Specs: registerMax=%u%s",
+ Hardware->registerMax,
+ (registerMax == 0) ? " (default)" : "");
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/******************************************************************************\
+****************************** gckHARDWARE API code *****************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHARDWARE_Construct
+**
+** Construct a new gckHARDWARE object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an initialized gckOS object.
+**
+** OUTPUT:
+**
+** gckHARDWARE * Hardware
+** Pointer to a variable that will hold the pointer to the gckHARDWARE
+** object.
+*/
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckHARDWARE * Hardware
+ )
+{
+ gckHARDWARE hardware = gcvNULL;
+ gceSTATUS status;
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures0;
+ gctUINT32 chipMinorFeatures1;
+ gctUINT16 data = 0xff00;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
+
+ /* Identify the hardware. */
+ gcmkONERROR(_IdentifyHardware(Os,
+ &chipModel,
+ &chipRevision,
+ &chipFeatures,
+ &chipMinorFeatures0,
+ &chipMinorFeatures1));
+
+ /* Allocate the gckHARDWARE object. */
+ gcmkONERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckHARDWARE),
+ (gctPOINTER *) &hardware));
+
+ /* Initialize the gckHARDWARE object. */
+ hardware->object.type = gcvOBJ_HARDWARE;
+ hardware->os = Os;
+
+ /* Set chip identity. */
+ hardware->chipModel = chipModel;
+ hardware->chipRevision = chipRevision;
+ hardware->chipFeatures = chipFeatures;
+ hardware->chipMinorFeatures0 = chipMinorFeatures0;
+ hardware->chipMinorFeatures1 = chipMinorFeatures1;
+ hardware->powerBaseAddress = ( (chipModel == gcv300)
+ && (chipRevision < 0x2000)
+ ) ? 0x100 : 0x00;
+ hardware->powerMutex = gcvNULL;
+
+ /* Get chip specs. */
+ gcmkONERROR(_GetChipSpecs(hardware));
+
+ /* Determine whether bug fixes #1 are present. */
+ hardware->extraEventStates = ((((gctUINT32) (chipMinorFeatures1)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
+
+ /* Check if big endian */
+ hardware->bigEndian = (*(gctUINT8 *)&data == 0xff);
+
+ /* Initialize the fast clear. */
+ gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
+
+ /* Set power state to ON. */
+ hardware->chipPowerState = gcvPOWER_ON;
+ hardware->lastWaitLink = ~0U;
+
+ gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
+
+ /* Return pointer to the gckHARDWARE object. */
+ *Hardware = hardware;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (hardware->powerMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
+ }
+
+ if (hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Free(Os, hardware));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Destroy
+**
+** Destroy an gckHARDWARE object.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Destroy(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Destroy the power mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
+
+ /* Mark the object as unknown. */
+ Hardware->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the object. */
+ gcmkONERROR(gckOS_Free(Hardware->os, Hardware));
+
+ /* Success. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_InitializeHardware
+**
+** Initialize the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 baseAddress;
+ gctUINT32 chipRev;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Read the chip revision register. */
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os,
+ 0x00024,
+ &chipRev));
+
+ if (chipRev != Hardware->chipRevision)
+ {
+ /* Chip is not there! */
+ gcmkONERROR(gcvSTATUS_CONTEXT_LOSSED);
+ }
+
+ /* Disable isolate GPU bit. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ ((((gctUINT32) (0x00000100)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)))));
+
+ /* Reset memory counters. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x0003C,
+ ~0U));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x0003C,
+ 0));
+
+ /* Get the system's physical base address. */
+ gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+ /* Program the base addesses. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x0041C,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00418,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00420,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00428,
+ baseAddress));
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ 0x00424,
+ baseAddress));
+
+#if !VIVANTE_PROFILER && 1
+ {
+ gctUINT32 data;
+
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os,
+ Hardware->powerBaseAddress +
+ 0x00100,
+ &data));
+
+ /* Enable clock gating. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+
+ if ((Hardware->chipRevision == 0x4301)
+ || (Hardware->chipRevision == 0x4302)
+ )
+ {
+ /* Disable stall module level clock gating for 4.3.0.1 and 4.3.0.2
+ ** revisions. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
+ }
+
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os,
+ Hardware->powerBaseAddress
+ + 0x00100,
+ data));
+
+ /* Disable PE clock gating on revs < 5.0 when HZ is present without a
+ ** bug fix. */
+ if ((Hardware->chipRevision < 0x5000)
+ && ((((gctUINT32) (Hardware->chipMinorFeatures1)) >> (0 ? 9:9) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))))
+ && ((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))))
+ )
+ {
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ &data));
+
+ /* Disable PE clock gating. */
+ data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)));
+
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ Hardware->powerBaseAddress
+ + 0x00104,
+ data));
+ }
+ }
+#endif
+
+ /* Test if MMU is initialized. */
+ if ((Hardware->kernel != gcvNULL)
+ && (Hardware->kernel->mmu != gcvNULL)
+ )
+ {
+ /* Reset MMU. */
+ gcmkONERROR(
+ gckHARDWARE_SetMMU(Hardware,
+ Hardware->kernel->mmu->pageTableLogical));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryMemory
+**
+** Query the amount of memory available on the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * InternalSize
+** Pointer to a variable that will hold the size of the internal video
+** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
+** internal memory will be returned.
+**
+** gctUINT32 * InternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * InternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the internal video memory. This pointer cannot be gcvNULL if
+** 'InternalSize' is also non-gcvNULL.
+**
+** gctSIZE_T * ExternalSize
+** Pointer to a variable that will hold the size of the external video
+** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
+** external memory will be returned.
+**
+** gctUINT32 * ExternalBaseAddress
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * ExternalAlignment
+** Pointer to a variable that will hold the hardware's base address for
+** the external video memory. This pointer cannot be gcvNULL if
+** 'ExternalSize' is also non-gcvNULL.
+**
+** gctUINT32 * HorizontalTileSize
+** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
+** gcvNULL, no horizontal pixel per tile will be returned.
+**
+** gctUINT32 * VerticalTileSize
+** Number of vertical pixels per tile. If 'VerticalTileSize' is
+** gcvNULL, no vertical pixel per tile will be returned.
+*/
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (InternalSize != gcvNULL)
+ {
+ /* No internal memory. */
+ *InternalSize = 0;
+ }
+
+ if (ExternalSize != gcvNULL)
+ {
+ /* No external memory. */
+ *ExternalSize = 0;
+ }
+
+ if (HorizontalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *HorizontalTileSize = 4;
+ }
+
+ if (VerticalTileSize != gcvNULL)
+ {
+ /* 4x4 tiles. */
+ *VerticalTileSize = 4;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*InternalSize=%lu *InternalBaseAddress=0x%08x "
+ "*InternalAlignment=0x%08x *ExternalSize=%lu "
+ "*ExternalBaseAddress=0x%08x *ExtenalAlignment=0x%08x "
+ "*HorizontalTileSize=%u *VerticalTileSize=%u",
+ gcmOPT_VALUE(InternalSize),
+ gcmOPT_VALUE(InternalBaseAddress),
+ gcmOPT_VALUE(InternalAlignment),
+ gcmOPT_VALUE(ExternalSize),
+ gcmOPT_VALUE(ExternalBaseAddress),
+ gcmOPT_VALUE(ExternalAlignment),
+ gcmOPT_VALUE(HorizontalTileSize),
+ gcmOPT_VALUE(VerticalTileSize));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryChipIdentity
+**
+** Query the identity of the hardware.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gceCHIPMODEL * ChipModel
+** If 'ChipModel' is not gcvNULL, the variable it points to will
+** receive the model of the chip.
+**
+** gctUINT32 * ChipRevision
+** If 'ChipRevision' is not gcvNULL, the variable it points to will
+** receive the revision of the chip.
+**
+** gctUINT32 * ChipFeatures
+** If 'ChipFeatures' is not gcvNULL, the variable it points to will
+** receive the feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures
+** If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
+** will receive the minor feature set of the chip.
+**
+** gctUINT32 * ChipMinorFeatures1
+** If 'ChipMinorFeatures1' is not gcvNULL, the variable it points to
+** will receive the minor feature set 1 of the chip.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPMODEL * ChipModel,
+ OUT gctUINT32 * ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures1
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Return chip model. */
+ if (ChipModel != gcvNULL)
+ {
+ *ChipModel = Hardware->chipModel;
+ }
+
+ /* Return revision number. */
+ if (ChipRevision != gcvNULL)
+ {
+ *ChipRevision = Hardware->chipRevision;
+ }
+
+ /* Return feature set. */
+ if (ChipFeatures != gcvNULL)
+ {
+ gctUINT32 features = Hardware->chipFeatures;
+
+ if (( ((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ /* Override fast clear by command line. */
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
+ }
+
+ if (( ((((gctUINT32) (features)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ))
+ {
+ /* Override compression by command line. */
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (Hardware->allowCompression) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
+ }
+
+ /* Mark 2D pipe as available for GC500.0 through GC500.2 and GC300,
+ ** since they did not have this bit. */
+ if (( (Hardware->chipModel == gcv500)
+ && (Hardware->chipRevision <= 2)
+ )
+ || (Hardware->chipModel == gcv300)
+ )
+ {
+ features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
+ }
+
+ *ChipFeatures = features;
+ }
+
+ /* Return minor feature set. */
+ if (ChipMinorFeatures != gcvNULL)
+ {
+ *ChipMinorFeatures = Hardware->chipMinorFeatures0;
+ }
+
+ /* Return minor feature set 1. */
+ if (ChipMinorFeatures1 != gcvNULL)
+ {
+ *ChipMinorFeatures1 = Hardware->chipMinorFeatures1;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ChipModel=0x%x *ChipRevision=0x%x *ChipFeatures=0x%08x "
+ "*ChipMinorFeatures=0x%08x *ChipMinorFeatures1=0x%08x",
+ gcmOPT_VALUE(ChipModel), gcmOPT_VALUE(ChipRevision),
+ gcmOPT_VALUE(ChipFeatures), gcmOPT_VALUE(ChipMinorFeatures),
+ gcmOPT_VALUE(ChipMinorFeatures1));
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_QueryChipSpecs(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR StreamCount,
+ OUT gctUINT32_PTR RegisterMax,
+ OUT gctUINT32_PTR ThreadCount,
+ OUT gctUINT32_PTR ShaderCoreCount,
+ OUT gctUINT32_PTR VertexCacheSize,
+ OUT gctUINT32_PTR VertexOutputBufferSize
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Return the number of streams. */
+ if (StreamCount != gcvNULL)
+ {
+ *StreamCount = Hardware->streamCount;
+ }
+
+ /* Return the number of temporary registers. */
+ if (RegisterMax != gcvNULL)
+ {
+ *RegisterMax = Hardware->registerMax;
+ }
+
+ /* Return the maximum number of thrteads. */
+ if (ThreadCount != gcvNULL)
+ {
+ *ThreadCount = Hardware->threadCount;
+ }
+
+ /* Return the number of shader cores. */
+ if (ShaderCoreCount != gcvNULL)
+ {
+ *ShaderCoreCount = Hardware->shaderCoreCount;
+ }
+
+ /* Return the number of entries in the vertex cache. */
+ if (VertexCacheSize != gcvNULL)
+ {
+ *VertexCacheSize = Hardware->vertexCacheSize;
+ }
+
+ /* Return the number of entries in the vertex output buffer. */
+ if (VertexOutputBufferSize != gcvNULL)
+ {
+ *VertexOutputBufferSize = Hardware->vertexOutputBufferSize;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*StreamCount=%u *RegisterMax=%u *ThreadCount=%u "
+ "*ShaderCoreCount=%u *VertexCacheSize=%u "
+ "*VertexOutputBufferSize=%u",
+ gcmOPT_VALUE(StreamCount), gcmOPT_VALUE(RegisterMax),
+ gcmOPT_VALUE(ThreadCount), gcmOPT_VALUE(ShaderCoreCount),
+ gcmOPT_VALUE(VertexCacheSize),
+ gcmOPT_VALUE(VertexOutputBufferSize));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertFormat
+**
+** Convert an API format to hardware parameters.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gceSURF_FORMAT Format
+** API format to convert.
+**
+** OUTPUT:
+**
+** gctUINT32 * BitsPerPixel
+** Pointer to a variable that will hold the number of bits per pixel.
+**
+** gctUINT32 * BytesPerTile
+** Pointer to a variable that will hold the number of bytes per tile.
+*/
+gceSTATUS
+gckHARDWARE_ConvertFormat(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ )
+{
+ gctUINT32 bitsPerPixel;
+ gctUINT32 bytesPerTile;
+
+ gcmkHEADER_ARG("Hardware=0x%x Format=%d", Hardware, Format);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Dispatch on format. */
+ switch (Format)
+ {
+ case gcvSURF_INDEX8:
+ case gcvSURF_A8:
+ case gcvSURF_L8:
+ /* 8-bpp format. */
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_YV12:
+ case gcvSURF_I420:
+ case gcvSURF_NV12:
+ case gcvSURF_NV21:
+ /* 12-bpp planar YUV formats. */
+ bitsPerPixel = 12;
+ bytesPerTile = (12 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_A8L8:
+ case gcvSURF_X4R4G4B4:
+ case gcvSURF_A4R4G4B4:
+ case gcvSURF_X1R5G5B5:
+ case gcvSURF_A1R5G5B5:
+ case gcvSURF_R5G5B5X1:
+ case gcvSURF_R4G4B4X4:
+ case gcvSURF_X4B4G4R4:
+ case gcvSURF_X1B5G5R5:
+ case gcvSURF_B4G4R4X4:
+ case gcvSURF_R5G6B5:
+ case gcvSURF_B5G5R5X1:
+ case gcvSURF_YUY2:
+ case gcvSURF_UYVY:
+ case gcvSURF_YVYU:
+ case gcvSURF_VYUY:
+ case gcvSURF_NV16:
+ case gcvSURF_NV61:
+ case gcvSURF_D16:
+ /* 16-bpp format. */
+ bitsPerPixel = 16;
+ bytesPerTile = (16 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_X8R8G8B8:
+ case gcvSURF_A8R8G8B8:
+ case gcvSURF_X8B8G8R8:
+ case gcvSURF_A8B8G8R8:
+ case gcvSURF_R8G8B8X8:
+ case gcvSURF_D32:
+ /* 32-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_D24S8:
+ case gcvSURF_D24X8:
+ /* 24-bpp format. */
+ bitsPerPixel = 32;
+ bytesPerTile = (32 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT1:
+ case gcvSURF_ETC1:
+ bitsPerPixel = 4;
+ bytesPerTile = (4 * 4 * 4) / 8;
+ break;
+
+ case gcvSURF_DXT2:
+ case gcvSURF_DXT3:
+ case gcvSURF_DXT4:
+ case gcvSURF_DXT5:
+ bitsPerPixel = 8;
+ bytesPerTile = (8 * 4 * 4) / 8;
+ break;
+
+ default:
+ /* Invalid format. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Set the result. */
+ if (BitsPerPixel != gcvNULL)
+ {
+ * BitsPerPixel = bitsPerPixel;
+ }
+
+ if (BytesPerTile != gcvNULL)
+ {
+ * BytesPerTile = bytesPerTile;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BitsPerPixel=%u *BytesPerTile=%u",
+ gcmOPT_VALUE(BitsPerPixel), gcmOPT_VALUE(BytesPerTile));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SplitMemory
+**
+** Split a hardware specific memory address into a pool and offset.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctUINT32 Address
+** Address in hardware specific format.
+**
+** OUTPUT:
+**
+** gcePOOL * Pool
+** Pointer to a variable that will hold the pool type for the address.
+**
+** gctUINT32 * Offset
+** Pointer to a variable that will hold the offset for the address.
+*/
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Addres=%08x", Hardware, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
+
+ /* Dispatch on memory type. */
+ switch (( ((((gctUINT32) (Address)) >> (0 ? 31:31)) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) ))
+ {
+ case 0x0:
+ /* System memory. */
+ *Pool = gcvPOOL_SYSTEM;
+ break;
+
+ case 0x1:
+ /* Virtual memory. */
+ *Pool = gcvPOOL_VIRTUAL;
+ break;
+
+ default:
+ /* Invalid memory type. */
+ gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Return offset of address. */
+ *Offset = ( ((((gctUINT32) (Address)) >> (0 ? 30:0)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1)))))) );
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Pool=%d *Offset=%08x", *Pool, *Offset);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Execute
+**
+** Kickstart the hardware's command processor with an initialized command
+** buffer.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of command buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes for the prefetch unit (until after the first LINK).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+#ifdef __QNXNTO__
+ IN gctPOINTER Physical,
+ IN gctBOOL PhysicalAddresses,
+#endif
+ IN gctSIZE_T Bytes
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0, control;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Bytes=%lu",
+ Hardware, Logical, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+#ifdef __QNXNTO__
+ if (PhysicalAddresses)
+ {
+ /* Convert physical into hardware specific address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertPhysical(Hardware, Physical, &address));
+ }
+ else
+ {
+#endif
+ /* Convert logical into hardware specific address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
+#ifdef __QNXNTO__
+ }
+#endif
+
+ /* Enable all events. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00014, ~0U));
+
+ /* Write address register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00654, address));
+
+ /* Build control register. */
+ control = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) ((Bytes+7)>>3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ /* Set big endian */
+ if (Hardware->bigEndian)
+ {
+ control |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 21:20) - (0 ? 21:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:20) - (0 ? 21:20) + 1))))))) << (0 ? 21:20)));
+ }
+
+ /* Write control register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00658, control));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Started command buffer @ %08x",
+ address);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_WaitLink
+**
+** Append a WAIT/LINK command sequence at the specified location in the command
+** queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** WAIT/LINK command sequence at or gcvNULL just to query the size of the
+** WAIT/LINK command sequence.
+**
+** gctUINT32 Offset
+** Offset into command buffer required for alignment.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the WAIT/LINK command
+** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** by the WAIT/LINK command sequence. If 'Bytes' is gcvNULL, nothing will
+** be returned.
+**
+** gctPOINTER * Wait
+** Pointer to a variable that will receive the pointer to the WAIT
+** command. If 'Wait' is gcvNULL nothing will be returned.
+**
+** gctSIZE_T * WaitSize
+** Pointer to a variable that will receive the number of bytes used by
+** the WAIT command. If 'LinkSize' is gcvNULL nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPOINTER * Wait,
+ OUT gctSIZE_T * WaitSize
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gctSIZE_T bytes;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=%08x *Bytes=%lu",
+ Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ /* Compute number of bytes required. */
+ bytes = gcmALIGN(Offset + 16, 8) - Offset;
+
+ if (Logical != gcvNULL)
+ {
+ /* Convert logical into hardware specific address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware,
+ Logical,
+ &address));
+
+ if (*Bytes < bytes)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append WAIT(200). */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (200) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: WAIT", address);
+
+ /* Append LINK(2, address). */
+ logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes>>3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ logical[3] = address;
+
+ Hardware->lastWaitLink = address;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: LINK %08x, #%lu",
+ address + 8, address, bytes);
+
+ if (Wait != gcvNULL)
+ {
+ /* Return pointer to WAIT command. */
+ *Wait = Logical;
+ }
+
+ if (WaitSize != gcvNULL)
+ {
+ /* Return number of bytes used by the WAIT command. */
+ *WaitSize = 8;
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the WAIT/LINK command
+ ** sequence. */
+ *Bytes = bytes;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu *Wait=0x%x *WaitSize=%lu",
+ gcmOPT_VALUE(Bytes), gcmOPT_POINTER(Wait),
+ gcmOPT_VALUE(WaitSize));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_End
+**
+** Append an END command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** END command at or gcvNULL just to query the size of the END command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the END command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the END command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append END. */
+ logical[0] =
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x02 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
+
+ /* Make sure the CPU writes out the data to memory. */
+ gcmkVERIFY_OK(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the END command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Nop
+**
+** Append a NOP command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** NOP command at or gcvNULL just to query the size of the NOP command.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the NOP command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
+ Hardware, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append NOP. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x03 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the NOP command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Wait
+**
+** Append a WAIT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** WAIT command at or gcvNULL just to query the size of the WAIT command.
+**
+** gctUINT32 Count
+** Number of cycles to wait.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the WAIT command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Wait(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Count,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Count=%u *Bytes=%lu",
+ Hardware, Logical, Count, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append WAIT. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: WAIT %u", Logical, Count);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the WAIT command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Event
+**
+** Append an EVENT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the EVENT command at or gcvNULL just to query the size of the EVENT
+** command.
+**
+** gctUINT8 Event
+** Event ID to program.
+**
+** gceKERNEL_WHERE FromWhere
+** Location of the pipe to send the event.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the EVENT command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the EVENT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT size;
+ gctUINT32 destination = 0;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
+ Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+ gcmkVERIFY_ARGUMENT(Event < 32);
+
+ /* Determine the size of the command. */
+ size = (Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL))
+ ? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
+ : 8;
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < size)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ switch (FromWhere)
+ {
+ case gcvKERNEL_COMMAND:
+ /* From command processor. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) (0x1&((gctUINT32)((((1?5:5)-(0?5:5)+1)==32)?~0:(~(~0<<((1?5:5)-(0?5:5)+1)))))))<<(0?5:5)));
+ break;
+
+ case gcvKERNEL_PIXEL:
+ /* From pixel engine. */
+ destination = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1&((gctUINT32)((((1?6:6)-(0?6:6)+1)==32)?~0:(~(~0<<((1?6:6)-(0?6:6)+1)))))))<<(0?6:6)));
+ break;
+
+ default:
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Append EVENT(Event, destiantion). */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E01) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1] = ((((gctUINT32) (destination)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (Event) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
+
+ /* Make sure the event ID gets written out before GPU can access it. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+#if gcdDEBUG
+ {
+ gctUINT32 phys;
+ gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: EVENT %d", phys, Event);
+ }
+#endif
+
+ /* Append the extra states. These are needed for the chips that do not
+ ** support back-to-back events due to the async interface. The extra
+ ** states add the necessary delay to ensure that event IDs do not
+ ** collide. */
+ if (size > 8)
+ {
+ logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0100) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+ logical[3] = 0;
+ logical[4] = 0;
+ logical[5] = 0;
+ logical[6] = 0;
+ logical[7] = 0;
+ }
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the EVENT command. */
+ *Bytes = size;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_PipeSelect
+**
+** Append a PIPESELECT command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the PIPESELECT command at or gcvNULL just to query the size of the
+** PIPESELECT command.
+**
+** gctUINT32 Pipe
+** Pipe value to select.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the PIPESELECT command.
+** If 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the PIPESELECT command. If 'Bytes' is gcvNULL, nothing will be
+** returned.
+*/
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pipe,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%u *Bytes=%lu",
+ Hardware, Logical, Pipe, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ /* Append a PipeSelect. */
+ if (Logical != gcvNULL)
+ {
+ gctUINT32 flush, stall;
+
+ if (*Bytes < 32)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ flush = (Pipe == 0x1)
+ ? ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1&((gctUINT32)((((1?1:1)-(0?1:1)+1)==32)?~0:(~(~0<<((1?1:1)-(0?1:1)+1)))))))<<(0?1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1&((gctUINT32)((((1?0:0)-(0?0:0)+1)==32)?~0:(~(~0<<((1?0:0)-(0?0:0)+1)))))))<<(0?0:0)))
+ : ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1&((gctUINT32)((((1?3:3)-(0?3:3)+1)==32)?~0:(~(~0<<((1?3:3)-(0?3:3)+1)))))))<<(0?3:3)));
+
+ stall = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));
+
+ /* LoadState(AQFlush, 1), flush. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1] = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH %x", logical, flush);
+
+ /* LoadState(AQSempahore, 1), stall. */
+ logical[2] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[3] = stall;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: SEMAPHORE %x", logical + 2, stall);
+
+ /* Stall, stall. */
+ logical[4] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)));
+
+ logical[5] = stall;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: STALL %x", logical + 4, stall);
+
+ /* LoadState(AQPipeSelect, 1), pipe. */
+ logical[6] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E00) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[7] = Pipe;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: PIPE %u", logical + 6, Pipe);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the PIPESELECT command. */
+ *Bytes = 32;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Link
+**
+** Append a LINK command at the specified location in the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Pointer to the current location inside the command queue to append
+** the LINK command at or gcvNULL just to query the size of the LINK
+** command.
+**
+** gctPOINTER FetchAddress
+** Logical address of destination of LINK.
+**
+** gctSIZE_T FetchSize
+** Number of bytes in destination of LINK.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes available for the LINK command. If
+** 'Logical' is gcvNULL, this argument will be ignored.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that will receive the number of bytes required
+** for the LINK command. If 'Bytes' is gcvNULL, nothing will be returned.
+*/
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctPOINTER FetchAddress,
+ IN gctSIZE_T FetchSize,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gctUINT32 address;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x FetchAddress=0x%x FetchSize=%lu "
+ "*Bytes=%lu",
+ Hardware, Logical, FetchAddress, FetchSize,
+ gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
+
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Convert logical address to hardware address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware, FetchAddress, &address));
+
+ logical[1] = address;
+
+ /* Make sure the address got written before the LINK command. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical + 1));
+
+ /* Compute number of 64-byte aligned bytes to fetch. */
+ bytes = gcmALIGN(address + FetchSize, 64) - address;
+
+ /* Append LINK(bytes / 8), FetchAddress. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes>>3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+
+#if gcdDEBUG
+ {
+ gctUINT32 phys;
+ gckHARDWARE_ConvertLogical(Hardware, Logical, &phys);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%08x: LINK %08x, #%lu", phys, address, bytes);
+ }
+#endif
+
+ /* Memory barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, logical));
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* Return number of bytes required by the LINK command. */
+ *Bytes = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_AlignToTile
+**
+** Align the specified width and height to tile boundaries.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gceSURF_TYPE Type
+** Type of alignment.
+**
+** gctUINT32 * Width
+** Pointer to the width to be aligned. If 'Width' is gcvNULL, no width
+** will be aligned.
+**
+** gctUINT32 * Height
+** Pointer to the height to be aligned. If 'Height' is gcvNULL, no height
+** will be aligned.
+**
+** OUTPUT:
+**
+** gctUINT32 * Width
+** Pointer to a variable that will receive the aligned width.
+**
+** gctUINT32 * Height
+** Pointer to a variable that will receive the aligned height.
+**
+** gctBOOL_PTR SuperTiled
+** Pointer to a variable that receives the super-tiling flag for the
+** surface.
+*/
+gceSTATUS
+gckHARDWARE_AlignToTile(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height,
+ OUT gctBOOL_PTR SuperTiled
+ )
+{
+ gctBOOL superTiled = gcvFALSE;
+ gctUINT32 xAlignment, yAlignment;
+
+ gcmkHEADER_ARG("Hardware=0x%x Type=%d *Width=%u *Height=%u",
+ Hardware, Type, gcmOPT_VALUE(Width), gcmOPT_VALUE(Height));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Super tiling can be enabled for render targets and depth buffers. */
+ superTiled =
+ ( (Type == gcvSURF_RENDER_TARGET)
+ || (Type == gcvSURF_DEPTH)
+ )
+ &&
+ /* Of course, hardware needs to support super tiles. */
+ ((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 12:12) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1)))))));
+
+ /* Compute alignment factors. */
+ xAlignment = superTiled ? 64
+ : (Type == gcvSURF_TEXTURE) ? 4
+ : 16;
+ yAlignment = superTiled ? 64 : 4;
+
+ if (Width != gcvNULL)
+ {
+ /* Align the width. */
+ *Width = gcmALIGN(*Width, xAlignment);
+ }
+
+ if (Height != gcvNULL)
+ {
+ /* Align the height. */
+ *Height = gcmALIGN(*Height, yAlignment);
+ }
+
+ if (SuperTiled != gcvNULL)
+ {
+ /* Copy the super tiling. */
+ *SuperTiled = superTiled;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Width=%u *Height=%u *SuperTiled=%d",
+ gcmOPT_VALUE(Width), gcmOPT_VALUE(Height),
+ gcmOPT_VALUE(SuperTiled));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_UpdateQueueTail
+**
+** Update the tail of the command queue.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the start of the command queue.
+**
+** gctUINT32 Offset
+** Offset into the command queue of the tail (last command).
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=%08x",
+ Hardware, Logical, Offset);
+
+ /* Verify the hardware. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Force a barrier. */
+ gcmkONERROR(
+ gckOS_MemoryBarrier(Hardware->os, Logical));
+
+ /* Notify gckKERNEL object of change. */
+ gcmkONERROR(
+ gckKERNEL_Notify(Hardware->kernel,
+ gcvNOTIFY_COMMAND_QUEUE,
+ gcvFALSE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertLogical
+**
+** Convert a logical system address into a hardware specific address.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address to convert.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Convert logical address into a physical address. */
+ gcmkONERROR(
+ gckOS_GetPhysicalAddress(Hardware->os, Logical, &address));
+
+ /* Return hardware specific address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_ConvertPhysical
+**
+** Convert a physical address into a hardware specific address.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctPHYS_ADDR Physical
+** Physical address to convert.
+**
+** gctUINT32* Address
+** Return hardware specific address.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ConvertPhysical(
+ IN gckHARDWARE Hardware,
+ IN gctPHYS_ADDR Physical,
+ OUT gctUINT32 * Address
+ )
+{
+ gctUINT32 address;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ address = (gctUINT32)Physical;
+
+ /* Return hardware specific address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (address) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+ /* Return the status. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_Interrupt
+**
+** Process an interrupt.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** gctBOOL InterruptValid
+** If gcvTRUE, this function will read the interrupt acknowledge
+** register, stores the data, and return whether or not the interrupt
+** is ours or not. If gcvFALSE, this functions will read the interrupt
+** acknowledge register and combine it with any stored value to handle
+** the event notifications.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL InterruptValid
+ )
+{
+ gckEVENT event;
+ gctUINT32 data;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Extract gckEVENT object. */
+ event = Hardware->kernel->event;
+ gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+ if (InterruptValid)
+ {
+ /* Read AQIntrAcknowledge register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00010,
+ &data));
+
+#if gcdDEBUG
+ if (data & 0x80000000)
+ {
+ gcmkONERROR(gckOS_Broadcast(Hardware->os,
+ Hardware,
+ gcvBROADCAST_AXI_BUS_ERROR));
+ }
+#endif
+
+ if (data == 0)
+ {
+ /* Not our interrupt. */
+ status = gcvSTATUS_NOT_OUR_INTERRUPT;
+ }
+ else
+ {
+ /* Inform gckEVENT of the interrupt. */
+ status = gckEVENT_Interrupt(event, data & 0x7FFFFFFF);
+ }
+ }
+ else
+ {
+ /* Handle events. */
+ status = gckEVENT_Notify(event, 0);
+ }
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryCommandBuffer
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Alignment
+** Pointer to a variable receiving the alignment for each command.
+**
+** gctSIZE_T * ReservedHead
+** Pointer to a variable receiving the number of reserved bytes at the
+** head of each command buffer.
+**
+** gctSIZE_T * ReservedTail
+** Pointer to a variable receiving the number of bytes reserved at the
+** tail of each command buffer.
+*/
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * Alignment,
+ OUT gctSIZE_T * ReservedHead,
+ OUT gctSIZE_T * ReservedTail
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Alignment != gcvNULL)
+ {
+ /* Align every 8 bytes. */
+ *Alignment = 8;
+ }
+
+ if (ReservedHead != gcvNULL)
+ {
+ /* Reserve space for SelectPipe(). */
+ *ReservedHead = 32;
+ }
+
+ if (ReservedTail != gcvNULL)
+ {
+ /* Reserve space for Link(). */
+ *ReservedTail = 8;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Alignment=%lu *ReservedHead=%lu *ReservedTail=%lu",
+ gcmOPT_VALUE(Alignment), gcmOPT_VALUE(ReservedHead),
+ gcmOPT_VALUE(ReservedTail));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QuerySystemMemory
+**
+** Query the command buffer alignment and number of reserved bytes.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * SystemSize
+** Pointer to a variable that receives the maximum size of the system
+** memory.
+**
+** gctUINT32 * SystemBaseAddress
+** Poinetr to a variable that receives the base address for system
+** memory.
+*/
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (SystemSize != gcvNULL)
+ {
+ /* Maximum system memory can be 2GB. */
+ *SystemSize = 1U << 31;
+ }
+
+ if (SystemBaseAddress != gcvNULL)
+ {
+ /* Set system memory base address. */
+ *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*SystemSize=%lu *SystemBaseAddress=%lu",
+ gcmOPT_VALUE(SystemSize), gcmOPT_VALUE(SystemBaseAddress));
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetMMU
+**
+** Set the page table base address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctPOINTER Logical
+** Logical address of the page table.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ )
+{
+ gceSTATUS status;
+ gctUINT32 address = 0;
+ gctUINT32 baseAddress;
+
+ gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ /* Convert the logical address into an hardware address. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertLogical(Hardware, Logical, &address));
+
+ /* Also get the base address - we need a real physical address. */
+ gcmkONERROR(
+ gckOS_GetBaseAddress(Hardware->os, &baseAddress));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "Setting page table to 0x%08X",
+ address + baseAddress);
+
+ /* Write the AQMemoryFePageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00400,
+ address + baseAddress));
+
+ /* Write the AQMemoryRaPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00410,
+ address + baseAddress));
+
+ /* Write the AQMemoryTxPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00404,
+ address + baseAddress));
+
+ /* Write the AQMemoryPePageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00408,
+ address + baseAddress));
+
+ /* Write the AQMemoryPezPageTable register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x0040C,
+ address + baseAddress));
+
+ /* Return the status. */
+ gcmkFOOTER_NO();
+ return status;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_FlushMMU
+**
+** Flush the page table.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 flush;
+ gctUINT32_PTR buffer;
+ gctSIZE_T bufferSize;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Flush the memory controller. */
+ flush = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1&((gctUINT32)((((1?0:0)-(0?0:0)+1)==32)?~0:(~(~0<<((1?0:0)-(0?0:0)+1)))))))<<(0?0:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1&((gctUINT32)((((1?1:1)-(0?1:1)+1)==32)?~0:(~(~0<<((1?1:1)-(0?1:1)+1)))))))<<(0?1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1&((gctUINT32)((((1?2:2)-(0?2:2)+1)==32)?~0:(~(~0<<((1?2:2)-(0?2:2)+1)))))))<<(0?2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1&((gctUINT32)((((1?3:3)-(0?3:3)+1)==32)?~0:(~(~0<<((1?3:3)-(0?3:3)+1)))))))<<(0?3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1&((gctUINT32)((((1?4:4)-(0?4:4)+1)==32)?~0:(~(~0<<((1?4:4)-(0?4:4)+1)))))))<<(0?4:4)));
+
+ gcmkONERROR(
+ gckCOMMAND_Reserve(Hardware->kernel->command,
+ 8,
+ (gctPOINTER *) &buffer,
+ &bufferSize));
+
+ buffer[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ buffer[1] = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH MMU", buffer);
+
+ gcmkONERROR(
+ gckCOMMAND_Execute(Hardware->kernel->command, 8));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_BuildVirtualAddress
+**
+** Build a virtual address.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gctUINT32 Index
+** Index into page table.
+**
+** gctUINT32 Offset
+** Offset into page.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable receiving te hardware address.
+*/
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x Index=%u Offset=%u", Hardware, Index, Offset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /* Build virtual address. */
+ *Address = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1))))))) << (0 ? 31:31)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0))) | (((gctUINT32) ((gctUINT32) (Offset|(Index<<12)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1))))))) << (0 ? 30:0)));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_GetIdle(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle = 0;
+ gctINT retry, poll, pollCount;
+
+ gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+
+ /* If we have to wait, try 100 polls per millisecond. */
+ pollCount = Wait ? 100 : 1;
+
+ /* At most, try for 1 second. */
+ for (retry = 0; retry < 1000; ++retry)
+ {
+ /* If we have to wait, try 100 polls per millisecond. */
+ for (poll = pollCount; poll > 0; --poll)
+ {
+ /* Read register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os, 0x00004, &idle));
+
+ /* See if we have to wait for FE idle. */
+ if (( ((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ /* FE is idle. */
+ break;
+ }
+ }
+
+ /* Check if we need to wait for FE and FE is busy. */
+ if (Wait && !( ((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ /* Wait a little. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "%s: Waiting for idle: 0x%08X",
+ __FUNCTION__, idle);
+
+ gcmkVERIFY_OK(gckOS_Delay(Hardware->os, 1));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* Return idle to caller. */
+ *Data = idle;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=%08x", *Data);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ )
+{
+ gctUINT32 pipe;
+ gctUINT32 flush = 0;
+ gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Flush=%x Logical=0x%x *Bytes=%lu",
+ Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get current pipe. */
+ pipe = Hardware->kernel->command->pipeSelect;
+
+ /* Flush 3D color cache. */
+ if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1&((gctUINT32)((((1?1:1)-(0?1:1)+1)==32)?~0:(~(~0<<((1?1:1)-(0?1:1)+1)))))))<<(0?1:1)));
+ }
+
+ /* Flush 3D depth cache. */
+ if ((Flush & gcvFLUSH_DEPTH) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1&((gctUINT32)((((1?0:0)-(0?0:0)+1)==32)?~0:(~(~0<<((1?0:0)-(0?0:0)+1)))))))<<(0?0:0)));
+ }
+
+ /* Flush 3D texture cache. */
+ if ((Flush & gcvFLUSH_TEXTURE) && (pipe == 0x0))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1&((gctUINT32)((((1?2:2)-(0?2:2)+1)==32)?~0:(~(~0<<((1?2:2)-(0?2:2)+1)))))))<<(0?2:2)));
+ }
+
+ /* Flush 2D cache. */
+ if ((Flush & gcvFLUSH_2D) && (pipe == 0x1))
+ {
+ flush |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1&((gctUINT32)((((1?3:3)-(0?3:3)+1)==32)?~0:(~(~0<<((1?3:3)-(0?3:3)+1)))))))<<(0?3:3)));
+ }
+
+ /* See if there is a valid flush. */
+ if (flush == 0)
+ {
+ if (Bytes != gcvNULL)
+ {
+ /* No bytes required. */
+ *Bytes = 0;
+ }
+ }
+
+ else
+ {
+ /* Copy to command queue. */
+ if (Logical != gcvNULL)
+ {
+ if (*Bytes < 8)
+ {
+ /* Command queue too small. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* Append LOAD_STATE to AQFlush. */
+ logical[0] = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+
+ logical[1] = flush;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "0x%x: FLUSH %x", logical, flush);
+ }
+
+ if (Bytes != gcvNULL)
+ {
+ /* 8 bytes required. */
+ *Bytes = 8;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ )
+{
+ gctUINT32 debug;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x Enable=%d Compression=%d",
+ Hardware, Enable, Compression);
+
+ /* Only process if fast clear is available. */
+ if (( ((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
+ {
+ if (Enable == -1)
+ {
+ /* Determine automatic value for fast clear. */
+ Enable = (Hardware->chipModel != gcv500)
+ | (Hardware->chipRevision >= 3);
+ }
+
+ if (Compression == -1)
+ {
+ /* Determine automatic value for compression. */
+ Compression = Enable
+ & ( ((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) );
+ }
+
+ /* Read AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os, 0x00414, &debug));
+
+ /* Set fast clear bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable==0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
+
+ /* Set copression bypass. */
+ debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21))) | (((gctUINT32) ((gctUINT32) (Compression==0) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))) << (0 ? 21:21)));
+
+ /* Write back AQMemoryDebug register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00414,
+ debug));
+
+ /* Store fast clear and comprersison flags. */
+ Hardware->allowFastClear = Enable;
+ Hardware->allowCompression = Compression;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
+ "FastClear=%d Compression=%d", Enable, Compression);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+typedef enum
+{
+ gcvPOWER_FLAG_INITIALIZE = 1 << 0,
+ gcvPOWER_FLAG_STALL = 1 << 1,
+ gcvPOWER_FLAG_STOP = 1 << 2,
+ gcvPOWER_FLAG_START = 1 << 3,
+ gcvPOWER_FLAG_RELEASE = 1 << 4,
+ gcvPOWER_FLAG_DELAY = 1 << 5,
+ gcvPOWER_FLAG_SAVE = 1 << 6,
+ gcvPOWER_FLAG_ACQUIRE = 1 << 7,
+ gcvPOWER_FLAG_OFF = 1 << 8,
+ gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
+}
+gcePOWER_FLAGS;
+
+/*******************************************************************************
+**
+** gckHARDWARE_SetPowerManagementState
+**
+** Set GPU to a specified power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ )
+{
+#if 0
+#if !gcdNO_POWER_MANAGEMENT
+ gceSTATUS status;
+ gckCOMMAND command = gcvNULL;
+ gckOS os;
+ gctUINT flag, clock;
+ gctPOINTER buffer;
+ gctSIZE_T bytes, requested;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL reserved = gcvFALSE;
+ gctBOOL mutexAcquired = gcvFALSE;
+ gctBOOL stall = gcvTRUE;
+ gctBOOL broadcast = gcvFALSE;
+ gctUINT32 process, thread;
+
+ /* State transition flags. */
+ static const gctUINT flags[4][4] =
+ {
+ /* gcvPOWER_ON */
+ { /* ON */ 0,
+ /* OFF */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL,
+ /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
+ gcvPOWER_FLAG_STALL |
+ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_OFF */
+ { /* ON */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* OFF */ 0,
+ /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY,
+ /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_IDLE */
+ { /* ON */ gcvPOWER_FLAG_RELEASE,
+ /* OFF */ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ 0,
+ /* SUSPEND */ gcvPOWER_FLAG_STOP |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ },
+
+ /* gcvPOWER_SUSPEND */
+ { /* ON */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_RELEASE |
+ gcvPOWER_FLAG_DELAY,
+ /* OFF */ gcvPOWER_FLAG_SAVE |
+ gcvPOWER_FLAG_OFF |
+ gcvPOWER_FLAG_CLOCK_OFF,
+ /* IDLE */ gcvPOWER_FLAG_START |
+ gcvPOWER_FLAG_DELAY,
+ /* SUSPEND */ 0,
+ },
+ };
+
+ /* Clocks. */
+ static const gctUINT clocks[4] =
+ {
+ /* gcvPOWER_ON */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (64) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ,
+ /* gcvPOWER_OFF */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ,
+ /* gcvPOWER_IDLE */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) ,
+ /* gcvPOWER_SUSPEND */
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))|
+ ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))), };
+
+ gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Get the gckOS object pointer. */
+ os = Hardware->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Convert the broadcast power state. */
+ switch (State)
+ {
+ case gcvPOWER_SUSPEND_ATPOWERON:
+ /* Convert to SUSPEND and don't wait for STALL. */
+ State = gcvPOWER_SUSPEND;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_OFF_ATPOWERON:
+ /* Convert to OFF and don't wait for STALL. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ break;
+
+ case gcvPOWER_IDLE_BROADCAST:
+ /* Convert to IDLE and note we are inside breoadcast. */
+ State = gcvPOWER_IDLE;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_SUSPEND_BROADCAST:
+ /* Convert to SUSPEND and note we are inside breoadcast. */
+ State = gcvPOWER_SUSPEND;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_BROADCAST:
+ /* Convert to OFF and note we are inside breoadcast. */
+ State = gcvPOWER_OFF;
+ broadcast = gcvTRUE;
+ break;
+
+ case gcvPOWER_OFF_RECOVERY:
+ /* Convert to OFF and note we are inside breoadcast. */
+ State = gcvPOWER_OFF;
+ stall = gcvFALSE;
+ broadcast = gcvTRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Get current process and thread IDs. */
+ gcmkONERROR(gckOS_GetProcessID(&process));
+ gcmkONERROR(gckOS_GetThreadID(&thread));
+
+ if (broadcast)
+ {
+ /* Try to acquire the power mutex. */
+ status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Check if we already own this mutex. */
+ if ((Hardware->powerProcess == process)
+ && (Hardware->powerThread == thread)
+ )
+ {
+ /* Bail out on recursive power management. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+ }
+ }
+ }
+ else
+ {
+ /* Acquire the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
+ }
+
+ Hardware->powerProcess = process;
+ Hardware->powerThread = thread;
+ mutexAcquired = gcvTRUE;
+
+ /* Grab control flags and clock. */
+ flag = flags[Hardware->chipPowerState][State];
+ clock = clocks[State];
+
+ if (flag == 0)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* No need to do anything. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ gcmkASSERT(Hardware->kernel != gcvNULL);
+ gcmkASSERT(Hardware->kernel->command != gcvNULL);
+ command = Hardware->kernel->command;
+
+ if (flag & gcvPOWER_FLAG_INITIALIZE)
+ {
+ /* Turn on the power. */
+ gcmkONERROR(gckOS_SetGPUPower(Hardware->os, gcvTRUE, gcvTRUE));
+ }
+
+ if ((flag & gcvPOWER_FLAG_STALL) && stall)
+ {
+ gctBOOL idle;
+ gctINT32 atomValue;
+
+ /* Check commit atom. */
+ gcmkONERROR(
+ gckOS_AtomGet(Hardware->os, command->atomCommit, &atomValue));
+
+ if (atomValue > 0)
+ {
+ /* Commits are pending - abort power management. */
+ status = broadcast ? gcvSTATUS_CHIP_NOT_READY
+ : gcvSTATUS_MORE_DATA;
+ goto OnError;
+ }
+
+ if (broadcast)
+ {
+ /* Check for idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Hardware, &idle));
+
+ if (!idle)
+ {
+ status = gcvSTATUS_CHIP_NOT_READY;
+ goto OnError;
+ }
+ }
+
+ else
+ {
+ /* Get the size of the flush command. */
+ gcmkONERROR(gckHARDWARE_Flush(Hardware,
+ gcvFLUSH_ALL,
+ gcvNULL,
+ &requested));
+
+ /* Reserve space in the command queue. */
+ gcmkONERROR(
+ gckCOMMAND_Reserve(command, requested, &buffer, &bytes));
+
+ reserved = gcvTRUE;
+
+ /* Append a flush. */
+ gcmkONERROR(gckHARDWARE_Flush(Hardware,
+ gcvFLUSH_ALL,
+ buffer,
+ &bytes));
+
+ /* Execute the command queue. */
+ acquired = gcvFALSE;
+ gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+ /* Wait to finish all commands. */
+ gcmkONERROR(gckCOMMAND_Stall(command));
+ }
+ }
+
+ if (flag & gcvPOWER_FLAG_ACQUIRE)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
+
+ acquired = gcvTRUE;
+ }
+
+ if (flag & gcvPOWER_FLAG_STOP)
+ {
+ /* Stop the command parser. */
+ gcmkONERROR(gckCOMMAND_Stop(command));
+ }
+
+ /* Write the clock control register. */
+ gcmkONERROR(gckOS_WriteRegister(os,
+ 0x00000,
+ clock));
+
+ /* Done loading the frequency scaler. */
+ gcmkONERROR(gckOS_WriteRegister(os,
+ 0x00000,
+ ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
+
+ if (flag & gcvPOWER_FLAG_DELAY)
+ {
+ /* Wait for the specified amount of time to settle coming back from
+ ** power-off or suspend state. */
+ gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
+ }
+
+ if (flag & gcvPOWER_FLAG_INITIALIZE)
+ {
+ /* Initialize hardware. */
+ gcmkONERROR(
+ gckHARDWARE_InitializeHardware(Hardware));
+
+ gcmkONERROR(
+ gckHARDWARE_SetFastClear(Hardware,
+ Hardware->allowFastClear,
+ Hardware->allowCompression));
+
+ /* Force the command queue to reload the next context. */
+ command->currentContext = 0;
+ }
+
+ if (flag & (gcvPOWER_FLAG_OFF | gcvPOWER_FLAG_CLOCK_OFF))
+ {
+ /* Turn off the GPU power. */
+ gcmkONERROR(
+ gckOS_SetGPUPower(os,
+ (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
+ : gcvTRUE,
+ (flag & gcvPOWER_FLAG_OFF) ? gcvFALSE : gcvTRUE));
+ }
+
+ if (flag & gcvPOWER_FLAG_START)
+ {
+ /* Start the command processor. */
+ gcmkONERROR(gckCOMMAND_Start(command));
+ }
+
+ if (flag & gcvPOWER_FLAG_RELEASE)
+ {
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
+ }
+
+ /* Save the new power state. */
+ Hardware->chipPowerState = State;
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (reserved)
+ {
+ /* Release command queue. */
+ gcmkVERIFY_OK(gckCOMMAND_Release(command));
+ }
+
+ if (acquired)
+ {
+ /* Release semaphore. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
+ }
+
+ if (mutexAcquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+#else
+ /* Do nothing */
+ return gcvSTATUS_OK;
+#endif
+#endif
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHARDWARE_QueryPowerManagementState
+**
+** Get GPU power state.
+**
+** INPUT:
+**
+** gckHARDWARE Harwdare
+** Pointer to an gckHARDWARE object.
+**
+** gceCHIPPOWERSTATE* State
+** Power State.
+**
+*/
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ )
+{
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(State != gcvNULL);
+
+ /* Return the statue. */
+ *State = Hardware->chipPowerState;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*State=%d", *State);
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle, address;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
+
+ /* We are idle when the power is not ON. */
+ if (Hardware->chipPowerState != gcvPOWER_ON)
+ {
+ *IsIdle = gcvTRUE;
+ }
+
+ else
+ {
+ /* Read idle register. */
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00004, &idle));
+
+ /* Pipe must be idle. */
+ if ((( ((((gctUINT32) (idle)) >> (0 ? 1:1)) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 3:3)) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) )!=1)
+ || (( ((((gctUINT32) (idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) )!=1)
+ )
+ {
+ /* Something is busy. */
+ *IsIdle = gcvFALSE;
+ }
+
+ else
+ {
+ /* Read the current FE address. */
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os,
+ 0x00664,
+ &address));
+
+ /* Test if address is inside the last WAIT/LINK sequence. */
+ if ((address >= Hardware->lastWaitLink)
+ && (address <= Hardware->lastWaitLink + 16)
+ )
+ {
+ /* FE is in last WAIT/LINK and the pipe is idle. */
+ *IsIdle = gcvTRUE;
+ }
+ else
+ {
+ /* FE is not in WAIT/LINK yet. */
+ *IsIdle = gcvFALSE;
+ }
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+** Handy macros that will help in reading those debug registers.
+*/
+
+#define gcmkREAD_DEBUG_REGISTER(control, block, index, data) \
+ gcmkONERROR( \
+ gckOS_WriteRegister(Hardware->os, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ index))); \
+ gcmkONERROR( \
+ gckOS_ReadRegister(Hardware->os, \
+ GC_DEBUG_SIGNALS_##block##_Address, \
+ &profiler->data))
+
+#define gcmkRESET_DEBUG_REGISTER(control, block) \
+ gcmkONERROR( \
+ gckOS_WriteRegister(Hardware->os, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ 15))); \
+ gcmkONERROR( \
+ gckOS_WriteRegister(Hardware->os, \
+ GC_DEBUG_CONTROL##control##_Address, \
+ gcmSETFIELD(0, \
+ GC_DEBUG_CONTROL##control, \
+ block, \
+ 0)))
+
+/*******************************************************************************
+**
+** gckHARDWARE_ProfileEngine2D
+**
+** Read the profile registers available in the 2D engine and sets them in the
+** profile. The function will also reset the pixelsRendered counter every time.
+**
+** INPUT:
+**
+** gckHARDWARE Hardware
+** Pointer to an gckHARDWARE object.
+**
+** OPTIONAL gcs2D_PROFILE_PTR Profile
+** Pointer to a gcs2D_Profile structure.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ )
+{
+ gceSTATUS status;
+ gcs2D_PROFILE_PTR profiler = Profile;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ if (Profile != gcvNULL)
+ {
+ /* Read the cycle count. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00438,
+ &Profile->cycleCount));
+
+ /* Read pixels rendered by 2D engine. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pixelsRendered));
+
+ /* Reset counter. */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ OUT gcsPROFILER_COUNTERS * Counters
+ )
+{
+ gceSTATUS status;
+ gcsPROFILER_COUNTERS * profiler = Counters;
+
+ gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ /* Read the counters. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00040,
+ &profiler->gpuTotalRead64BytesPerFrame));
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00044,
+ &profiler->gpuTotalWrite64BytesPerFrame));
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00438,
+ &profiler->gpuCyclesCounter));
+
+ /* Reset counters. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x0003C, 1));
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x0003C, 0));
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os, 0x00438, 0));
+
+ /* PE */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_killed_by_color_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_killed_by_depth_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_drawn_by_color_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00454, &profiler->pe_pixel_count_drawn_by_depth_pipe));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+
+ /* SH */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->ps_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->rendered_pixel_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->vs_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->rendered_vertice_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->vtx_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->vtx_texld_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->pxl_branch_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0045C, &profiler->pxl_texld_inst_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00470, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)))
+)));
+
+ /* PA */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_input_vtx_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_input_prim_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_output_prim_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_depth_clipped_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_trivial_rejected_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00460, &profiler->pa_culled_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0)))
+)));
+
+ /* SE */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00464, &profiler->se_culled_triangle_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00464, &profiler->se_culled_lines_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8)))
+)));
+
+ /* RA */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_valid_pixel_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_total_quad_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_total_primitive_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_pipe_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:16) - (0 ? 19:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:16) - (0 ? 19:16) + 1))))))) << (0 ? 19:16)))
+)));
+
+ /* TX */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_bilinear_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_trilinear_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_discarded_texture_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_total_texture_requests));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_mem_read_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_mem_read_in_8B_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_miss_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_hit_texel_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0044C, &profiler->tx_cache_miss_texel_count));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00474, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 27:24) - (0 ? 27:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:24) - (0 ? 27:24) + 1))))))) << (0 ? 27:24)))
+)));
+
+ /* MC */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1))))))) << (0 ? 3:0)))
+)));
+
+ /* HI */
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_ReadRegister(Hardware->os, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) )));
+ gcmkONERROR(gckOS_WriteRegister(Hardware->os, 0x00478, ( ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1))))))) << (0 ? 11:8)))
+)));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ )
+{
+ gceSTATUS status;
+ gctUINT32 control, idle;
+ gckCOMMAND command;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkASSERT(Hardware->kernel != gcvNULL);
+ command = Hardware->kernel->command;
+ gcmkASSERT(command != gcvNULL);
+
+ if (Hardware->chipRevision < 0x4600)
+ {
+ /* Not supported - we need the isolation bit. */
+ gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
+ }
+
+ if (Hardware->chipPowerState == gcvPOWER_ON)
+ {
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(
+ gckOS_AcquireSemaphore(Hardware->os, command->powerSemaphore));
+ acquired = gcvTRUE;
+ }
+
+ if ((Hardware->chipPowerState == gcvPOWER_ON)
+ || (Hardware->chipPowerState == gcvPOWER_IDLE)
+ )
+ {
+ /* Stop the command processor. */
+ gcmkONERROR(
+ gckCOMMAND_Stop(command));
+
+ /* Grab the queue mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Hardware->os,
+ command->mutexQueue,
+ gcvINFINITE));
+ }
+
+ /* Read register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00000,
+ &control));
+
+ for (;;)
+ {
+ /* Isolate the GPU. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ control));
+
+ /* Set soft reset. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Wait for reset. */
+ gcmkONERROR(
+ gckOS_Delay(Hardware->os, 1));
+
+ /* Reset soft reset bit. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
+
+ /* Reset GPU isolation. */
+ control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
+
+ gcmkONERROR(
+ gckOS_WriteRegister(Hardware->os,
+ 0x00000,
+ control));
+
+ /* Read idle register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00004,
+ &idle));
+
+ if (( ((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) )==0)
+ {
+ continue;
+ }
+
+ /* Read reset register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Hardware->os,
+ 0x00000,
+ &control));
+
+ if ((( ((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) )==0)
+ || (( ((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) )==0)
+ )
+ {
+ continue;
+ }
+
+ /* GPU is idle. */
+ break;
+ }
+
+ /* Force an OFF to ON power switch. */
+ Hardware->chipPowerState = gcvPOWER_OFF;
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the power management semaphore. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
+ }
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Hardware=0x%x", Hardware);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Test if we have a new Memory Controller. */
+ if (((((gctUINT32) (Hardware->chipMinorFeatures0)) >> (0 ? 22:22) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))))
+ {
+ /* No base address required. */
+ *BaseAddress = 0;
+ }
+ else
+ {
+ /* Get the base address from the OS. */
+ gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, BaseAddress));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ )
+{
+ gctBOOL need = gcvFALSE;
+
+ gcmkHEADER_ARG("Hardware=0x%x State=0x%08x", Hardware, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+ gcmkVERIFY_ARGUMENT(NeedBase != gcvNULL);
+
+ /* Make sure this is a load state. */
+ if (((((gctUINT32) (State)) >> (0 ? 31:27) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27)+1))))))))
+ {
+ /* Get the state address. */
+ switch (( ((((gctUINT32) (State)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0)+1))))))))
+ {
+ case 0x0596:
+ case 0x0597:
+ case 0x0599:
+ case 0x059A:
+ case 0x05A9:
+ /* These states need a TRUE physical address. */
+ need = gcvTRUE;
+ break;
+ }
+ }
+
+ /* Return the flag. */
+ *NeedBase = need;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
+ return gcvSTATUS_OK;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_hardware_h_
+#define __gc_hal_kernel_hardware_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* gckHARDWARE object. */
+struct _gckHARDWARE
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gctKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Pointer to gctOS object. */
+ gckOS os;
+
+ /* Chip characteristics. */
+ gceCHIPMODEL chipModel;
+ gctUINT32 chipRevision;
+ gctUINT32 chipFeatures;
+ gctUINT32 chipMinorFeatures0;
+ gctUINT32 chipMinorFeatures1;
+ gctBOOL allowFastClear;
+ gctBOOL allowCompression;
+ gctUINT32 powerBaseAddress;
+ gctBOOL extraEventStates;
+
+ gctUINT32 streamCount;
+ gctUINT32 registerMax;
+ gctUINT32 threadCount;
+ gctUINT32 shaderCoreCount;
+ gctUINT32 vertexCacheSize;
+ gctUINT32 vertexOutputBufferSize;
+
+ /* Big endian */
+ gctBOOL bigEndian;
+
+ /* Chip status */
+ gctPOINTER powerMutex;
+ gctUINT32 powerProcess;
+ gctUINT32 powerThread;
+ gceCHIPPOWERSTATE chipPowerState;
+ gctUINT32 lastWaitLink;
+};
+
+gceSTATUS
+gckHARDWARE_GetBaseAddress(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+gceSTATUS
+gckHARDWARE_NeedBaseAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 State,
+ OUT gctBOOL_PTR NeedBase
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_hardware_h_ */
+
--- /dev/null
+##############################################################################
+#
+# 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
--- /dev/null
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+ARCH_TYPE ?= arm
+SDK_DIR ?= $(AQROOT)/build/sdk
+USE_3D_VG = 1
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_h_
+#define __gc_hal_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+#include "gc_hal_base.h"
+#include "gc_hal_profiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* Alignment Macros *******************************
+\******************************************************************************/
+
+#define gcmALIGN(n, align) \
+( \
+ ((n) + ((align) - 1)) & ~((align) - 1) \
+)
+
+/******************************************************************************\
+***************************** Element Count Macro *****************************
+\******************************************************************************/
+
+#define gcmSIZEOF(a) \
+( \
+ (gctSIZE_T) (sizeof(a)) \
+)
+
+#define gcmCOUNTOF(a) \
+( \
+ sizeof(a) / sizeof(a[0]) \
+)
+
+/******************************************************************************\
+******************************** gcsOBJECT Object *******************************
+\******************************************************************************/
+
+/* Type of objects. */
+typedef enum _gceOBJECT_TYPE
+{
+ gcvOBJ_UNKNOWN = 0,
+ gcvOBJ_2D = gcmCC('2','D',' ',' '),
+ gcvOBJ_3D = gcmCC('3','D',' ',' '),
+ gcvOBJ_ATTRIBUTE = gcmCC('A','T','T','R'),
+ gcvOBJ_BRUSHCACHE = gcmCC('B','R','U','$'),
+ gcvOBJ_BRUSHNODE = gcmCC('B','R','U','n'),
+ gcvOBJ_BRUSH = gcmCC('B','R','U','o'),
+ gcvOBJ_BUFFER = gcmCC('B','U','F','R'),
+ gcvOBJ_COMMAND = gcmCC('C','M','D',' '),
+ gcvOBJ_COMMANDBUFFER = gcmCC('C','M','D','B'),
+ gcvOBJ_CONTEXT = gcmCC('C','T','X','T'),
+ gcvOBJ_DEVICE = gcmCC('D','E','V',' '),
+ gcvOBJ_DUMP = gcmCC('D','U','M','P'),
+ gcvOBJ_EVENT = gcmCC('E','V','N','T'),
+ gcvOBJ_FUNCTION = gcmCC('F','U','N','C'),
+ gcvOBJ_HAL = gcmCC('H','A','L',' '),
+ gcvOBJ_HARDWARE = gcmCC('H','A','R','D'),
+ gcvOBJ_HEAP = gcmCC('H','E','A','P'),
+ gcvOBJ_INDEX = gcmCC('I','N','D','X'),
+ gcvOBJ_INTERRUPT = gcmCC('I','N','T','R'),
+ gcvOBJ_KERNEL = gcmCC('K','E','R','N'),
+ gcvOBJ_MEMORYBUFFER = gcmCC('M','E','M','B'),
+ gcvOBJ_MMU = gcmCC('M','M','U',' '),
+ gcvOBJ_OS = gcmCC('O','S',' ',' '),
+ gcvOBJ_OUTPUT = gcmCC('O','U','T','P'),
+ gcvOBJ_PAINT = gcmCC('P','N','T',' '),
+ gcvOBJ_PATH = gcmCC('P','A','T','H'),
+ gcvOBJ_QUEUE = gcmCC('Q','U','E',' '),
+ gcvOBJ_SAMPLER = gcmCC('S','A','M','P'),
+ gcvOBJ_SHADER = gcmCC('S','H','D','R'),
+ gcvOBJ_STREAM = gcmCC('S','T','R','M'),
+ gcvOBJ_SURF = gcmCC('S','U','R','F'),
+ gcvOBJ_TEXTURE = gcmCC('T','X','T','R'),
+ gcvOBJ_UNIFORM = gcmCC('U','N','I','F'),
+ gcvOBJ_VARIABLE = gcmCC('V','A','R','I'),
+ gcvOBJ_VERTEX = gcmCC('V','R','T','X'),
+ gcvOBJ_VIDMEM = gcmCC('V','M','E','M'),
+ gcvOBJ_VG = gcmCC('V','G',' ',' '),
+}
+gceOBJECT_TYPE;
+
+/* gcsOBJECT object defintinon. */
+typedef struct _gcsOBJECT
+{
+ /* Type of an object. */
+ gceOBJECT_TYPE type;
+}
+gcsOBJECT;
+
+/* Kernel settings. */
+typedef struct _gcsKERNEL_SETTINGS
+{
+ /* Used RealTime signal between kernel and user. */
+ gctINT signal;
+}
+gcsKERNEL_SETTINGS;
+
+typedef struct _gckHARDWARE * gckHARDWARE;
+
+/*******************************************************************************
+**
+** gcmVERIFY_OBJECT
+**
+** Assert if an object is invalid or is not of the specified type. If the
+** object is invalid or not of the specified type, gcvSTATUS_INVALID_OBJECT
+** will be returned from the current function. In retail mode this macro
+** does nothing.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_OBJECT(prefix, obj, t) \
+ do \
+ { \
+ if ((obj) == gcvNULL) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: NULL"); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT((obj) != gcvNULL); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ } \
+ else if (((gcsOBJECT*) (obj))->type != t) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "VERIFY_OBJECT failed: %c%c%c%c", \
+ gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
+ prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
+ gcmCC_PRINT(t)); \
+ prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
+ return gcvSTATUS_INVALID_OBJECT; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcm, obj, t)
+# define gcmkVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcmk, obj, t)
+#else
+# define gcmVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+# define gcmkVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
+#endif
+
+/******************************************************************************\
+********************************** gckOS Object *********************************
+\******************************************************************************/
+
+typedef struct _gckOS * gckOS;
+
+/* Construct a new gckOS object. */
+gceSTATUS
+gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ );
+
+/* Destroy an gckOS object. */
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gckOS_QueryVideoMemory(
+ IN gckOS Os,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Wrapper for allocation memory.. */
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Wrapper for freeing memory. */
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Allocate paged memory. */
+gceSTATUS
+gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ );
+
+/* Lock pages. */
+gceSTATUS
+gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+#endif
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ );
+
+/* Map pages. */
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+#ifdef __QNXNTO__
+ IN gctPOINTER Logical,
+#endif
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ );
+
+/* Unlock pages. */
+gceSTATUS
+gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+#endif
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Free paged memory. */
+gceSTATUS
+gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Allocate non-paged memory. */
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non-paged memory. */
+gceSTATUS
+gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get the number fo bytes per page. */
+gceSTATUS
+gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ );
+
+/* Get the physical address of a corresponding logical address. */
+gceSTATUS
+gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ );
+
+/* Map physical memory. */
+gceSTATUS
+gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap previously mapped physical memory. */
+gceSTATUS
+gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Read data from a hardware register. */
+gceSTATUS
+gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+/* Write data to a hardware register. */
+gceSTATUS
+gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Write data to a 32-bit memory location. */
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ );
+
+/* Map physical memory into the process space. */
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap physical memory from the process space. */
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Create a new mutex. */
+gceSTATUS
+gckOS_CreateMutex(
+ IN gckOS Os,
+ OUT gctPOINTER * Mutex
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Atomically exchange a pair of 32-bit values. */
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ );
+
+/* Atomically exchange a pair of pointers. */
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ );
+
+/* Memory barrier. */
+gceSTATUS
+gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ );
+
+/* Map user pointer. */
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Unmap user pointer. */
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ );
+
+#ifdef __QNXNTO__
+/* Map user physical address. */
+gceSTATUS
+gckOS_MapUserPhysical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Phys,
+ OUT gctPOINTER * KernelPointer
+ );
+
+/* Allocate from user's shared pool. */
+gceSTATUS
+gckOS_AllocateNonPagedMemoryShmPool(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+#endif
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ );
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Perform a memory copy. */
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ );
+
+/* Zero memory. */
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Device I/O control to the kernel HAL layer. */
+gceSTATUS
+gckOS_DeviceControl(
+ IN gckOS Os,
+ IN gctBOOL FromUser,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ OUT gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ );
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ );
+
+/******************************************************************************\
+********************************** Signal Object *********************************
+\******************************************************************************/
+
+/* User signal command codes. */
+typedef enum _gceUSER_SIGNAL_COMMAND_CODES
+{
+ gcvUSER_SIGNAL_CREATE,
+ gcvUSER_SIGNAL_DESTROY,
+ gcvUSER_SIGNAL_SIGNAL,
+ gcvUSER_SIGNAL_WAIT,
+}
+gceUSER_SIGNAL_COMMAND_CODES;
+
+/* Create a signal. */
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+/* Map a user signal to the kernel space. */
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ );
+
+/* Map user memory. */
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+#if !USE_NEW_LINUX_SIGNAL
+/* Create signal to be used in the user space. */
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctINT * SignalID
+ );
+
+/* Destroy signal used in the user space. */
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ );
+
+/* Wait for signal used in the user space. */
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ );
+
+/* Signal a signal used in the user space. */
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ );
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/* Set a signal owned by a process. */
+#if defined(__QNXNTO__)
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctINT Recvid,
+ IN gctINT Coid
+ );
+#else
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ );
+#endif
+
+/******************************************************************************\
+** Cache Support
+*/
+
+gceSTATUS
+gckOS_CacheFlush(
+ gckOS Os,
+ gctHANDLE ProcessId,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gckOS_CacheInvalidate(
+ gckOS Os,
+ gctHANDLE ProcessId,
+ gctPOINTER Logical,
+ gctSIZE_T Bytes
+ );
+
+/******************************************************************************\
+** Debug Support
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gckOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+/*******************************************************************************
+** Broadcast interface.
+*/
+
+typedef enum _gceBROADCAST
+{
+ /* GPU might be idle. */
+ gcvBROADCAST_GPU_IDLE,
+
+ /* A commit is going to happen. */
+ gcvBROADCAST_GPU_COMMIT,
+
+ /* GPU seems to be stuck. */
+ gcvBROADCAST_GPU_STUCK,
+
+ /* First process gets attached. */
+ gcvBROADCAST_FIRST_PROCESS,
+
+ /* Last process gets detached. */
+ gcvBROADCAST_LAST_PROCESS,
+
+ /* AXI bus error. */
+ gcvBROADCAST_AXI_BUS_ERROR,
+}
+gceBROADCAST;
+
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ );
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.ß
+**
+** gctBOOL Clock
+** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ );
+
+/*******************************************************************************
+** Semaphores.
+*/
+
+/* Create a new semaphore. */
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ );
+
+/* Delete a semahore. */
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Acquire a semahore. */
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/* Release a semahore. */
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ );
+
+/******************************************************************************\
+********************************* gckHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gckHEAP * gckHEAP;
+
+/* Construct a new gckHEAP object. */
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ );
+
+/* Destroy an gckHEAP object. */
+gceSTATUS
+gckHEAP_Destroy(
+ IN gckHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+/* Profile the heap. */
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ );
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gckHEAP_Test(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Vectors,
+ IN gctSIZE_T MaxSize
+ );
+#endif
+
+/******************************************************************************\
+******************************** gckVIDMEM Object ******************************
+\******************************************************************************/
+
+typedef struct _gckVIDMEM * gckVIDMEM;
+typedef union _gcuVIDMEM_NODE * gcuVIDMEM_NODE_PTR;
+typedef struct _gckKERNEL * gckKERNEL;
+
+/* Construct a new gckVIDMEM object. */
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T Banking,
+ OUT gckVIDMEM * Memory
+ );
+
+/* Destroy an gckVDIMEM object. */
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ );
+
+/* Allocate rectangular memory. */
+gceSTATUS
+gckVIDMEM_Allocate(
+ IN gckVIDMEM Memory,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT BytesPerPixel,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Allocate linear memory. */
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+ IN gckVIDMEM Memory,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gckVIDMEM_Free(
+ IN gcuVIDMEM_NODE_PTR Node
+ );
+
+/* Lock memory. */
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ OUT gctUINT32 * Address
+ );
+
+/* Unlock memory. */
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ );
+
+/* Construct a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ );
+
+/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+ IN gcuVIDMEM_NODE_PTR Node
+ );
+
+#ifdef __QNXNTO__
+/* Set the allocating process' PID for this node. */
+gceSTATUS
+gckVIDMEM_SetPID(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctUINT32 Pid);
+#endif
+
+/******************************************************************************\
+******************************** gckKERNEL Object ******************************
+\******************************************************************************/
+
+struct _gcsHAL_INTERFACE;
+
+/* Notifications. */
+typedef enum _gceNOTIFY
+{
+ gcvNOTIFY_INTERRUPT,
+ gcvNOTIFY_COMMAND_QUEUE,
+}
+gceNOTIFY;
+
+/* Event locations. */
+typedef enum _gceKERNEL_WHERE
+{
+ gcvKERNEL_COMMAND,
+ gcvKERNEL_VERTEX,
+ gcvKERNEL_TRIANGLE,
+ gcvKERNEL_TEXTURE,
+ gcvKERNEL_PIXEL,
+}
+gceKERNEL_WHERE;
+
+/* Flush flags. */
+typedef enum _gceKERNEL_FLUSH
+{
+ gcvFLUSH_COLOR = 0x01,
+ gcvFLUSH_DEPTH = 0x02,
+ gcvFLUSH_TEXTURE = 0x04,
+ gcvFLUSH_2D = 0x08,
+ gcvFLUSH_ALL = gcvFLUSH_COLOR
+ | gcvFLUSH_DEPTH
+ | gcvFLUSH_TEXTURE
+ | gcvFLUSH_2D,
+}
+gceKERNEL_FLUSH;
+
+/* Construct a new gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ OUT gckKERNEL * Kernel
+ );
+
+/* Destroy an gckKERNEL object. */
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ );
+
+/* Dispatch a user-level command. */
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT struct _gcsHAL_INTERFACE * Interface
+ );
+
+/* Lookup the gckVIDMEM object for a pool. */
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ );
+
+/* Map video memory. */
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+#ifdef __QNXNTO__
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes,
+#endif
+ OUT gctPOINTER * Logical
+ );
+
+#ifdef __QNXNTO__
+/* Unmap video memory. */
+gceSTATUS
+gckKERNEL_UnmapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes
+ );
+#endif
+
+/* Map memory. */
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap memory. */
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ );
+
+/* Notification of events. */
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+ IN gceNOTIFY Notifcation,
+ IN gctBOOL Data
+ );
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ );
+
+/*******************************************************************************
+**
+** gckKERNEL_Recovery
+**
+** Try to recover the GPU from a fatal error.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+ IN gckKERNEL Kernel
+ );
+
+/******************************************************************************\
+******************************* gckHARDWARE Object *****************************
+\******************************************************************************/
+
+/* Construct a new gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Construct(
+ IN gckOS Os,
+ OUT gckHARDWARE * Hardware
+ );
+
+/* Destroy an gckHARDWARE object. */
+gceSTATUS
+gckHARDWARE_Destroy(
+ IN gckHARDWARE Hardware
+ );
+
+/* Query system memory requirements. */
+gceSTATUS
+gckHARDWARE_QuerySystemMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * SystemSize,
+ OUT gctUINT32 * SystemBaseAddress
+ );
+
+/* Build virtual address. */
+gceSTATUS
+gckHARDWARE_BuildVirtualAddress(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Index,
+ IN gctUINT32 Offset,
+ OUT gctUINT32 * Address
+ );
+
+/* Query command buffer requirements. */
+gceSTATUS
+gckHARDWARE_QueryCommandBuffer(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * Alignment,
+ OUT gctSIZE_T * ReservedHead,
+ OUT gctSIZE_T * ReservedTail
+ );
+
+/* Add a WAIT/LINK pair in the command queue. */
+gceSTATUS
+gckHARDWARE_WaitLink(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPOINTER * Wait,
+ OUT gctSIZE_T * WaitBytes
+ );
+
+/* Kickstart the command processor. */
+gceSTATUS
+gckHARDWARE_Execute(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+#ifdef __QNXNTO__
+ IN gctPOINTER Physical,
+ IN gctBOOL PhysicalAddresses,
+#endif
+ IN gctSIZE_T Bytes
+ );
+
+/* Add an END command in the command queue. */
+gceSTATUS
+gckHARDWARE_End(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a NOP command in the command queue. */
+gceSTATUS
+gckHARDWARE_Nop(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a WAIT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Wait(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Count,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a PIPESELECT command in the command queue. */
+gceSTATUS
+gckHARDWARE_PipeSelect(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pipe,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add a LINK command in the command queue. */
+gceSTATUS
+gckHARDWARE_Link(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctPOINTER FetchAddress,
+ IN gctSIZE_T FetchSize,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Add an EVENT command in the command queue. */
+gceSTATUS
+gckHARDWARE_Event(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT8 Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Query the available memory. */
+gceSTATUS
+gckHARDWARE_QueryMemory(
+ IN gckHARDWARE Hardware,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctUINT32 * InternalBaseAddress,
+ OUT gctUINT32 * InternalAlignment,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctUINT32 * ExternalBaseAddress,
+ OUT gctUINT32 * ExternalAlignment,
+ OUT gctUINT32 * HorizontalTileSize,
+ OUT gctUINT32 * VerticalTileSize
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipIdentity(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures,
+ OUT gctUINT32* ChipMinorFeatures1
+ );
+
+/* Query the specifications sof the hardware. */
+gceSTATUS
+gckHARDWARE_QueryChipSpecs(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR StreamCount,
+ OUT gctUINT32_PTR RegisterMax,
+ OUT gctUINT32_PTR ThreadCount,
+ OUT gctUINT32_PTR ShaderCoreCount,
+ OUT gctUINT32_PTR VertexCacheSize,
+ OUT gctUINT32_PTR VertexOutputBufferSize
+ );
+
+/* Convert an API format. */
+gceSTATUS
+gckHARDWARE_ConvertFormat(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_FORMAT Format,
+ OUT gctUINT32 * BitsPerPixel,
+ OUT gctUINT32 * BytesPerTile
+ );
+
+/* Split a harwdare specific address into API stuff. */
+gceSTATUS
+gckHARDWARE_SplitMemory(
+ IN gckHARDWARE Hardware,
+ IN gctUINT32 Address,
+ OUT gcePOOL * Pool,
+ OUT gctUINT32 * Offset
+ );
+
+/* Align size to tile boundary. */
+gceSTATUS
+gckHARDWARE_AlignToTile(
+ IN gckHARDWARE Hardware,
+ IN gceSURF_TYPE Type,
+ IN OUT gctUINT32_PTR Width,
+ IN OUT gctUINT32_PTR Height,
+ OUT gctBOOL_PTR SuperTiled
+ );
+
+/* Update command queue tail pointer. */
+gceSTATUS
+gckHARDWARE_UpdateQueueTail(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset
+ );
+
+/* Convert logical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertLogical(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ );
+
+#ifdef __QNXNTO__
+/* Convert physical address to hardware specific address. */
+gceSTATUS
+gckHARDWARE_ConvertPhysical(
+ IN gckHARDWARE Hardware,
+ IN gctPHYS_ADDR Physical,
+ OUT gctUINT32 * Address
+ );
+#endif
+
+/* Interrupt manager. */
+gceSTATUS
+gckHARDWARE_Interrupt(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL InterruptValid
+ );
+
+/* Program MMU. */
+gceSTATUS
+gckHARDWARE_SetMMU(
+ IN gckHARDWARE Hardware,
+ IN gctPOINTER Logical
+ );
+
+/* Flush the MMU. */
+gceSTATUS
+gckHARDWARE_FlushMMU(
+ IN gckHARDWARE Hardware
+ );
+
+/* Get idle register. */
+gceSTATUS
+gckHARDWARE_GetIdle(
+ IN gckHARDWARE Hardware,
+ IN gctBOOL Wait,
+ OUT gctUINT32 * Data
+ );
+
+/* Flush the caches. */
+gceSTATUS
+gckHARDWARE_Flush(
+ IN gckHARDWARE Hardware,
+ IN gceKERNEL_FLUSH Flush,
+ IN gctPOINTER Logical,
+ IN OUT gctSIZE_T * Bytes
+ );
+
+/* Enable/disable fast clear. */
+gceSTATUS
+gckHARDWARE_SetFastClear(
+ IN gckHARDWARE Hardware,
+ IN gctINT Enable,
+ IN gctINT Compression
+ );
+
+gceSTATUS
+gckHARDWARE_ReadInterrupt(
+ IN gckHARDWARE Hardware,
+ OUT gctUINT32_PTR IDs
+ );
+
+/* Power management. */
+gceSTATUS
+gckHARDWARE_SetPowerManagementState(
+ IN gckHARDWARE Hardware,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gckHARDWARE_QueryPowerManagementState(
+ IN gckHARDWARE Hardware,
+ OUT gceCHIPPOWERSTATE* State
+ );
+
+/* Profile 2D Engine. */
+gceSTATUS
+gckHARDWARE_ProfileEngine2D(
+ IN gckHARDWARE Hardware,
+ OUT gcs2D_PROFILE_PTR Profile
+ );
+
+gceSTATUS
+gckHARDWARE_InitializeHardware(
+ IN gckHARDWARE Hardware
+ );
+
+gceSTATUS
+gckHARDWARE_Reset(
+ IN gckHARDWARE Hardware
+ );
+
+/******************************************************************************\
+***************************** gckINTERRUPT Object ******************************
+\******************************************************************************/
+
+typedef struct _gckINTERRUPT * gckINTERRUPT;
+
+typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
+ IN gckKERNEL Kernel
+ );
+
+gceSTATUS
+gckINTERRUPT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckINTERRUPT * Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_Destroy(
+ IN gckINTERRUPT Interrupt
+ );
+
+gceSTATUS
+gckINTERRUPT_SetHandler(
+ IN gckINTERRUPT Interrupt,
+ IN OUT gctINT32_PTR Id,
+ IN gctINTERRUPT_HANDLER Handler
+ );
+
+gceSTATUS
+gckINTERRUPT_Notify(
+ IN gckINTERRUPT Interrupt,
+ IN gctBOOL Valid
+ );
+
+/******************************************************************************\
+******************************** gckEVENT Object *******************************
+\******************************************************************************/
+
+typedef struct _gckEVENT * gckEVENT;
+
+/* Construct a new gckEVENT object. */
+gceSTATUS
+gckEVENT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckEVENT * Event
+ );
+
+/* Destroy an gckEVENT object. */
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ );
+
+/* Schedule a FreeNonPagedMemory event. */
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeContiguousMemory event. */
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a FreeVideoMemory event. */
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+ IN gckEVENT Event,
+ IN gcuVIDMEM_NODE_PTR VideoMemory,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule a signal event. */
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ );
+
+/* Schedule an Unlock event. */
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type
+ );
+
+gceSTATUS
+gckEVENT_Submit(
+ IN gckEVENT Event,
+ IN gctBOOL Wait
+ );
+
+struct _gcsQUEUE;
+
+/* Commit an event queue. */
+gceSTATUS
+gckEVENT_Commit(
+ IN gckEVENT Event,
+ IN struct _gcsQUEUE * Queue
+ );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ );
+
+/* Event callback routine. */
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ );
+
+/******************************************************************************\
+******************************* gckCOMMAND Object ******************************
+\******************************************************************************/
+
+typedef struct _gckCOMMAND * gckCOMMAND;
+
+/* Construct a new gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckCOMMAND * Command
+ );
+
+/* Destroy an gckCOMMAND object. */
+gceSTATUS
+gckCOMMAND_Destroy(
+ IN gckCOMMAND Command
+ );
+
+/* Start the command queue. */
+gceSTATUS
+gckCOMMAND_Start(
+ IN gckCOMMAND Command
+ );
+
+/* Stop the command queue. */
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command
+ );
+
+/* Commit a buffer to the command queue. */
+gceSTATUS
+gckCOMMAND_Commit(
+ IN gckCOMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcoCONTEXT Context,
+ IN gctHANDLE Process
+ );
+
+/* Reserve space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctSIZE_T * BufferSize
+ );
+
+/* Release reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Release(
+ IN gckCOMMAND Command
+ );
+
+/* Execute reserved space in the command buffer. */
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequstedBytes
+ );
+
+/* Stall the command queue. */
+gceSTATUS
+gckCOMMAND_Stall(
+ IN gckCOMMAND Command
+ );
+
+/******************************************************************************\
+********************************* gckMMU Object ********************************
+\******************************************************************************/
+
+typedef struct _gckMMU * gckMMU;
+
+/* Construct a new gckMMU object. */
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ );
+
+/* Destroy an gckMMU object. */
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ );
+
+/* Allocate pages inside the MMU. */
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ );
+
+/* Remove a page table from the MMU. */
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ );
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_InsertNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node);
+
+gceSTATUS
+gckMMU_RemoveNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node);
+#endif
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_FreeHandleMemory(
+ IN gckMMU Mmu,
+ IN gctHANDLE Handle
+ );
+#endif
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gckMMU_Test(
+ IN gckMMU Mmu,
+ IN gctSIZE_T Vectors,
+ IN gctINT MaxSize
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryProfileRegisters(
+ IN gckHARDWARE Hardware,
+ OUT gcsPROFILER_COUNTERS * Counters
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_base_h_
+#define __gc_hal_base_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+#include "gc_hal_dump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoHAL * gcoHAL;
+typedef struct _gcoOS * gcoOS;
+typedef struct _gco2D * gco2D;
+typedef struct _gcoVG * gcoVG;
+typedef struct _gco3D * gco3D;
+typedef struct _gcoSURF * gcoSURF;
+typedef struct _gcsSURF_INFO * gcsSURF_INFO_PTR;
+typedef struct _gcsSURF_NODE * gcsSURF_NODE_PTR;
+typedef struct _gcsSURF_FORMAT_INFO * gcsSURF_FORMAT_INFO_PTR;
+typedef struct _gcsPOINT * gcsPOINT_PTR;
+typedef struct _gcsSIZE * gcsSIZE_PTR;
+typedef struct _gcsRECT * gcsRECT_PTR;
+typedef struct _gcsBOUNDARY * gcsBOUNDARY_PTR;
+typedef struct _gcoDUMP * gcoDUMP;
+typedef struct _gcoHARDWARE * gcoHARDWARE;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+/* Video memory pool type. */
+typedef enum _gcePOOL
+{
+ gcvPOOL_UNKNOWN,
+ gcvPOOL_DEFAULT,
+ gcvPOOL_LOCAL,
+ gcvPOOL_LOCAL_INTERNAL,
+ gcvPOOL_LOCAL_EXTERNAL,
+ gcvPOOL_UNIFIED,
+ gcvPOOL_SYSTEM,
+ gcvPOOL_VIRTUAL,
+ gcvPOOL_USER,
+ gcvPOOL_CONTIGUOUS
+}
+gcePOOL;
+
+/* Blending functions. */
+typedef enum _gceBLEND_FUNCTION
+{
+ gcvBLEND_ZERO,
+ gcvBLEND_ONE,
+ gcvBLEND_SOURCE_COLOR,
+ gcvBLEND_INV_SOURCE_COLOR,
+ gcvBLEND_SOURCE_ALPHA,
+ gcvBLEND_INV_SOURCE_ALPHA,
+ gcvBLEND_TARGET_COLOR,
+ gcvBLEND_INV_TARGET_COLOR,
+ gcvBLEND_TARGET_ALPHA,
+ gcvBLEND_INV_TARGET_ALPHA,
+ gcvBLEND_SOURCE_ALPHA_SATURATE,
+ gcvBLEND_CONST_COLOR,
+ gcvBLEND_INV_CONST_COLOR,
+ gcvBLEND_CONST_ALPHA,
+ gcvBLEND_INV_CONST_ALPHA,
+}
+gceBLEND_FUNCTION;
+
+/* Blending modes. */
+typedef enum _gceBLEND_MODE
+{
+ gcvBLEND_ADD,
+ gcvBLEND_SUBTRACT,
+ gcvBLEND_REVERSE_SUBTRACT,
+ gcvBLEND_MIN,
+ gcvBLEND_MAX,
+}
+gceBLEND_MODE;
+
+/* API flags. */
+typedef enum _gceAPI
+{
+ gcvAPI_D3D = 0x1,
+ gcvAPI_OPENGL = 0x2,
+}
+gceAPI;
+
+/* Depth modes. */
+typedef enum _gceDEPTH_MODE
+{
+ gcvDEPTH_NONE,
+ gcvDEPTH_Z,
+ gcvDEPTH_W,
+}
+gceDEPTH_MODE;
+
+typedef enum _gceWHERE
+{
+ gcvWHERE_COMMAND,
+ gcvWHERE_RASTER,
+ gcvWHERE_PIXEL,
+}
+gceWHERE;
+
+typedef enum _gceHOW
+{
+ gcvHOW_SEMAPHORE = 0x1,
+ gcvHOW_STALL = 0x2,
+ gcvHOW_SEMAPHORE_STALL = 0x3,
+}
+gceHOW;
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Construct a new gcoHAL object. */
+gceSTATUS
+gcoHAL_Construct(
+ IN gctPOINTER Context,
+ IN gcoOS Os,
+ OUT gcoHAL * Hal
+ );
+
+/* Destroy an gcoHAL object. */
+gceSTATUS
+gcoHAL_Destroy(
+ IN gcoHAL Hal
+ );
+
+/* Get pointer to gco2D object. */
+gceSTATUS
+gcoHAL_Get2DEngine(
+ IN gcoHAL Hal,
+ OUT gco2D * Engine
+ );
+
+/* Get pointer to gcoVG object. */
+gceSTATUS
+gcoHAL_GetVGEngine(
+ IN gcoHAL Hal,
+ OUT gcoVG * Engine
+ );
+
+/* Get pointer to gco3D object. */
+gceSTATUS
+gcoHAL_Get3DEngine(
+ IN gcoHAL Hal,
+ OUT gco3D * Engine
+ );
+
+/* Verify whether the specified feature is available in hardware. */
+gceSTATUS
+gcoHAL_IsFeatureAvailable(
+ IN gcoHAL Hal,
+ IN gceFEATURE Feature
+ );
+
+/* Query the identity of the hardware. */
+gceSTATUS
+gcoHAL_QueryChipIdentity(
+ IN gcoHAL Hal,
+ OUT gceCHIPMODEL* ChipModel,
+ OUT gctUINT32* ChipRevision,
+ OUT gctUINT32* ChipFeatures,
+ OUT gctUINT32* ChipMinorFeatures
+ );
+
+/* Query the amount of video memory. */
+gceSTATUS
+gcoHAL_QueryVideoMemory(
+ IN gcoHAL Hal,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/* Map video memory. */
+gceSTATUS
+gcoHAL_MapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ OUT gctPOINTER * Logical
+ );
+
+/* Unmap video memory. */
+gceSTATUS
+gcoHAL_UnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* Schedule an unmap of a buffer mapped through its physical address. */
+gceSTATUS
+gcoHAL_ScheduleUnmapMemory(
+ IN gcoHAL Hal,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T NumberOfBytes,
+ IN gctPOINTER Logical
+ );
+
+/* Schedule an unmap of a user buffer using event mechanism. */
+gceSTATUS
+gcoHAL_ScheduleUnmapUserMemory(
+ IN gcoHAL Hal,
+ IN gctPOINTER Info,
+ IN gctSIZE_T Size,
+ IN gctUINT32 Address,
+ IN gctPOINTER Memory
+ );
+
+/* Commit the current command buffer. */
+gceSTATUS
+gcoHAL_Commit(
+ IN gcoHAL Hal,
+ IN gctBOOL Stall
+ );
+
+/* Query the tile capabilities. */
+gceSTATUS
+gcoHAL_QueryTiled(
+ IN gcoHAL Hal,
+ OUT gctINT32 * TileWidth2D,
+ OUT gctINT32 * TileHeight2D,
+ OUT gctINT32 * TileWidth3D,
+ OUT gctINT32 * TileHeight3D
+ );
+
+gceSTATUS
+gcoHAL_Compact(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_ProfileStart(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoHAL_ProfileEnd(
+ IN gcoHAL Hal,
+ IN gctCONST_STRING Title
+ );
+
+/* Power Management */
+gceSTATUS
+gcoHAL_SetPowerManagementState(
+ IN gcoHAL Hal,
+ IN gceCHIPPOWERSTATE State
+ );
+
+gceSTATUS
+gcoHAL_QueryPowerManagementState(
+ IN gcoHAL Hal,
+ OUT gceCHIPPOWERSTATE *State
+ );
+
+/* Set the filter type for filter blit. */
+gceSTATUS
+gcoHAL_SetFilterType(
+ IN gcoHAL Hal,
+ IN gceFILTER_TYPE FilterType
+ );
+
+gceSTATUS
+gcoHAL_GetDump(
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+/* Call the kernel HAL layer. */
+gceSTATUS
+gcoHAL_Call(
+ IN gcoHAL Hal,
+ IN OUT gcsHAL_INTERFACE_PTR Interface
+ );
+
+/* Schedule an event. */
+gceSTATUS
+gcoHAL_ScheduleEvent(
+ IN gcoHAL Hal,
+ IN OUT gcsHAL_INTERFACE_PTR Interface
+ );
+
+/* Destroy a surface. */
+gceSTATUS
+gcoHAL_DestroySurface(
+ IN gcoHAL Hal,
+ IN gcoSURF Surface
+ );
+
+/******************************************************************************\
+********************************** gcoOS Object *********************************
+\******************************************************************************/
+
+/* Construct a new gcoOS object. */
+gceSTATUS
+gcoOS_Construct(
+ IN gctPOINTER Context,
+ OUT gcoOS * Os
+ );
+
+/* Destroy an gcoOS object. */
+gceSTATUS
+gcoOS_Destroy(
+ IN gcoOS Os
+ );
+
+/* Get the base address for the physical memory. */
+gceSTATUS
+gcoOS_GetBaseAddress(
+ IN gcoOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ );
+
+/* Allocate memory from the heap. */
+gceSTATUS
+gcoOS_Allocate(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free allocated memory. */
+gceSTATUS
+gcoOS_Free(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoOS_AllocateMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoOS_FreeMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory
+ );
+
+/* Allocate contiguous memory. */
+gceSTATUS
+gcoOS_AllocateContiguous(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free contiguous memory. */
+gceSTATUS
+gcoOS_FreeContiguous(
+ IN gcoOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/* Map user memory. */
+gceSTATUS
+gcoOS_MapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ );
+
+/* Unmap user memory. */
+gceSTATUS
+gcoOS_UnmapUserMemory(
+ IN gcoOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ );
+
+/* Device I/O Control call to the kernel HAL layer. */
+gceSTATUS
+gcoOS_DeviceControl(
+ IN gcoOS Os,
+ IN gctUINT32 IoControlCode,
+ IN gctPOINTER InputBuffer,
+ IN gctSIZE_T InputBufferSize,
+ IN gctPOINTER OutputBuffer,
+ IN gctSIZE_T OutputBufferSize
+ );
+
+/* Allocate non paged memory. */
+gceSTATUS gcoOS_AllocateNonPagedMemory(
+ IN gcoOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+/* Free non paged memory. */
+gceSTATUS gcoOS_FreeNonPagedMemory(
+ IN gcoOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ );
+
+typedef enum _gceFILE_MODE
+{
+ gcvFILE_CREATE = 0,
+ gcvFILE_APPEND,
+ gcvFILE_READ,
+ gcvFILE_CREATETEXT,
+ gcvFILE_APPENDTEXT,
+ gcvFILE_READTEXT,
+}
+gceFILE_MODE;
+
+/* Open a file. */
+gceSTATUS
+gcoOS_Open(
+ IN gcoOS Os,
+ IN gctCONST_STRING FileName,
+ IN gceFILE_MODE Mode,
+ OUT gctFILE * File
+ );
+
+/* Close a file. */
+gceSTATUS
+gcoOS_Close(
+ IN gcoOS Os,
+ IN gctFILE File
+ );
+
+/* Read data from a file. */
+gceSTATUS
+gcoOS_Read(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctPOINTER Data,
+ OUT gctSIZE_T * ByteRead
+ );
+
+/* Write data to a file. */
+gceSTATUS
+gcoOS_Write(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+typedef enum _gceFILE_WHENCE
+{
+ gcvFILE_SEEK_SET,
+ gcvFILE_SEEK_CUR,
+ gcvFILE_SEEK_END
+}
+gceFILE_WHENCE;
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_Seek(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Offset,
+ IN gceFILE_WHENCE Whence
+ );
+
+/* Set the current position of a file. */
+gceSTATUS
+gcoOS_SetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ IN gctUINT32 Position
+ );
+
+/* Get the current position of a file. */
+gceSTATUS
+gcoOS_GetPos(
+ IN gcoOS Os,
+ IN gctFILE File,
+ OUT gctUINT32 * Position
+ );
+
+/* Perform a memory copy. */
+gceSTATUS
+gcoOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ );
+
+/* Perform a memory fill. */
+gceSTATUS
+gcoOS_MemFill(
+ IN gctPOINTER Destination,
+ IN gctUINT8 Filler,
+ IN gctSIZE_T Bytes
+ );
+
+/* Zero memory. */
+gceSTATUS
+gcoOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Find the last occurance of a character inside a string. */
+gceSTATUS
+gcoOS_StrFindReverse(
+ IN gctCONST_STRING String,
+ IN gctINT8 Character,
+ OUT gctSTRING * Output
+ );
+
+gceSTATUS
+gcoOS_StrLen(
+ IN gctCONST_STRING String,
+ OUT gctSIZE_T * Length
+ );
+
+gceSTATUS
+gcoOS_StrDup(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ OUT gctSTRING * Target
+ );
+
+/* Copy a string. */
+gceSTATUS
+gcoOS_StrCopySafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Append a string. */
+gceSTATUS
+gcoOS_StrCatSafe(
+ IN gctSTRING Destination,
+ IN gctSIZE_T DestinationSize,
+ IN gctCONST_STRING Source
+ );
+
+/* Compare two strings. */
+gceSTATUS
+gcoOS_StrCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2
+ );
+
+/* Compare characters of two strings. */
+gceSTATUS
+gcoOS_StrNCmp(
+ IN gctCONST_STRING String1,
+ IN gctCONST_STRING String2,
+ IN gctSIZE_T Count
+ );
+
+/* Convert string to float. */
+gceSTATUS
+gcoOS_StrToFloat(
+ IN gctCONST_STRING String,
+ OUT gctFLOAT * Float
+ );
+
+/* Convert string to integer. */
+gceSTATUS
+gcoOS_StrToInt(
+ IN gctCONST_STRING String,
+ OUT gctINT * Int
+ );
+
+gceSTATUS
+gcoOS_MemCmp(
+ IN gctCONST_POINTER Memory1,
+ IN gctCONST_POINTER Memory2,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_PrintStrSafe(
+ OUT gctSTRING String,
+ IN gctSIZE_T StringSize,
+ IN OUT gctUINT * Offset,
+ IN gctCONST_STRING Format,
+ ...
+ );
+
+gceSTATUS
+gcoOS_PrintStrVSafe(
+ OUT gctSTRING String,
+ IN gctSIZE_T StringSize,
+ IN OUT gctUINT * Offset,
+ IN gctCONST_STRING Format,
+ IN gctPOINTER Arguments
+ );
+
+gceSTATUS
+gcoOS_LoadLibrary(
+ IN gcoOS Os,
+ IN gctCONST_STRING Library,
+ OUT gctHANDLE * Handle
+ );
+
+gceSTATUS
+gcoOS_FreeLibrary(
+ IN gcoOS Os,
+ IN gctHANDLE Handle
+ );
+
+gceSTATUS
+gcoOS_GetProcAddress(
+ IN gcoOS Os,
+ IN gctHANDLE Handle,
+ IN gctCONST_STRING Name,
+ OUT gctPOINTER * Function
+ );
+
+gceSTATUS
+gcoOS_Compact(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_ProfileStart(
+ IN gcoOS Os
+ );
+
+gceSTATUS
+gcoOS_ProfileEnd(
+ IN gcoOS Os,
+ IN gctCONST_STRING Title
+ );
+
+gceSTATUS
+gcoOS_SetProfileSetting(
+ IN gcoOS Os,
+ IN gctBOOL Enable,
+ IN gctCONST_STRING FileName
+ );
+
+/* Query the video memory. */
+gceSTATUS
+gcoOS_QueryVideoMemory(
+ IN gcoOS Os,
+ OUT gctPHYS_ADDR * InternalAddress,
+ OUT gctSIZE_T * InternalSize,
+ OUT gctPHYS_ADDR * ExternalAddress,
+ OUT gctSIZE_T * ExternalSize,
+ OUT gctPHYS_ADDR * ContiguousAddress,
+ OUT gctSIZE_T * ContiguousSize
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Atoms ----------------------------------------------------------------*/
+
+typedef struct gcsATOM * gcsATOM_PTR;
+
+/* Construct an atom. */
+gceSTATUS
+gcoOS_AtomConstruct(
+ IN gcoOS Os,
+ OUT gcsATOM_PTR * Atom
+ );
+
+/* Destroy an atom. */
+gceSTATUS
+gcoOS_AtomDestroy(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom
+ );
+
+/* Increment an atom. */
+gceSTATUS
+gcoOS_AtomIncrement(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+/* Decrement an atom. */
+gceSTATUS
+gcoOS_AtomDecrement(
+ IN gcoOS Os,
+ IN gcsATOM_PTR Atom,
+ OUT gctINT32_PTR OldValue
+ );
+
+gctHANDLE
+gcoOS_GetCurrentProcessID(
+ void
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Time -----------------------------------------------------------------*/
+
+/* Get the number of milliseconds since the system started. */
+gctUINT32
+gcoOS_GetTicks(
+ void
+ );
+
+/* Get time in microseconds. */
+gceSTATUS
+gcoOS_GetTime(
+ gctUINT64_PTR Time
+ );
+
+/* Get CPU usage in microseconds. */
+gceSTATUS
+gcoOS_GetCPUTime(
+ gctUINT64_PTR CPUTime
+ );
+
+/* Get memory usage. */
+gceSTATUS
+gcoOS_GetMemoryUsage(
+ gctUINT32_PTR MaxRSS,
+ gctUINT32_PTR IxRSS,
+ gctUINT32_PTR IdRSS,
+ gctUINT32_PTR IsRSS
+ );
+
+/* Delay a number of microseconds. */
+gceSTATUS
+gcoOS_Delay(
+ IN gcoOS Os,
+ IN gctUINT32 Delay
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Mutexes --------------------------------------------------------------*/
+
+/* Create a new mutex. */
+gceSTATUS
+gcoOS_CreateMutex(
+ IN gcoOS Os,
+ OUT gctPOINTER * Mutex
+ );
+
+/* Delete a mutex. */
+gceSTATUS
+gcoOS_DeleteMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/* Acquire a mutex. */
+gceSTATUS
+gcoOS_AcquireMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ );
+
+/* Release a mutex. */
+gceSTATUS
+gcoOS_ReleaseMutex(
+ IN gcoOS Os,
+ IN gctPOINTER Mutex
+ );
+
+/*----------------------------------------------------------------------------*/
+/*----- Signals --------------------------------------------------------------*/
+
+/* Create a signal. */
+gceSTATUS
+gcoOS_CreateSignal(
+ IN gcoOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ );
+
+/* Destroy a signal. */
+gceSTATUS
+gcoOS_DestroySignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal
+ );
+
+/* Signal a signal. */
+gceSTATUS
+gcoOS_Signal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ );
+
+/* Wait for a signal. */
+gceSTATUS
+gcoOS_WaitSignal(
+ IN gcoOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ );
+
+/* Write a register. */
+gceSTATUS
+gcoOS_WriteRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ );
+
+/* Read a register. */
+gceSTATUS
+gcoOS_ReadRegister(
+ IN gcoOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ );
+
+gceSTATUS
+gcoOS_CacheFlush(
+ IN gcoOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoOS_CacheInvalidate(
+ IN gcoOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+
+/*******************************************************************************
+** gcoMATH object
+*/
+
+#define gcdPI 3.14159265358979323846f
+
+gctUINT32
+gcoMATH_Log2in5dot5(
+ IN gctINT X
+ );
+
+gctFLOAT
+gcoMATH_Sine(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Cosine(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Floor(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Ceiling(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_SquareRoot(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Log2(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Power(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+gctFLOAT
+gcoMATH_Modulo(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+gctFLOAT
+gcoMATH_Exp(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Absolute(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_ArcCosine(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Tangent(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_UInt2Float(
+ IN gctUINT X
+ );
+
+gctUINT
+gcoMATH_Float2UInt(
+ IN gctFLOAT X
+ );
+
+gctFLOAT
+gcoMATH_Multiply(
+ IN gctFLOAT X,
+ IN gctFLOAT Y
+ );
+
+/******************************************************************************\
+**************************** Coordinate Structures *****************************
+\******************************************************************************/
+
+typedef struct _gcsPOINT
+{
+ gctINT32 x;
+ gctINT32 y;
+}
+gcsPOINT;
+
+typedef struct _gcsSIZE
+{
+ gctINT32 width;
+ gctINT32 height;
+}
+gcsSIZE;
+
+typedef struct _gcsRECT
+{
+ gctINT32 left;
+ gctINT32 top;
+ gctINT32 right;
+ gctINT32 bottom;
+}
+gcsRECT;
+
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*------------------------------- gcoSURF Common ------------------------------*/
+
+/* Color format classes. */
+typedef enum _gceFORMAT_CLASS
+{
+ gcvFORMAT_CLASS_RGBA = 4500,
+ gcvFORMAT_CLASS_YUV,
+ gcvFORMAT_CLASS_INDEX,
+ gcvFORMAT_CLASS_LUMINANCE,
+ gcvFORMAT_CLASS_BUMP,
+ gcvFORMAT_CLASS_DEPTH,
+}
+gceFORMAT_CLASS;
+
+/* Special enums for width field in gcsFORMAT_COMPONENT. */
+typedef enum _gceCOMPONENT_CONTROL
+{
+ gcvCOMPONENT_NOTPRESENT = 0x00,
+ gcvCOMPONENT_DONTCARE = 0x80,
+ gcvCOMPONENT_WIDTHMASK = 0x7F,
+ gcvCOMPONENT_ODD = 0x80
+}
+gceCOMPONENT_CONTROL;
+
+/* Color format component parameters. */
+typedef struct _gcsFORMAT_COMPONENT
+{
+ gctUINT8 start;
+ gctUINT8 width;
+}
+gcsFORMAT_COMPONENT;
+
+/* RGBA color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_RGBA
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT red;
+ gcsFORMAT_COMPONENT green;
+ gcsFORMAT_COMPONENT blue;
+}
+gcsFORMAT_CLASS_TYPE_RGBA;
+
+/* YUV color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_YUV
+{
+ gcsFORMAT_COMPONENT y;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT v;
+}
+gcsFORMAT_CLASS_TYPE_YUV;
+
+/* Index color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_INDEX
+{
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_INDEX;
+
+/* Luminance color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_LUMINANCE
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT value;
+}
+gcsFORMAT_CLASS_TYPE_LUMINANCE;
+
+/* Bump map color format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_BUMP
+{
+ gcsFORMAT_COMPONENT alpha;
+ gcsFORMAT_COMPONENT l;
+ gcsFORMAT_COMPONENT v;
+ gcsFORMAT_COMPONENT u;
+ gcsFORMAT_COMPONENT q;
+ gcsFORMAT_COMPONENT w;
+}
+gcsFORMAT_CLASS_TYPE_BUMP;
+
+/* Depth and stencil format class. */
+typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
+{
+ gcsFORMAT_COMPONENT depth;
+ gcsFORMAT_COMPONENT stencil;
+}
+gcsFORMAT_CLASS_TYPE_DEPTH;
+
+/* Format parameters. */
+typedef struct _gcsSURF_FORMAT_INFO
+{
+ /* Format code and class. */
+ gceSURF_FORMAT format;
+ gceFORMAT_CLASS fmtClass;
+
+ /* The size of one pixel in bits. */
+ gctUINT8 bitsPerPixel;
+
+ /* Component swizzle. */
+ gceSURF_SWIZZLE swizzle;
+
+ /* Some formats have two neighbour pixels interleaved together. */
+ /* To describe such format, set the flag to 1 and add another */
+ /* like this one describing the odd pixel format. */
+ gctUINT8 interleaved;
+
+ /* Format components. */
+ union
+ {
+ gcsFORMAT_CLASS_TYPE_BUMP bump;
+ gcsFORMAT_CLASS_TYPE_RGBA rgba;
+ gcsFORMAT_CLASS_TYPE_YUV yuv;
+ gcsFORMAT_CLASS_TYPE_LUMINANCE lum;
+ gcsFORMAT_CLASS_TYPE_INDEX index;
+ gcsFORMAT_CLASS_TYPE_DEPTH depth;
+ } u;
+}
+gcsSURF_FORMAT_INFO;
+
+/* Frame buffer information. */
+typedef struct _gcsSURF_FRAMEBUFFER
+{
+ gctPOINTER logical;
+ gctUINT width, height;
+ gctINT stride;
+ gceSURF_FORMAT format;
+}
+gcsSURF_FRAMEBUFFER;
+
+/* Generic pixel component descriptors. */
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_X8XX;
+extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_8XXX;
+
+typedef enum _gceORIENTATION
+{
+ gcvORIENTATION_TOP_BOTTOM,
+ gcvORIENTATION_BOTTOM_TOP,
+}
+gceORIENTATION;
+
+
+/* Construct a new gcoSURF object. */
+gceSTATUS
+gcoSURF_Construct(
+ IN gcoHAL Hal,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+/* Destroy an gcoSURF object. */
+gceSTATUS
+gcoSURF_Destroy(
+ IN gcoSURF Surface
+ );
+
+/* Map user-allocated surface. */
+gceSTATUS
+gcoSURF_MapUserSurface(
+ IN gcoSURF Surface,
+ IN gctUINT Alignment,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* Set the color type of the surface. */
+gceSTATUS
+gcoSURF_SetColorType(
+ IN gcoSURF Surface,
+ IN gceSURF_COLOR_TYPE ColorType
+ );
+
+/* Get the color type of the surface. */
+gceSTATUS
+gcoSURF_GetColorType(
+ IN gcoSURF Surface,
+ OUT gceSURF_COLOR_TYPE *ColorType
+ );
+
+/* Set the surface ration angle. */
+gceSTATUS
+gcoSURF_SetRotation(
+ IN gcoSURF Surface,
+ IN gceSURF_ROTATION Rotation
+ );
+
+/* Verify and return the state of the tile status mechanism. */
+gceSTATUS
+gcoSURF_IsTileStatusSupported(
+ IN gcoSURF Surface
+ );
+
+/* Enable tile status for the specified surface. */
+gceSTATUS
+gcoSURF_EnableTileStatus(
+ IN gcoSURF Surface
+ );
+
+/* Disable tile status for the specified surface. */
+gceSTATUS
+gcoSURF_DisableTileStatus(
+ IN gcoSURF Surface,
+ IN gctBOOL Decompress
+ );
+
+/* Get surface size. */
+gceSTATUS
+gcoSURF_GetSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctUINT * Depth
+ );
+
+/* Get surface aligned sizes. */
+gceSTATUS
+gcoSURF_GetAlignedSize(
+ IN gcoSURF Surface,
+ OUT gctUINT * Width,
+ OUT gctUINT * Height,
+ OUT gctINT * Stride
+ );
+
+/* Get surface type and format. */
+gceSTATUS
+gcoSURF_GetFormat(
+ IN gcoSURF Surface,
+ OUT gceSURF_TYPE * Type,
+ OUT gceSURF_FORMAT * Format
+ );
+
+/* Lock the surface. */
+gceSTATUS
+gcoSURF_Lock(
+ IN gcoSURF Surface,
+ IN OUT gctUINT32 * Address,
+ IN OUT gctPOINTER * Memory
+ );
+
+/* Unlock the surface. */
+gceSTATUS
+gcoSURF_Unlock(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory
+ );
+
+/* Return pixel format parameters. */
+gceSTATUS
+gcoSURF_QueryFormat(
+ IN gceSURF_FORMAT Format,
+ OUT gcsSURF_FORMAT_INFO_PTR * Info
+ );
+
+/* Compute the color pixel mask. */
+gceSTATUS
+gcoSURF_ComputeColorMask(
+ IN gcsSURF_FORMAT_INFO_PTR Format,
+ OUT gctUINT32_PTR ColorMask
+ );
+
+/* Flush the surface. */
+gceSTATUS
+gcoSURF_Flush(
+ IN gcoSURF Surface
+ );
+
+/* Fill surface with a value. */
+gceSTATUS
+gcoSURF_Fill(
+ IN gcoSURF Surface,
+ IN gcsPOINT_PTR Origin,
+ IN gcsSIZE_PTR Size,
+ IN gctUINT32 Value,
+ IN gctUINT32 Mask
+ );
+
+/* Alpha blend two surfaces together. */
+gceSTATUS
+gcoSURF_Blend(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsPOINT_PTR SrcOrig,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsSIZE_PTR Size,
+ IN gceSURF_BLEND_MODE Mode
+ );
+
+/* Create a new gcoSURF wrapper object. */
+gceSTATUS
+gcoSURF_ConstructWrapper(
+ IN gcoHAL Hal,
+ OUT gcoSURF * Surface
+ );
+
+/* Set the underlying buffer for the surface wrapper. */
+gceSTATUS
+gcoSURF_SetBuffer(
+ IN gcoSURF Surface,
+ IN gceSURF_TYPE Type,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Stride,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Physical
+ );
+
+/* Set the size of the surface in pixels and map the underlying buffer. */
+gceSTATUS
+gcoSURF_SetWindow(
+ IN gcoSURF Surface,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height
+ );
+
+/* Increase reference count of the surface. */
+gceSTATUS
+gcoSURF_ReferenceSurface(
+ IN gcoSURF Surface
+ );
+
+/* Get surface reference count. */
+gceSTATUS
+gcoSURF_QueryReferenceCount(
+ IN gcoSURF Surface,
+ OUT gctINT32 * ReferenceCount
+ );
+
+/* Set surface orientation. */
+gceSTATUS
+gcoSURF_SetOrientation(
+ IN gcoSURF Surface,
+ IN gceORIENTATION Orientation
+ );
+
+/* Query surface orientation. */
+gceSTATUS
+gcoSURF_QueryOrientation(
+ IN gcoSURF Surface,
+ OUT gceORIENTATION * Orientation
+ );
+
+/******************************************************************************\
+********************************* gcoDUMP Object ********************************
+\******************************************************************************/
+
+/* Construct a new gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Construct(
+ IN gcoOS Os,
+ IN gcoHAL Hal,
+ OUT gcoDUMP * Dump
+ );
+
+/* Destroy a gcoDUMP object. */
+gceSTATUS
+gcoDUMP_Destroy(
+ IN gcoDUMP Dump
+ );
+
+/* Enable/disable dumping. */
+gceSTATUS
+gcoDUMP_Control(
+ IN gcoDUMP Dump,
+ IN gctSTRING FileName
+ );
+
+gceSTATUS
+gcoDUMP_IsEnabled(
+ IN gcoDUMP Dump,
+ OUT gctBOOL * Enabled
+ );
+
+/* Add surface. */
+gceSTATUS
+gcoDUMP_AddSurface(
+ IN gcoDUMP Dump,
+ IN gctINT32 Width,
+ IN gctINT32 Height,
+ IN gceSURF_FORMAT PixelFormat,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount
+ );
+
+/* Mark the beginning of a frame. */
+gceSTATUS
+gcoDUMP_FrameBegin(
+ IN gcoDUMP Dump
+ );
+
+/* Mark the end of a frame. */
+gceSTATUS
+gcoDUMP_FrameEnd(
+ IN gcoDUMP Dump
+ );
+
+/* Dump data. */
+gceSTATUS
+gcoDUMP_DumpData(
+ IN gcoDUMP Dump,
+ IN gceDUMP_TAG Type,
+ IN gctUINT32 Address,
+ IN gctSIZE_T ByteCount,
+ IN gctCONST_POINTER Data
+ );
+
+/* Delete an address. */
+gceSTATUS
+gcoDUMP_Delete(
+ IN gcoDUMP Dump,
+ IN gctUINT32 Address
+ );
+
+/******************************************************************************\
+******************************* gcsRECT Structure ******************************
+\******************************************************************************/
+
+/* Initialize rectangle structure. */
+gceSTATUS
+gcsRECT_Set(
+ OUT gcsRECT_PTR Rect,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Return the width of the rectangle. */
+gceSTATUS
+gcsRECT_Width(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Width
+ );
+
+/* Return the height of the rectangle. */
+gceSTATUS
+gcsRECT_Height(
+ IN gcsRECT_PTR Rect,
+ OUT gctINT32 * Height
+ );
+
+/* Ensure that top left corner is to the left and above the right bottom. */
+gceSTATUS
+gcsRECT_Normalize(
+ IN OUT gcsRECT_PTR Rect
+ );
+
+/* Compare two rectangles. */
+gceSTATUS
+gcsRECT_IsEqual(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * Equal
+ );
+
+/* Compare the sizes of two rectangles. */
+gceSTATUS
+gcsRECT_IsOfEqualSize(
+ IN gcsRECT_PTR Rect1,
+ IN gcsRECT_PTR Rect2,
+ OUT gctBOOL * EqualSize
+ );
+
+
+/******************************************************************************\
+**************************** gcsBOUNDARY Structure *****************************
+\******************************************************************************/
+
+typedef struct _gcsBOUNDARY
+{
+ gctINT x;
+ gctINT y;
+ gctINT width;
+ gctINT height;
+}
+gcsBOUNDARY;
+
+/******************************************************************************\
+********************************* gcoHEAP Object ********************************
+\******************************************************************************/
+
+typedef struct _gcoHEAP * gcoHEAP;
+
+/* Construct a new gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Construct(
+ IN gcoOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gcoHEAP * Heap
+ );
+
+/* Destroy an gcoHEAP object. */
+gceSTATUS
+gcoHEAP_Destroy(
+ IN gcoHEAP Heap
+ );
+
+/* Allocate memory. */
+gceSTATUS
+gcoHEAP_Allocate(
+ IN gcoHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Node
+ );
+
+/* Free memory. */
+gceSTATUS
+gcoHEAP_Free(
+ IN gcoHEAP Heap,
+ IN gctPOINTER Node
+ );
+
+/* Profile the heap. */
+gceSTATUS
+gcoHEAP_ProfileStart(
+ IN gcoHEAP Heap
+ );
+
+gceSTATUS
+gcoHEAP_ProfileEnd(
+ IN gcoHEAP Heap,
+ IN gctCONST_STRING Title
+ );
+
+#if defined gcdHAL_TEST
+gceSTATUS
+gcoHEAP_Test(
+ IN gcoHEAP Heap,
+ IN gctSIZE_T Vectors,
+ IN gctSIZE_T MaxSize
+ );
+#endif
+
+/******************************************************************************\
+******************************* Debugging Macros *******************************
+\******************************************************************************/
+
+void
+gcoOS_SetDebugLevel(
+ IN gctUINT32 Level
+ );
+
+void
+gcoOS_SetDebugZone(
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ );
+
+void
+gcoOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ );
+
+void
+gcoOS_SetDebugFile(
+ IN gctCONST_STRING FileName
+ );
+
+/*******************************************************************************
+**
+** gcmFATAL
+**
+** Print a message to the debugger and execute a break point.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcdDEBUG
+# define gcmFATAL gcoOS_DebugFatal
+# define gcmkFATAL gckOS_DebugFatal
+#elif gcdHAS_ELLIPSES
+# define gcmFATAL(...)
+# define gcmkFATAL(...)
+#else
+ gcmINLINE static void
+ __dummy_fatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmFATAL __dummy_fatal
+# define gcmkFATAL __dummy_fatal
+#endif
+
+#define gcmENUM2TEXT(e) case e: return #e
+
+/*******************************************************************************
+**
+** gcmTRACE
+**
+** Print a message to the debugfer if the correct level has been set. In
+** retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** level Level of message.
+** message Message.
+** ... Optional arguments.
+*/
+#define gcvLEVEL_NONE -1
+#define gcvLEVEL_ERROR 0
+#define gcvLEVEL_WARNING 1
+#define gcvLEVEL_INFO 2
+#define gcvLEVEL_VERBOSE 3
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+void
+
+gcoOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcdDEBUG
+# define gcmTRACE gcoOS_DebugTrace
+# define gcmkTRACE gckOS_DebugTrace
+#elif gcdHAS_ELLIPSES
+# define gcmTRACE(...)
+# define gcmkTRACE(...)
+#else
+ gcmINLINE static void
+ __dummy_trace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmTRACE __dummy_trace
+# define gcmkTRACE __dummy_trace
+#endif
+
+/* Debug zones. */
+#define gcvZONE_OS (1 << 0)
+#define gcvZONE_HARDWARE (1 << 1)
+#define gcvZONE_HEAP (1 << 2)
+
+/* Kernel zones. */
+#define gcvZONE_KERNEL (1 << 3)
+#define gcvZONE_VIDMEM (1 << 4)
+#define gcvZONE_COMMAND (1 << 5)
+#define gcvZONE_DRIVER (1 << 6)
+#define gcvZONE_CMODEL (1 << 7)
+#define gcvZONE_MMU (1 << 8)
+#define gcvZONE_EVENT (1 << 9)
+#define gcvZONE_DEVICE (1 << 10)
+
+/* User zones. */
+#define gcvZONE_HAL (1 << 3)
+#define gcvZONE_BUFFER (1 << 4)
+#define gcvZONE_CONTEXT (1 << 5)
+#define gcvZONE_SURFACE (1 << 6)
+#define gcvZONE_INDEX (1 << 7)
+#define gcvZONE_STREAM (1 << 8)
+#define gcvZONE_TEXTURE (1 << 9)
+#define gcvZONE_2D (1 << 10)
+#define gcvZONE_3D (1 << 11)
+#define gcvZONE_COMPILER (1 << 12)
+#define gcvZONE_MEMORY (1 << 13)
+#define gcvZONE_STATE (1 << 14)
+#define gcvZONE_AUX (1 << 15)
+
+/* API definitions. */
+#define gcvZONE_API_HAL (0 << 28)
+#define gcvZONE_API_EGL (1 << 28)
+#define gcvZONE_API_ES11 (2 << 28)
+#define gcvZONE_API_ES20 (3 << 28)
+#define gcvZONE_API_VG11 (4 << 28)
+#define gcvZONE_API_GL (5 << 28)
+#define gcvZONE_API_DFB (6 << 28)
+#define gcvZONE_API_GDI (7 << 28)
+#define gcvZONE_API_D3D (8 << 28)
+
+#define gcmZONE_GET_API(zone) ((zone) >> 28)
+#define gcdZONE_MASK 0x0FFFFFFF
+
+/* Handy zones. */
+#define gcvZONE_NONE 0
+#define gcvZONE_ALL gcdZONE_MASK
+
+/*******************************************************************************
+**
+** gcmTRACE_ZONE
+**
+** Print a message to the debugger if the correct level and zone has been
+** set. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** Level Level of message.
+** Zone Zone of message.
+** Message Message.
+** ... Optional arguments.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+#if gcdDEBUG
+# define gcmTRACE_ZONE gcoOS_DebugTraceZone
+# define gcmkTRACE_ZONE gckOS_DebugTraceZone
+#elif gcdHAS_ELLIPSES
+# define gcmTRACE_ZONE(...)
+# define gcmkTRACE_ZONE(...)
+#else
+ gcmINLINE static void
+ __dummy_trace_zone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmTRACE_ZONE __dummy_trace_zone
+# define gcmkTRACE_ZONE __dummy_trace_zone
+#endif
+
+/******************************************************************************\
+******************************** Logging Macros ********************************
+\******************************************************************************/
+
+#define gcdHEADER_LEVEL gcvLEVEL_VERBOSE
+
+#define gcmHEADER() \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmHEADER_ARG(Text, ...) \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_header_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmHEADER_ARG __dummy_header_arg
+#endif
+
+#define gcmFOOTER() \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): status=%d", \
+ __FUNCTION__, __LINE__, status)
+
+#define gcmFOOTER_NO() \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmFOOTER_ARG(Text, ...) \
+ gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): " Text, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_footer_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmFOOTER_ARG __dummy_footer_arg
+#endif
+
+#define gcmkHEADER() \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmkHEADER_ARG(Text, ...) \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_kheader_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkHEADER_ARG __dummy_kheader_arg
+#endif
+
+#define gcmkFOOTER() \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): status=%d", \
+ __FUNCTION__, __LINE__, status)
+
+#define gcmkFOOTER_NO() \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d)", __FUNCTION__, __LINE__)
+
+#if gcdHAS_ELLIPSES
+# define gcmkFOOTER_ARG(Text, ...) \
+ gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
+ "--%s(%d): " Text, \
+ __FUNCTION__, __LINE__, __VA_ARGS__)
+#else
+ gcmINLINE static void
+ __dummy_kfooter_arg(
+ IN gctCONST_STRING Text,
+ ...
+ )
+ {
+ }
+# define gcmkFOOTER_ARG __dummy_kfooter_arg
+#endif
+
+#define gcmOPT_VALUE(ptr) (((ptr) == gcvNULL) ? 0 : *(ptr))
+#define gcmOPT_POINTER(ptr) (((ptr) == gcvNULL) ? gcvNULL : *(ptr))
+
+void
+gcoOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ );
+#define gcmPRINT gcoOS_Print
+#define gcmkPRINT gckOS_Print
+
+/*******************************************************************************
+**
+** gcmDUMP
+**
+** Print a dump message.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+#if gcdDUMP
+ gceSTATUS
+ gcfDump(
+ IN gcoOS Os,
+ IN gctCONST_STRING String,
+ ...
+ );
+# define gcmDUMP gcfDump
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP(...)
+#else
+ gcmINLINE static void
+ __dummy_dump(
+ IN gcoOS Os,
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP __dummy_dump
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_DATA
+**
+** Add data to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP
+ gceSTATUS
+ gcfDumpData(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_DATA gcfDumpData
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_DATA(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_data(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_DATA __dummy_dump_data
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_BUFFER
+**
+** Print a buffer to the dump.
+**
+** ARGUMENTS:
+**
+** gctSTRING Tag
+** Tag for dump.
+**
+** gctUINT32 Physical
+** Physical address of buffer.
+**
+** gctPOINTER Logical
+** Logical address of buffer.
+**
+** gctUINT32 Offset
+** Offset into buffer.
+**
+** gctSIZE_T Bytes
+** Number of bytes.
+*/
+
+#if gcdDUMP
+gceSTATUS
+gcfDumpBuffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes
+ );
+# define gcmDUMP_BUFFER gcfDumpBuffer
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_BUFFER(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_buffer(
+ IN gcoOS Os,
+ IN gctSTRING Tag,
+ IN gctUINT32 Physical,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes
+ )
+ {
+ }
+# define gcmDUMP_BUFFER __dummy_dump_buffer
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API
+**
+** Print a dump message for a high level API prefixed by the function name.
+**
+** ARGUMENTS:
+**
+** gctSTRING Message.
+**
+** ... Optional arguments.
+*/
+#if gcdDUMP_API
+ gceSTATUS
+ gcfDumpApi(
+ IN gctCONST_STRING String,
+ ...
+ );
+# define gcmDUMP_API gcfDumpApi
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_API(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api(
+ IN gctCONST_STRING Message,
+ ...
+ )
+ {
+ }
+# define gcmDUMP_API __dummy_dump_api
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY
+**
+** Print an array of data.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Size.
+*/
+#if gcdDUMP_API
+ gceSTATUS
+ gcfDumpArray(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Size
+ );
+# define gcmDUMP_API_ARRAY gcfDumpArray
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_API_ARRAY(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Size
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY __dummy_dump_api_array
+#endif
+
+/*******************************************************************************
+**
+** gcmDUMP_API_ARRAY_TOKEN
+**
+** Print an array of data terminated by a token.
+**
+** ARGUMENTS:
+**
+** gctUINT32_PTR Pointer to array.
+** gctUINT32 Termination.
+*/
+#if gcdDUMP_API
+ gceSTATUS
+ gcfDumpArrayToken(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Termination
+ );
+# define gcmDUMP_API_ARRAY_TOKEN gcfDumpArrayToken
+#elif gcdHAS_ELLIPSES
+# define gcmDUMP_API_ARRAY_TOKEN(...)
+#else
+ gcmINLINE static void
+ __dummy_dump_api_array_token(
+ IN gctCONST_POINTER Data,
+ IN gctUINT32 Termination
+ )
+ {
+ }
+# define gcmDUMP_API_ARRAY_TOKEN __dummy_dump_api_array_token
+#endif
+
+/*******************************************************************************
+**
+** gcmTRACE_RELEASE
+**
+** Print a message to the shader debugger.
+**
+** ARGUMENTS:
+**
+** message Message.
+** ... Optional arguments.
+*/
+
+#define gcmTRACE_RELEASE gcoOS_DebugShaderTrace
+
+void
+gcoOS_DebugShaderTrace(
+ IN gctCONST_STRING Message,
+ ...
+ );
+
+void
+gcoOS_SetDebugShaderFiles(
+ IN gctCONST_STRING VSFileName,
+ IN gctCONST_STRING FSFileName
+ );
+
+void
+gcoOS_SetDebugShaderFileType(
+ IN gctUINT32 ShaderType
+ );
+
+/*******************************************************************************
+**
+** gcmBREAK
+**
+** Break into the debugger. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** None.
+*/
+
+void
+gcoOS_DebugBreak(
+ void
+ );
+
+void
+gckOS_DebugBreak(
+ void
+ );
+
+#if gcdDEBUG
+# define gcmBREAK gcoOS_DebugBreak
+# define gcmkBREAK gckOS_DebugBreak
+#else
+# define gcmBREAK()
+# define gcmkBREAK()
+#endif
+
+/*******************************************************************************
+**
+** gcmASSERT
+**
+** Evaluate an expression and break into the debugger if the expression
+** evaluates to false. In retail mode this macro does nothing.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcdDEBUG
+# define _gcmASSERT(prefix, exp) \
+ do \
+ { \
+ if (!(exp)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ASSERT at %s(%d) in " __FILE__, \
+ __FUNCTION__, __LINE__); \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ "(%s)", #exp); \
+ prefix##BREAK(); \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmASSERT(exp) _gcmASSERT(gcm, exp)
+# define gcmkASSERT(exp) _gcmASSERT(gcmk, exp)
+#else
+# define gcmASSERT(exp)
+# define gcmkASSERT(exp)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY
+**
+** Verify if an expression returns true. If the expression does not
+** evaluates to true, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** exp Expression to evaluate.
+*/
+#if gcdDEBUG
+# define gcmVERIFY(exp) gcmASSERT(exp)
+# define gcmkVERIFY(exp) gcmkASSERT(exp)
+#else
+# define gcmVERIFY(exp) exp
+# define gcmkVERIFY(exp) exp
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_OK
+**
+** Verify a fucntion returns gcvSTATUS_OK. If the function does not return
+** gcvSTATUS_OK, an assertion will happen in debug mode.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+
+void
+gcoOS_Verify(
+ IN gceSTATUS Status
+ );
+
+void
+gckOS_Verify(
+ IN gceSTATUS Status
+ );
+
+#if gcdDEBUG
+# define gcmVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ gcoOS_Verify(verifyStatus); \
+ gcmASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+# define gcmkVERIFY_OK(func) \
+ do \
+ { \
+ gceSTATUS verifyStatus = func; \
+ gckOS_Verify(verifyStatus); \
+ gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
+ } \
+ while (gcvFALSE)
+#else
+# define gcmVERIFY_OK(func) func
+# define gcmkVERIFY_OK(func) func
+#endif
+
+/*******************************************************************************
+**
+** gcmERR_BREAK
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_BREAK(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_BREAK: status=%d @ %s(%d) in " __FILE__, \
+ status, __FUNCTION__, __LINE__); \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_BREAK(func) _gcmERR_BREAK(gcm, func)
+#define gcmkERR_BREAK(func) _gcmERR_BREAK(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmERR_RETURN
+**
+** Executes a return on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmERR_RETURN(prefix, func) \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ERR_RETURN: status=%d @ %s(%d) in " __FILE__, \
+ status, __FUNCTION__, __LINE__); \
+ return status; \
+ } \
+ do { } while (gcvFALSE)
+#define gcmERR_RETURN(func) _gcmERR_RETURN(gcm, func)
+#define gcmkERR_RETURN(func) _gcmERR_RETURN(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmONERROR
+**
+** Jump to the error handler in case there is an error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmONERROR(prefix, func) \
+ do \
+ { \
+ status = func; \
+ if (gcmIS_ERROR(status)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "ONERROR: status=%d @ %s(%d) in " __FILE__, \
+ status, __FUNCTION__, __LINE__); \
+ goto OnError; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmONERROR(func) _gcmONERROR(gcm, func)
+#define gcmkONERROR(func) _gcmONERROR(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmVERIFY_LOCK
+**
+** Verifies whether the surface is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_LOCK(surfaceInfo) \
+ if (!surfaceInfo->node.valid) \
+ { \
+ status = gcvSTATUS_MEMORY_UNLOCKED; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmVERIFY_NODE_LOCK
+**
+** Verifies whether the surface node is locked.
+**
+** ARGUMENTS:
+**
+** surfaceInfo Pointer to the surface iniformational structure.
+*/
+#define gcmVERIFY_NODE_LOCK(surfaceNode) \
+ if (!surfaceNode->valid) \
+ { \
+ status = gcvSTATUS_MEMORY_UNLOCKED; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmBADOBJECT_BREAK
+**
+** Executes a break statement on bad object.
+**
+** ARGUMENTS:
+**
+** obj Object to test.
+** t Expected type of the object.
+*/
+#define gcmBADOBJECT_BREAK(obj, t) \
+ if ((obj == gcvNULL) \
+ || (((gcsOBJECT *)(obj))->type != t) \
+ ) \
+ { \
+ status = gcvSTATUS_INVALID_OBJECT; \
+ break; \
+ } \
+ do { } while (gcvFALSE)
+
+/*******************************************************************************
+**
+** gcmCHECK_STATUS
+**
+** Executes a break statement on error.
+**
+** ASSUMPTIONS:
+**
+** 'status' variable of gceSTATUS type must be defined.
+**
+** ARGUMENTS:
+**
+** func Function to evaluate.
+*/
+#define _gcmCHECK_STATUS(prefix, func) \
+ do \
+ { \
+ last = func; \
+ if (gcmIS_ERROR(last)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "CHECK_STATUS: status=%d @ %s(%d) in " __FILE__, \
+ last, __FUNCTION__, __LINE__); \
+ status = last; \
+ } \
+ } \
+ while (gcvFALSE)
+#define gcmCHECK_STATUS(func) _gcmCHECK_STATUS(gcm, func)
+#define gcmkCHECK_STATUS(func) _gcmCHECK_STATUS(gcmk, func)
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_ARGUMENT(prefix, arg) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, #prefix "VERIFY_ARGUMENT failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT); \
+ return gcvSTATUS_INVALID_ARGUMENT; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
+# define gcmkVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcmk, arg)
+#else
+# define gcmVERIFY_ARGUMENT(arg)
+# define gcmkVERIFY_ARGUMENT(arg)
+#endif
+
+/*******************************************************************************
+**
+** gcmVERIFY_ARGUMENT_RETURN
+**
+** Assert if an argument does not apply to the specified expression. If
+** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
+** returned from the current function. In retail mode this macro does
+** nothing.
+**
+** ARGUMENTS:
+**
+** arg Argument to evaluate.
+*/
+#ifndef EGL_API_ANDROID
+# define _gcmVERIFY_ARGUMENT_RETURN(prefix, arg, value) \
+ do \
+ { \
+ if (!(arg)) \
+ { \
+ prefix##TRACE(gcvLEVEL_ERROR, \
+ #prefix "gcmVERIFY_ARGUMENT_RETURN failed:"); \
+ prefix##ASSERT(arg); \
+ prefix##FOOTER_ARG("value=%d", value); \
+ return value; \
+ } \
+ } \
+ while (gcvFALSE)
+# define gcmVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcm, arg, value)
+# define gcmkVERIFY_ARGUMENT_RETURN(arg, value) \
+ _gcmVERIFY_ARGUMENT_RETURN(gcmk, arg, value)
+#else
+# define gcmVERIFY_ARGUMENT_RETURN(arg, value)
+# define gcmkVERIFY_ARGUMENT_RETURN(arg, value)
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_base_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* 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_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_driver_h_
+#define __gc_hal_driver_h_
+
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+******************************* I/O Control Codes ******************************
+\******************************************************************************/
+
+#define gcvHAL_CLASS "galcore"
+#define IOCTL_GCHAL_INTERFACE 30000
+#define IOCTL_GCHAL_KERNEL_INTERFACE 30001
+#define IOCTL_GCHAL_TERMINATE 30002
+
+/******************************************************************************\
+********************************* Command Codes ********************************
+\******************************************************************************/
+
+typedef enum _gceHAL_COMMAND_CODES
+{
+ /* Generic query. */
+ gcvHAL_QUERY_VIDEO_MEMORY,
+ gcvHAL_QUERY_CHIP_IDENTITY,
+
+ /* Contiguous memory. */
+ gcvHAL_ALLOCATE_NON_PAGED_MEMORY,
+ gcvHAL_FREE_NON_PAGED_MEMORY,
+ gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY,
+ gcvHAL_FREE_CONTIGUOUS_MEMORY,
+
+ /* Video memory allocation. */
+ gcvHAL_ALLOCATE_VIDEO_MEMORY, /* Enforced alignment. */
+ gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY, /* No alignment. */
+ gcvHAL_FREE_VIDEO_MEMORY,
+
+ /* Physical-to-logical mapping. */
+ gcvHAL_MAP_MEMORY,
+ gcvHAL_UNMAP_MEMORY,
+
+ /* Logical-to-physical mapping. */
+ gcvHAL_MAP_USER_MEMORY,
+ gcvHAL_UNMAP_USER_MEMORY,
+
+ /* Surface lock/unlock. */
+ gcvHAL_LOCK_VIDEO_MEMORY,
+ gcvHAL_UNLOCK_VIDEO_MEMORY,
+
+ /* Event queue. */
+ gcvHAL_EVENT_COMMIT,
+
+ gcvHAL_USER_SIGNAL,
+ gcvHAL_SIGNAL,
+ gcvHAL_WRITE_DATA,
+
+ gcvHAL_COMMIT,
+ gcvHAL_STALL,
+
+ gcvHAL_READ_REGISTER,
+ gcvHAL_WRITE_REGISTER,
+
+ gcvHAL_GET_PROFILE_SETTING,
+ gcvHAL_SET_PROFILE_SETTING,
+
+ gcvHAL_READ_ALL_PROFILE_REGISTERS,
+ gcvHAL_PROFILE_REGISTERS_2D,
+
+ /* Power management. */
+ gcvHAL_SET_POWER_MANAGEMENT_STATE,
+ gcvHAL_QUERY_POWER_MANAGEMENT_STATE,
+
+ gcvHAL_GET_BASE_ADDRESS,
+
+ gcvHAL_SET_IDLE, /* reserved */
+
+ /* Queries. */
+ gcvHAL_QUERY_KERNEL_SETTINGS,
+
+ /* Reset. */
+ gcvHAL_RESET,
+
+ /* Map physical address into handle. */
+ gcvHAL_MAP_PHYSICAL,
+
+ /* Debugger stuff. */
+ gcvHAL_DEBUG,
+
+ /* Cache stuff. */
+ gcvHAL_CACHE,
+}
+gceHAL_COMMAND_CODES;
+
+/******************************************************************************\
+****************************** Interface Structure *****************************
+\******************************************************************************/
+
+#define gcdMAX_PROFILE_FILE_NAME 128
+
+typedef struct _gcsHAL_INTERFACE
+{
+ /* Command code. */
+ gceHAL_COMMAND_CODES command;
+
+ /* Status value. */
+ gceSTATUS status;
+
+ /* Handle to this interface channel. */
+ gctHANDLE handle;
+
+ /* Pid of the client. */
+ gctUINT32 pid;
+
+ /* Union of command structures. */
+ union _u
+ {
+ /* gcvHAL_GET_BASE_ADDRESS */
+ struct _gcsHAL_GET_BASE_ADDRESS
+ {
+ /* Physical memory address of internal memory. */
+ OUT gctUINT32 baseAddress;
+ }
+ GetBaseAddress;
+
+ /* gcvHAL_QUERY_VIDEO_MEMORY */
+ struct _gcsHAL_QUERY_VIDEO_MEMORY
+ {
+ /* Physical memory address of internal memory. */
+ OUT gctPHYS_ADDR internalPhysical;
+
+ /* Size in bytes of internal memory.*/
+ OUT gctSIZE_T internalSize;
+
+ /* Physical memory address of external memory. */
+ OUT gctPHYS_ADDR externalPhysical;
+
+ /* Size in bytes of external memory.*/
+ OUT gctSIZE_T externalSize;
+
+ /* Physical memory address of contiguous memory. */
+ OUT gctPHYS_ADDR contiguousPhysical;
+
+ /* Size in bytes of contiguous memory.*/
+ OUT gctSIZE_T contiguousSize;
+ }
+ QueryVideoMemory;
+
+ /* gcvHAL_QUERY_CHIP_IDENTITY */
+ struct _gcsHAL_QUERY_CHIP_IDENTITY
+ {
+
+ /* Chip model. */
+ OUT gceCHIPMODEL chipModel;
+
+ /* Revision value.*/
+ OUT gctUINT32 chipRevision;
+
+ /* Supported feature fields. */
+ OUT gctUINT32 chipFeatures;
+
+ /* Supported minor feature fields. */
+ OUT gctUINT32 chipMinorFeatures;
+
+ /* Supported minor feature 1 fields. */
+ OUT gctUINT32 chipMinorFeatures1;
+
+ /* Number of streams supported. */
+ OUT gctUINT32 streamCount;
+
+ /* Total number of temporary registers per thread. */
+ OUT gctUINT32 registerMax;
+
+ /* Maximum number of threads. */
+ OUT gctUINT32 threadCount;
+
+ /* Number of shader cores. */
+ OUT gctUINT32 shaderCoreCount;
+
+ /* Size of the vertex cache. */
+ OUT gctUINT32 vertexCacheSize;
+
+ /* Number of entries in the vertex output buffer. */
+ OUT gctUINT32 vertexOutputBufferSize;
+ }
+ QueryChipIdentity;
+
+ /* gcvHAL_MAP_MEMORY */
+ struct _gcsHAL_MAP_MEMORY
+ {
+ /* Physical memory address to map. */
+ IN gctPHYS_ADDR physical;
+
+ /* Number of bytes in physical memory to map. */
+ IN gctSIZE_T bytes;
+
+ /* Address of mapped memory. */
+ OUT gctPOINTER logical;
+ }
+ MapMemory;
+
+ /* gcvHAL_UNMAP_MEMORY */
+ struct _gcsHAL_UNMAP_MEMORY
+ {
+ /* Physical memory address to unmap. */
+ IN gctPHYS_ADDR physical;
+
+ /* Number of bytes in physical memory to unmap. */
+ IN gctSIZE_T bytes;
+
+ /* Address of mapped memory to unmap. */
+ IN gctPOINTER logical;
+ }
+ UnmapMemory;
+
+ /* gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctUINT bytes;
+
+ /* Buffer alignment. */
+ IN gctUINT alignment;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gcuVIDMEM_NODE_PTR node;
+ }
+ AllocateLinearVideoMemory;
+
+ /* gcvHAL_ALLOCATE_VIDEO_MEMORY */
+ struct _gcsHAL_ALLOCATE_VIDEO_MEMORY
+ {
+ /* Width of rectangle to allocate. */
+ IN OUT gctUINT width;
+
+ /* Height of rectangle to allocate. */
+ IN OUT gctUINT height;
+
+ /* Depth of rectangle to allocate. */
+ IN gctUINT depth;
+
+ /* Format rectangle to allocate in gceSURF_FORMAT. */
+ IN gceSURF_FORMAT format;
+
+ /* Type of allocation. */
+ IN gceSURF_TYPE type;
+
+ /* Memory pool to allocate from. */
+ IN OUT gcePOOL pool;
+
+ /* Allocated video memory. */
+ OUT gcuVIDMEM_NODE_PTR node;
+ }
+ AllocateVideoMemory;
+
+ /* gcvHAL_FREE_VIDEO_MEMORY */
+ struct _gcsHAL_FREE_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gcuVIDMEM_NODE_PTR node;
+
+#ifdef __QNXNTO__
+/* TODO: This is part of the unlock - why is it here? */
+ /* Mapped logical address to unmap in user space. */
+ OUT gctPOINTER memory;
+
+ /* Number of bytes to allocated. */
+ OUT gctSIZE_T bytes;
+#endif
+ }
+ FreeVideoMemory;
+
+ /* gcvHAL_LOCK_VIDEO_MEMORY */
+ struct _gcsHAL_LOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gcuVIDMEM_NODE_PTR node;
+
+ /* Hardware specific address. */
+ OUT gctUINT32 address;
+
+ /* Mapped logical address. */
+ OUT gctPOINTER memory;
+ }
+ LockVideoMemory;
+
+ /* gcvHAL_UNLOCK_VIDEO_MEMORY */
+ struct _gcsHAL_UNLOCK_VIDEO_MEMORY
+ {
+ /* Allocated video memory. */
+ IN gcuVIDMEM_NODE_PTR node;
+
+ /* Type of surface. */
+ IN gceSURF_TYPE type;
+
+ /* Flag to unlock surface asynchroneously. */
+ IN OUT gctBOOL asynchroneous;
+ }
+ UnlockVideoMemory;
+
+ /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
+ struct _gcsHAL_ALLOCATE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ OUT gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ OUT gctPOINTER logical;
+ }
+ AllocateNonPagedMemory;
+
+ /* gcvHAL_FREE_NON_PAGED_MEMORY */
+ struct _gcsHAL_FREE_NON_PAGED_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ IN gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ IN gctPOINTER logical;
+ }
+ FreeNonPagedMemory;
+
+ /* gcvHAL_EVENT_COMMIT. */
+ struct _gcsHAL_EVENT_COMMIT
+ {
+ /* Event queue. */
+ IN struct _gcsQUEUE * queue;
+ }
+ Event;
+
+ /* gcvHAL_COMMIT */
+ struct _gcsHAL_COMMIT
+ {
+ /* Command buffer. */
+ IN gcoCMDBUF commandBuffer;
+
+ /* Context buffer. */
+ IN gcoCONTEXT contextBuffer;
+
+ /* Process handle. */
+ IN gctHANDLE process;
+ }
+ Commit;
+
+ /* gcvHAL_MAP_USER_MEMORY */
+ struct _gcsHAL_MAP_USER_MEMORY
+ {
+ /* Base address of user memory to map. */
+ IN gctPOINTER memory;
+
+ /* Size of user memory in bytes to map. */
+ IN gctSIZE_T size;
+
+ /* Info record required by gcvHAL_UNMAP_USER_MEMORY. */
+ OUT gctPOINTER info;
+
+ /* Physical address of mapped memory. */
+ OUT gctUINT32 address;
+ }
+ MapUserMemory;
+
+ /* gcvHAL_UNMAP_USER_MEMORY */
+ struct _gcsHAL_UNMAP_USER_MEMORY
+ {
+ /* Base address of user memory to unmap. */
+ IN gctPOINTER memory;
+
+ /* Size of user memory in bytes to unmap. */
+ IN gctSIZE_T size;
+
+ /* Info record returned by gcvHAL_MAP_USER_MEMORY. */
+ IN gctPOINTER info;
+
+ /* Physical address of mapped memory as returned by
+ gcvHAL_MAP_USER_MEMORY. */
+ IN gctUINT32 address;
+ }
+ UnmapUserMemory;
+
+#if !USE_NEW_LINUX_SIGNAL
+ /* gcsHAL_USER_SIGNAL */
+ struct _gcsHAL_USER_SIGNAL
+ {
+ /* Command. */
+ gceUSER_SIGNAL_COMMAND_CODES command;
+
+ /* Signal ID. */
+ IN OUT gctINT id;
+
+ /* Reset mode. */
+ IN gctBOOL manualReset;
+
+ /* Wait timedout. */
+ IN gctUINT32 wait;
+
+ /* State. */
+ IN gctBOOL state;
+ }
+ UserSignal;
+#endif
+
+ /* gcvHAL_SIGNAL. */
+ struct _gcsHAL_SIGNAL
+ {
+ /* Signal handle to signal. */
+ IN gctSIGNAL signal;
+
+ /* Reserved. */
+ IN gctSIGNAL auxSignal;
+
+ /* Process owning the signal. */
+ IN gctHANDLE process;
+
+#if defined(__QNXNTO__)
+ /* Client pulse side-channel connection ID. Set by client in gcoOS_CreateSignal. */
+ IN gctINT32 coid;
+
+ /* Set by server. */
+ IN gctINT32 rcvid;
+#endif
+ /* Event generated from where of pipeline */
+ IN gceKERNEL_WHERE fromWhere;
+ }
+ Signal;
+
+ /* gcvHAL_WRITE_DATA. */
+ struct _gcsHAL_WRITE_DATA
+ {
+ /* Address to write data to. */
+ IN gctUINT32 address;
+
+ /* Data to write. */
+ IN gctUINT32 data;
+ }
+ WriteData;
+
+ /* gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_ALLOCATE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes to allocate. */
+ IN OUT gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ OUT gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ OUT gctPOINTER logical;
+
+ }
+ AllocateContiguousMemory;
+
+ /* gcvHAL_FREE_CONTIGUOUS_MEMORY */
+ struct _gcsHAL_FREE_CONTIGUOUS_MEMORY
+ {
+ /* Number of bytes allocated. */
+ IN gctSIZE_T bytes;
+
+ /* Physical address of allocation. */
+ IN gctPHYS_ADDR physical;
+
+ /* Logical address of allocation. */
+ IN gctPOINTER logical;
+ }
+ FreeContiguousMemory;
+
+ /* gcvHAL_READ_REGISTER */
+ struct _gcsHAL_READ_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ OUT gctUINT32 data;
+ }
+ ReadRegisterData;
+
+ /* gcvHAL_WRITE_REGISTER */
+ struct _gcsHAL_WRITE_REGISTER
+ {
+ /* Logical address of memory to write data to. */
+ IN gctUINT32 address;
+
+ /* Data read. */
+ IN gctUINT32 data;
+ }
+ WriteRegisterData;
+
+ /* gcvHAL_GET_PROFILE_SETTING */
+ struct _gcsHAL_GET_PROFILE_SETTING
+ {
+ /* Enable profiling */
+ OUT gctBOOL enable;
+
+ /* The profile file name */
+ OUT gctCHAR fileName[gcdMAX_PROFILE_FILE_NAME];
+ }
+ GetProfileSetting;
+
+ /* gcvHAL_SET_PROFILE_SETTING */
+ struct _gcsHAL_SET_PROFILE_SETTING
+ {
+ /* Enable profiling */
+ IN gctBOOL enable;
+
+ /* The profile file name */
+ IN gctCHAR fileName[gcdMAX_PROFILE_FILE_NAME];
+ }
+ SetProfileSetting;
+
+ /* gcvHAL_READ_ALL_PROFILE_REGISTERS */
+ struct _gcsHAL_READ_ALL_PROFILE_REGISTERS
+ {
+ /* Data read. */
+ OUT gcsPROFILER_COUNTERS counters;
+ }
+ RegisterProfileData;
+
+ /* gcvHAL_PROFILE_REGISTERS_2D */
+ struct _gcsHAL_PROFILE_REGISTERS_2D
+ {
+ /* Data read. */
+ OUT gcs2D_PROFILE_PTR hwProfile2D;
+ }
+ RegisterProfileData2D;
+
+ /* Power management. */
+ /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_SET_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ IN gceCHIPPOWERSTATE state;
+ }
+ SetPowerManagement;
+
+ /* gcvHAL_QUERY_POWER_MANAGEMENT_STATE */
+ struct _gcsHAL_QUERY_POWER_MANAGEMENT
+ {
+ /* Data read. */
+ OUT gceCHIPPOWERSTATE state;
+
+ /* Idle query. */
+ OUT gctBOOL isIdle;
+ }
+ QueryPowerManagement;
+
+ /* gcvHAL_QUERY_KERNEL_SETTINGS */
+ struct _gcsHAL_QUERY_KERNEL_SETTINGS
+ {
+ /* Settings.*/
+ OUT gcsKERNEL_SETTINGS settings;
+ }
+ QueryKernelSettings;
+
+ /* gcvHAL_MAP_PHYSICAL */
+ struct _gcsHAL_MAP_PHYSICAL
+ {
+ /* gcvTRUE to map, gcvFALSE to unmap. */
+ IN gctBOOL map;
+
+ /* Physical address. */
+ IN OUT gctPHYS_ADDR physical;
+ }
+ MapPhysical;
+
+ /* gcvHAL_DEBUG */
+ struct _gcsHAL_DEBUG
+ {
+ /* If gcvTRUE, set the debug information. */
+ IN gctBOOL set;
+ IN gctUINT32 level;
+ IN gctUINT32 zones;
+ IN gctBOOL enable;
+
+ /* Message to print if not empty. */
+ IN gctCHAR message[80];
+ }
+ Debug;
+
+ struct _gcsHAL_CACHE
+ {
+ IN gctBOOL invalidate;
+ IN gctHANDLE process;
+ IN gctPOINTER logical;
+ IN gctSIZE_T bytes;
+ }
+ Cache;
+ }
+ u;
+}
+gcsHAL_INTERFACE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_driver_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* 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_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_engine_h_
+#define __gc_hal_engine_h_
+
+#include "gc_hal_types.h"
+#include "gc_hal_enum.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoSTREAM * gcoSTREAM;
+typedef struct _gcoVERTEX * gcoVERTEX;
+typedef struct _gcoTEXTURE * gcoTEXTURE;
+typedef struct _gcoINDEX * gcoINDEX;
+typedef struct _gcsVERTEX_ATTRIBUTES * gcsVERTEX_ATTRIBUTES_PTR;
+
+/******************************************************************************\
+********************************* Enumerations *********************************
+\******************************************************************************/
+
+/* Shading format. */
+typedef enum _gceSHADING
+{
+ gcvSHADING_SMOOTH,
+ gcvSHADING_FLAT_D3D,
+ gcvSHADING_FLAT_OPENGL,
+}
+gceSHADING;
+
+/* Culling modes. */
+typedef enum _gceCULL
+{
+ gcvCULL_NONE,
+ gcvCULL_CCW,
+ gcvCULL_CW,
+}
+gceCULL;
+
+/* Fill modes. */
+typedef enum _gceFILL
+{
+ gcvFILL_POINT,
+ gcvFILL_WIRE_FRAME,
+ gcvFILL_SOLID,
+}
+gceFILL;
+
+/* Compare modes. */
+typedef enum _gceCOMPARE
+{
+ gcvCOMPARE_NEVER,
+ gcvCOMPARE_NOT_EQUAL,
+ gcvCOMPARE_LESS,
+ gcvCOMPARE_LESS_OR_EQUAL,
+ gcvCOMPARE_EQUAL,
+ gcvCOMPARE_GREATER,
+ gcvCOMPARE_GREATER_OR_EQUAL,
+ gcvCOMPARE_ALWAYS,
+}
+gceCOMPARE;
+
+/* Stencil modes. */
+typedef enum _gceSTENCIL_MODE
+{
+ gcvSTENCIL_NONE,
+ gcvSTENCIL_SINGLE_SIDED,
+ gcvSTENCIL_DOUBLE_SIDED,
+}
+gceSTENCIL_MODE;
+
+/* Stencil operations. */
+typedef enum _gceSTENCIL_OPERATION
+{
+ gcvSTENCIL_KEEP,
+ gcvSTENCIL_REPLACE,
+ gcvSTENCIL_ZERO,
+ gcvSTENCIL_INVERT,
+ gcvSTENCIL_INCREMENT,
+ gcvSTENCIL_DECREMENT,
+ gcvSTENCIL_INCREMENT_SATURATE,
+ gcvSTENCIL_DECREMENT_SATURATE,
+}
+gceSTENCIL_OPERATION;
+
+/* Stencil selection. */
+typedef enum _gceSTENCIL_WHERE
+{
+ gcvSTENCIL_FRONT,
+ gcvSTENCIL_BACK,
+}
+gceSTENCIL_WHERE;
+
+/* Texture addressing selection. */
+typedef enum _gceTEXTURE_WHICH
+{
+ gcvTEXTURE_S,
+ gcvTEXTURE_T,
+ gcvTEXTURE_R,
+}
+gceTEXTURE_WHICH;
+
+/* Texture addressing modes. */
+typedef enum _gceTEXTURE_ADDRESSING
+{
+ gcvTEXTURE_WRAP,
+ gcvTEXTURE_CLAMP,
+ gcvTEXTURE_BORDER,
+ gcvTEXTURE_MIRROR,
+ gcvTEXTURE_MIRROR_ONCE,
+}
+gceTEXTURE_ADDRESSING;
+
+/* Texture filters. */
+typedef enum _gceTEXTURE_FILTER
+{
+ gcvTEXTURE_NONE,
+ gcvTEXTURE_POINT,
+ gcvTEXTURE_LINEAR,
+ gcvTEXTURE_ANISOTROPIC,
+}
+gceTEXTURE_FILTER;
+
+/* Primitive types. */
+typedef enum _gcePRIMITIVE
+{
+ gcvPRIMITIVE_POINT_LIST,
+ gcvPRIMITIVE_LINE_LIST,
+ gcvPRIMITIVE_LINE_STRIP,
+ gcvPRIMITIVE_LINE_LOOP,
+ gcvPRIMITIVE_TRIANGLE_LIST,
+ gcvPRIMITIVE_TRIANGLE_STRIP,
+ gcvPRIMITIVE_TRIANGLE_FAN,
+}
+gcePRIMITIVE;
+
+/* Index types. */
+typedef enum _gceINDEX_TYPE
+{
+ gcvINDEX_8,
+ gcvINDEX_16,
+ gcvINDEX_32,
+}
+gceINDEX_TYPE;
+
+/******************************************************************************\
+********************************* gcoHAL Object *********************************
+\******************************************************************************/
+
+/* Query the target capabilities. */
+gceSTATUS
+gcoHAL_QueryTargetCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MultiTargetCount,
+ OUT gctUINT * MaxSamples
+ );
+
+gceSTATUS
+gcoHAL_SetDepthOnly(
+ IN gcoHAL Hal,
+ IN gctBOOL Enable
+ );
+
+gceSTATUS
+gcoHAL_QueryShaderCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * VertexUniforms,
+ OUT gctUINT * FragmentUniforms,
+ OUT gctUINT * Varyings
+ );
+
+gceSTATUS
+gcoHAL_QueryTextureCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoHAL_QueryStreamCaps(
+ IN gcoHAL Hal,
+ OUT gctUINT32 * MaxAttributes,
+ OUT gctUINT32 * MaxStreamSize,
+ OUT gctUINT32 * NumberOfStreams,
+ OUT gctUINT32 * Alignment
+ );
+
+/******************************************************************************\
+********************************* gcoSURF Object ********************************
+\******************************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/*--------------------------------- gcoSURF 3D --------------------------------*/
+
+/* Copy surface. */
+gceSTATUS
+gcoSURF_Copy(
+ IN gcoSURF Surface,
+ IN gcoSURF Source
+ );
+
+/* Clear surface. */
+gceSTATUS
+gcoSURF_Clear(
+ IN gcoSURF Surface,
+ IN gctUINT Flags
+ );
+
+/* Set number of samples for a gcoSURF object. */
+gceSTATUS
+gcoSURF_SetSamples(
+ IN gcoSURF Surface,
+ IN gctUINT Samples
+ );
+
+/* Get the number of samples per pixel. */
+gceSTATUS
+gcoSURF_GetSamples(
+ IN gcoSURF Surface,
+ OUT gctUINT_PTR Samples
+ );
+
+/* Clear rectangular surface. */
+gceSTATUS
+gcoSURF_ClearRect(
+ IN gcoSURF Surface,
+ IN gctINT Left,
+ IN gctINT Top,
+ IN gctINT Right,
+ IN gctINT Bottom,
+ IN gctUINT Flags
+ );
+
+/* TO BE REMOVED */
+#if 1
+ gceSTATUS
+ depr_gcoSURF_Resolve(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 DestAddress,
+ IN gctPOINTER DestBits,
+ IN gctINT DestStride,
+ IN gceSURF_TYPE DestType,
+ IN gceSURF_FORMAT DestFormat,
+ IN gctUINT DestWidth,
+ IN gctUINT DestHeight
+ );
+
+ gceSTATUS
+ depr_gcoSURF_ResolveRect(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 DestAddress,
+ IN gctPOINTER DestBits,
+ IN gctINT DestStride,
+ IN gceSURF_TYPE DestType,
+ IN gceSURF_FORMAT DestFormat,
+ IN gctUINT DestWidth,
+ IN gctUINT DestHeight,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+#endif
+
+/* Resample surface. */
+gceSTATUS
+gcoSURF_Resample(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface
+ );
+
+/* Resolve surface. */
+gceSTATUS
+gcoSURF_Resolve(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface
+ );
+
+/* Resolve rectangular area of a surface. */
+gceSTATUS
+gcoSURF_ResolveRect(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsPOINT_PTR SrcOrigin,
+ IN gcsPOINT_PTR DestOrigin,
+ IN gcsPOINT_PTR RectSize
+ );
+
+/* Set surface resolvability. */
+gceSTATUS
+gcoSURF_SetResolvability(
+ IN gcoSURF Surface,
+ IN gctBOOL Resolvable
+ );
+
+/******************************************************************************\
+******************************** gcoINDEX Object *******************************
+\******************************************************************************/
+
+/* Construct a new gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoINDEX * Index
+ );
+
+/* Destroy a gcoINDEX object. */
+gceSTATUS
+gcoINDEX_Destroy(
+ IN gcoINDEX Index
+ );
+
+/* Lock index in memory. */
+gceSTATUS
+gcoINDEX_Lock(
+ IN gcoINDEX Index,
+ OUT gctUINT32 * Address,
+ OUT gctPOINTER * Memory
+ );
+
+/* Unlock index that was previously locked with gcoINDEX_Lock. */
+gceSTATUS
+gcoINDEX_Unlock(
+ IN gcoINDEX Index
+ );
+
+/* Upload index data into the memory. */
+gceSTATUS
+gcoINDEX_Load(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE IndexType,
+ IN gctUINT32 IndexCount,
+ IN gctPOINTER IndexBuffer
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_Bind(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type
+ );
+
+/* Bind an index object to the hardware. */
+gceSTATUS
+gcoINDEX_BindOffset(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset
+ );
+
+/* Free existing index buffer. */
+gceSTATUS
+gcoINDEX_Free(
+ IN gcoINDEX Index
+ );
+
+/* Upload data into an index buffer. */
+gceSTATUS
+gcoINDEX_Upload(
+ IN gcoINDEX Index,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/* Upload data into an index buffer starting at an offset. */
+gceSTATUS
+gcoINDEX_UploadOffset(
+ IN gcoINDEX Index,
+ IN gctUINT32 Offset,
+ IN gctCONST_POINTER Buffer,
+ IN gctSIZE_T Bytes
+ );
+
+/* Query the index capabilities. */
+gceSTATUS
+gcoINDEX_QueryCaps(
+ OUT gctBOOL * Index8,
+ OUT gctBOOL * Index16,
+ OUT gctBOOL * Index32,
+ OUT gctUINT * MaxIndex
+ );
+
+/* Determine the index range in the current index buffer. */
+gceSTATUS
+gcoINDEX_GetIndexRange(
+ IN gcoINDEX Index,
+ IN gceINDEX_TYPE Type,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Count,
+ OUT gctUINT32 * MinimumIndex,
+ OUT gctUINT32 * MaximumIndex
+ );
+
+/* Dynamic buffer management. */
+gceSTATUS
+gcoINDEX_SetDynamic(
+ IN gcoINDEX Index,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Buffers
+ );
+
+gceSTATUS
+gcoINDEX_UploadDynamic(
+ IN gcoINDEX Index,
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Bytes
+ );
+
+/******************************************************************************\
+********************************** gco3D Object *********************************
+\******************************************************************************/
+
+/* Clear flags. */
+typedef enum _gceCLEAR
+{
+ gcvCLEAR_COLOR = 0x1,
+ gcvCLEAR_DEPTH = 0x2,
+ gcvCLEAR_STENCIL = 0x4,
+ gcvCLEAR_HZ = 0x8,
+ gcvCLEAR_HAS_VAA = 0x10,
+}
+gceCLEAR;
+
+/* Blending targets. */
+typedef enum _gceBLEND_UNIT
+{
+ gcvBLEND_SOURCE,
+ gcvBLEND_TARGET,
+}
+gceBLEND_UNIT;
+
+/* Construct a new gco3D object. */
+gceSTATUS
+gco3D_Construct(
+ IN gcoHAL Hal,
+ OUT gco3D * Engine
+ );
+
+/* Destroy an gco3D object. */
+gceSTATUS
+gco3D_Destroy(
+ IN gco3D Engine
+ );
+
+/* Set 3D API type. */
+gceSTATUS
+gco3D_SetAPI(
+ IN gco3D Engine,
+ IN gceAPI ApiType
+ );
+
+/* Set render target. */
+gceSTATUS
+gco3D_SetTarget(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Unset render target. */
+gceSTATUS
+gco3D_UnsetTarget(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Set depth buffer. */
+gceSTATUS
+gco3D_SetDepth(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Unset depth buffer. */
+gceSTATUS
+gco3D_UnsetDepth(
+ IN gco3D Engine,
+ IN gcoSURF Surface
+ );
+
+/* Set viewport. */
+gceSTATUS
+gco3D_SetViewport(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set scissors. */
+gceSTATUS
+gco3D_SetScissors(
+ IN gco3D Engine,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom
+ );
+
+/* Set clear color. */
+gceSTATUS
+gco3D_SetClearColor(
+ IN gco3D Engine,
+ IN gctUINT8 Red,
+ IN gctUINT8 Green,
+ IN gctUINT8 Blue,
+ IN gctUINT8 Alpha
+ );
+
+/* Set fixed point clear color. */
+gceSTATUS
+gco3D_SetClearColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point clear color. */
+gceSTATUS
+gco3D_SetClearColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set fixed point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Depth
+ );
+
+/* Set floating point clear depth. */
+gceSTATUS
+gco3D_SetClearDepthF(
+ IN gco3D Engine,
+ IN gctFLOAT Depth
+ );
+
+/* Set clear stencil. */
+gceSTATUS
+gco3D_SetClearStencil(
+ IN gco3D Engine,
+ IN gctUINT32 Stencil
+ );
+
+/* Clear a Rect sub-surface. */
+gceSTATUS
+gco3D_ClearRect(
+ IN gco3D Engine,
+ IN gctUINT32 Address,
+ IN gctPOINTER Memory,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctINT32 Left,
+ IN gctINT32 Top,
+ IN gctINT32 Right,
+ IN gctINT32 Bottom,
+ IN gctUINT32 Width,
+ IN gctUINT32 Height,
+ IN gctUINT32 Flags
+ );
+
+/* Clear surface. */
+gceSTATUS
+gco3D_Clear(
+ IN gco3D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 Width,
+ IN gctUINT32 Height,
+ IN gctUINT32 Flags
+ );
+
+
+/* Clear tile status. */
+gceSTATUS
+gco3D_ClearTileStatus(
+ IN gco3D Engine,
+ IN gcsSURF_INFO_PTR Surface,
+ IN gctUINT32 TileStatusAddress,
+ IN gctUINT32 Flags
+ );
+
+/* Set shading mode. */
+gceSTATUS
+gco3D_SetShading(
+ IN gco3D Engine,
+ IN gceSHADING Shading
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_EnableBlending(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set blending function. */
+gceSTATUS
+gco3D_SetBlendFunction(
+ IN gco3D Engine,
+ IN gceBLEND_UNIT Unit,
+ IN gceBLEND_FUNCTION FunctionRGB,
+ IN gceBLEND_FUNCTION FunctionAlpha
+ );
+
+/* Set blending mode. */
+gceSTATUS
+gco3D_SetBlendMode(
+ IN gco3D Engine,
+ IN gceBLEND_MODE ModeRGB,
+ IN gceBLEND_MODE ModeAlpha
+ );
+
+/* Set blending color. */
+gceSTATUS
+gco3D_SetBlendColor(
+ IN gco3D Engine,
+ IN gctUINT Red,
+ IN gctUINT Green,
+ IN gctUINT Blue,
+ IN gctUINT Alpha
+ );
+
+/* Set fixed point blending color. */
+gceSTATUS
+gco3D_SetBlendColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+/* Set floating point blending color. */
+gceSTATUS
+gco3D_SetBlendColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Set culling mode. */
+gceSTATUS
+gco3D_SetCulling(
+ IN gco3D Engine,
+ IN gceCULL Mode
+ );
+
+/* Enable point size */
+gceSTATUS
+gco3D_SetPointSizeEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set point sprite */
+gceSTATUS
+gco3D_SetPointSprite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set fill mode. */
+gceSTATUS
+gco3D_SetFill(
+ IN gco3D Engine,
+ IN gceFILL Mode
+ );
+
+/* Set depth compare mode. */
+gceSTATUS
+gco3D_SetDepthCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Enable depth writing. */
+gceSTATUS
+gco3D_EnableDepthWrite(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth mode. */
+gceSTATUS
+gco3D_SetDepthMode(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeX(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFIXED_POINT Near,
+ IN gctFIXED_POINT Far
+ );
+
+/* Set depth range. */
+gceSTATUS
+gco3D_SetDepthRangeF(
+ IN gco3D Engine,
+ IN gceDEPTH_MODE Mode,
+ IN gctFLOAT Near,
+ IN gctFLOAT Far
+ );
+
+/* Set last pixel enable */
+gceSTATUS
+gco3D_SetLastPixelEnable(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set depth Bias and Scale */
+gceSTATUS
+gco3D_SetDepthScaleBiasX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT DepthScale,
+ IN gctFIXED_POINT DepthBias
+ );
+
+gceSTATUS
+gco3D_SetDepthScaleBiasF(
+ IN gco3D Engine,
+ IN gctFLOAT DepthScale,
+ IN gctFLOAT DepthBias
+ );
+
+/* Enable or disable dithering. */
+gceSTATUS
+gco3D_EnableDither(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set color write enable bits. */
+gceSTATUS
+gco3D_SetColorWrite(
+ IN gco3D Engine,
+ IN gctUINT8 Enable
+ );
+
+/* Enable or disable early depth. */
+gceSTATUS
+gco3D_SetEarlyDepth(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Enable or disable depth-only mode. */
+gceSTATUS
+gco3D_SetDepthOnly(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set stencil mode. */
+gceSTATUS
+gco3D_SetStencilMode(
+ IN gco3D Engine,
+ IN gceSTENCIL_MODE Mode
+ );
+
+/* Set stencil mask. */
+gceSTATUS
+gco3D_SetStencilMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil write mask. */
+gceSTATUS
+gco3D_SetStencilWriteMask(
+ IN gco3D Engine,
+ IN gctUINT8 Mask
+ );
+
+/* Set stencil reference. */
+gceSTATUS
+gco3D_SetStencilReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference
+ );
+
+/* Set stencil compare. */
+gceSTATUS
+gco3D_SetStencilCompare(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceCOMPARE Compare
+ );
+
+/* Set stencil operation on pass. */
+gceSTATUS
+gco3D_SetStencilPass(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on fail. */
+gceSTATUS
+gco3D_SetStencilFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Set stencil operation on depth fail. */
+gceSTATUS
+gco3D_SetStencilDepthFail(
+ IN gco3D Engine,
+ IN gceSTENCIL_WHERE Where,
+ IN gceSTENCIL_OPERATION Operation
+ );
+
+/* Enable or disable alpha test. */
+gceSTATUS
+gco3D_SetAlphaTest(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set alpha test compare. */
+gceSTATUS
+gco3D_SetAlphaCompare(
+ IN gco3D Engine,
+ IN gceCOMPARE Compare
+ );
+
+/* Set alpha test reference in unsigned integer. */
+gceSTATUS
+gco3D_SetAlphaReference(
+ IN gco3D Engine,
+ IN gctUINT8 Reference
+ );
+
+/* Set alpha test reference in fixed point. */
+gceSTATUS
+gco3D_SetAlphaReferenceX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Reference
+ );
+
+/* Set alpha test reference in floating point. */
+gceSTATUS
+gco3D_SetAlphaReferenceF(
+ IN gco3D Engine,
+ IN gctFLOAT Reference
+ );
+
+/* Enable/Disable anti-alias line. */
+gceSTATUS
+gco3D_SetAntiAliasLine(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Set texture slot for anti-alias line. */
+gceSTATUS
+gco3D_SetAALineTexSlot(
+ IN gco3D Engine,
+ IN gctUINT TexSlot
+ );
+
+/* Set anti-alias line width scale. */
+gceSTATUS
+gco3D_SetAALineWidth(
+ IN gco3D Engine,
+ IN gctFLOAT Width
+ );
+
+/* Draw a number of primitives. */
+gceSTATUS
+gco3D_DrawPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT StartVertex,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of primitives using offsets. */
+gceSTATUS
+gco3D_DrawPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of indexed primitives. */
+gceSTATUS
+gco3D_DrawIndexedPrimitives(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT BaseVertex,
+ IN gctINT StartIndex,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Draw a number of indexed primitives using offsets. */
+gceSTATUS
+gco3D_DrawIndexedPrimitivesOffset(
+ IN gco3D Engine,
+ IN gcePRIMITIVE Type,
+ IN gctINT32 BaseOffset,
+ IN gctINT32 StartOffset,
+ IN gctSIZE_T PrimitiveCount
+ );
+
+/* Enable or disable anti-aliasing. */
+gceSTATUS
+gco3D_SetAntiAlias(
+ IN gco3D Engine,
+ IN gctBOOL Enable
+ );
+
+/* Write data into the command buffer. */
+gceSTATUS
+gco3D_WriteBuffer(
+ IN gco3D Engine,
+ IN gctCONST_POINTER Data,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Aligned
+ );
+
+/*Send sempahore and stall until sempahore is signalled.*/
+gceSTATUS
+gco3D_Semaphore(
+ IN gco3D Engine,
+ IN gceWHERE From,
+ IN gceWHERE To,
+ IN gceHOW How);
+
+/*Set the subpixels center .*/
+gceSTATUS
+gco3D_SetCentroids(
+ IN gco3D Engine,
+ IN gctUINT32 Index,
+ IN gctPOINTER Centroids
+ );
+/*----------------------------------------------------------------------------*/
+/*-------------------------- gco3D Fragment Processor ------------------------*/
+
+/* Set the fragment processor configuration. */
+gceSTATUS
+gco3D_SetFragmentConfiguration(
+ IN gco3D Engine,
+ IN gctBOOL ColorFromStream,
+ IN gctBOOL EnableFog,
+ IN gctBOOL EnableSmoothPoint,
+ IN gctUINT32 ClipPlanes
+ );
+
+/* Enable/disable texture stage operation. */
+gceSTATUS
+gco3D_EnableTextureStage(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL Enable
+ );
+
+/* Program the channel enable masks for the color texture function. */
+gceSTATUS
+gco3D_SetTextureColorMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the channel enable masks for the alpha texture function. */
+gceSTATUS
+gco3D_SetTextureAlphaMask(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctBOOL ColorEnabled,
+ IN gctBOOL AlphaEnabled
+ );
+
+/* Program the constant fragment color. */
+gceSTATUS
+gco3D_SetFragmentColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFragmentColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant fog color. */
+gceSTATUS
+gco3D_SetFogColorX(
+ IN gco3D Engine,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetFogColorF(
+ IN gco3D Engine,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Program the constant texture color. */
+gceSTATUS
+gco3D_SetTetxureColorX(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gco3D_SetTetxureColorF(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+/* Configure color texture function. */
+gceSTATUS
+gco3D_SetColorTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+/* Configure alpha texture function. */
+gceSTATUS
+gco3D_SetAlphaTextureFunction(
+ IN gco3D Engine,
+ IN gctINT Stage,
+ IN gceTEXTURE_FUNCTION Function,
+ IN gceTEXTURE_SOURCE Source0,
+ IN gceTEXTURE_CHANNEL Channel0,
+ IN gceTEXTURE_SOURCE Source1,
+ IN gceTEXTURE_CHANNEL Channel1,
+ IN gceTEXTURE_SOURCE Source2,
+ IN gceTEXTURE_CHANNEL Channel2,
+ IN gctINT Scale
+ );
+
+
+/******************************************************************************\
+******************************* gcoTEXTURE Object *******************************
+\******************************************************************************/
+
+/* Cube faces. */
+typedef enum _gceTEXTURE_FACE
+{
+ gcvFACE_NONE,
+ gcvFACE_POSITIVE_X,
+ gcvFACE_NEGATIVE_X,
+ gcvFACE_POSITIVE_Y,
+ gcvFACE_NEGATIVE_Y,
+ gcvFACE_POSITIVE_Z,
+ gcvFACE_NEGATIVE_Z,
+}
+gceTEXTURE_FACE;
+
+/* Construct a new gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Construct(
+ IN gcoHAL Hal,
+ OUT gcoTEXTURE * Texture
+ );
+
+/* Construct a new sized gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_ConstructSized(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT Faces,
+ IN gctUINT MipMapCount,
+ IN gcePOOL Pool,
+ OUT gcoTEXTURE * Texture
+ );
+
+/* Destroy an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Destroy(
+ IN gcoTEXTURE Texture
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_Upload(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctINT Stride,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Upload data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadSub(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT X,
+ IN gctUINT Y,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctINT Stride,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Upload compressed data to an gcoTEXTURE object. */
+gceSTATUS
+gcoTEXTURE_UploadCompressed(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FACE Face,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Slice,
+ IN gctCONST_POINTER Memory,
+ IN gctSIZE_T Bytes
+ );
+
+/* Get gcoSURF object for a mipmap level. */
+gceSTATUS
+gcoTEXTURE_GetMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ OUT gcoSURF * Surface
+ );
+
+/* Get gcoSURF object for a mipmap level and face offset. */
+gceSTATUS
+gcoTEXTURE_GetMipMapFace(
+ IN gcoTEXTURE Texture,
+ IN gctUINT MipMap,
+ IN gceTEXTURE_FACE Face,
+ OUT gcoSURF * Surface,
+ OUT gctUINT32_PTR Offset
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT Faces,
+ IN gcePOOL Pool,
+ OUT gcoSURF * Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromClient(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_AddMipMapFromSurface(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level,
+ IN gcoSURF Surface
+ );
+
+gceSTATUS
+gcoTEXTURE_SetEndianHint(
+ IN gcoTEXTURE Texture,
+ IN gceENDIAN_HINT EndianHint
+ );
+
+gceSTATUS
+gcoTEXTURE_SetAddressingMode(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_WHICH Which,
+ IN gceTEXTURE_ADDRESSING Mode
+ );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColor(
+ IN gcoTEXTURE Texture,
+ IN gctUINT Red,
+ IN gctUINT Green,
+ IN gctUINT Blue,
+ IN gctUINT Alpha
+ );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColorX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT Red,
+ IN gctFIXED_POINT Green,
+ IN gctFIXED_POINT Blue,
+ IN gctFIXED_POINT Alpha
+ );
+
+gceSTATUS
+gcoTEXTURE_SetBorderColorF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT Red,
+ IN gctFLOAT Green,
+ IN gctFLOAT Blue,
+ IN gctFLOAT Alpha
+ );
+
+gceSTATUS
+gcoTEXTURE_SetMinFilter(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FILTER Filter
+ );
+
+gceSTATUS
+gcoTEXTURE_SetMagFilter(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FILTER Filter
+ );
+
+gceSTATUS
+gcoTEXTURE_SetMipFilter(
+ IN gcoTEXTURE Texture,
+ IN gceTEXTURE_FILTER Filter
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODBiasX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT Bias
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODBiasF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT Bias
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMinX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMinF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMaxX(
+ IN gcoTEXTURE Texture,
+ IN gctFIXED_POINT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_SetLODMaxF(
+ IN gcoTEXTURE Texture,
+ IN gctFLOAT LevelOfDetail
+ );
+
+gceSTATUS
+gcoTEXTURE_Bind(
+ IN gcoTEXTURE Texture,
+ IN gctINT Sampler
+ );
+
+gceSTATUS
+gcoTEXTURE_Disable(
+ IN gcoHAL Hal,
+ IN gctINT Sampler
+ );
+
+gceSTATUS
+gcoTEXTURE_Flush(
+ IN gcoTEXTURE Texture
+ );
+
+gceSTATUS
+gcoTEXTURE_QueryCaps(
+ OUT gctUINT * MaxWidth,
+ OUT gctUINT * MaxHeight,
+ OUT gctUINT * MaxDepth,
+ OUT gctBOOL * Cubic,
+ OUT gctBOOL * NonPowerOfTwo,
+ OUT gctUINT * VertexSamplers,
+ OUT gctUINT * PixelSamplers
+ );
+
+gceSTATUS
+gcoTEXTURE_GetClosestFormat(
+ IN gcoHAL Hal,
+ IN gceSURF_FORMAT InFormat,
+ OUT gceSURF_FORMAT* OutFormat
+ );
+
+gceSTATUS
+gcoTEXTURE_RenderIntoMipMap(
+ IN gcoTEXTURE Texture,
+ IN gctINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_IsRenderable(
+ IN gcoTEXTURE Texture,
+ IN gctUINT Level
+ );
+
+gceSTATUS
+gcoTEXTURE_IsComplete(
+ IN gcoTEXTURE Texture,
+ IN gctINT MaxLevel
+ );
+
+/******************************************************************************\
+******************************* gcoSTREAM Object ******************************
+\******************************************************************************/
+
+typedef enum _gceVERTEX_FORMAT
+{
+ gcvVERTEX_BYTE,
+ gcvVERTEX_UNSIGNED_BYTE,
+ gcvVERTEX_SHORT,
+ gcvVERTEX_UNSIGNED_SHORT,
+ gcvVERTEX_INT,
+ gcvVERTEX_UNSIGNED_INT,
+ gcvVERTEX_FIXED,
+ gcvVERTEX_HALF,
+ gcvVERTEX_FLOAT,
+}
+gceVERTEX_FORMAT;
+
+gceSTATUS
+gcoSTREAM_Construct(
+ IN gcoHAL Hal,
+ OUT gcoSTREAM * Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Destroy(
+ IN gcoSTREAM Stream
+ );
+
+gceSTATUS
+gcoSTREAM_Upload(
+ IN gcoSTREAM Stream,
+ IN gctCONST_POINTER Buffer,
+ IN gctUINT32 Offset,
+ IN gctSIZE_T Bytes,
+ IN gctBOOL Dynamic
+ );
+
+gceSTATUS
+gcoSTREAM_SetStride(
+ IN gcoSTREAM Stream,
+ IN gctUINT32 Stride
+ );
+
+gceSTATUS
+gcoSTREAM_Lock(
+ IN gcoSTREAM Stream,
+ OUT gctPOINTER * Logical,
+ OUT gctUINT32 * Physical
+ );
+
+gceSTATUS
+gcoSTREAM_Unlock(
+ IN gcoSTREAM Stream);
+
+gceSTATUS
+gcoSTREAM_Reserve(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Bytes
+ );
+
+gceSTATUS
+gcoSTREAM_Flush(
+ IN gcoSTREAM Stream
+ );
+
+/* Dynamic buffer API. */
+gceSTATUS
+gcoSTREAM_SetDynamic(
+ IN gcoSTREAM Stream,
+ IN gctSIZE_T Bytes,
+ IN gctUINT Buffers
+ );
+
+typedef struct _gcsSTREAM_INFO
+{
+ gctUINT index;
+ gceVERTEX_FORMAT format;
+ gctBOOL normalized;
+ gctUINT components;
+ gctSIZE_T size;
+ gctCONST_POINTER data;
+ gctUINT stride;
+}
+gcsSTREAM_INFO, * gcsSTREAM_INFO_PTR;
+
+gceSTATUS
+gcoSTREAM_UploadDynamic(
+ IN gcoSTREAM Stream,
+ IN gctUINT VertexCount,
+ IN gctUINT InfoCount,
+ IN gcsSTREAM_INFO_PTR Info,
+ IN gcoVERTEX Vertex
+ );
+
+/******************************************************************************\
+******************************** gcoVERTEX Object ******************************
+\******************************************************************************/
+
+typedef struct _gcsVERTEX_ATTRIBUTES
+{
+ gceVERTEX_FORMAT format;
+ gctBOOL normalized;
+ gctUINT32 components;
+ gctSIZE_T size;
+ gctUINT32 stream;
+ gctUINT32 offset;
+ gctUINT32 stride;
+}
+gcsVERTEX_ATTRIBUTES;
+
+gceSTATUS
+gcoVERTEX_Construct(
+ IN gcoHAL Hal,
+ OUT gcoVERTEX * Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Destroy(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_Reset(
+ IN gcoVERTEX Vertex
+ );
+
+gceSTATUS
+gcoVERTEX_EnableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index,
+ IN gceVERTEX_FORMAT Format,
+ IN gctBOOL Normalized,
+ IN gctUINT32 Components,
+ IN gcoSTREAM Stream,
+ IN gctUINT32 Offset,
+ IN gctUINT32 Stride
+ );
+
+gceSTATUS
+gcoVERTEX_DisableAttribute(
+ IN gcoVERTEX Vertex,
+ IN gctUINT32 Index
+ );
+
+gceSTATUS
+gcoVERTEX_Bind(
+ IN gcoVERTEX Vertex
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_engine_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_enum_h_
+#define __gc_hal_enum_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Chip models. */
+typedef enum _gceCHIPMODEL
+{
+ gcv300 = 0x0300,
+ gcv400 = 0x0400,
+ gcv410 = 0x0410,
+ gcv450 = 0x0450,
+ gcv500 = 0x0500,
+ gcv530 = 0x0530,
+ gcv600 = 0x0600,
+ gcv700 = 0x0700,
+ gcv800 = 0x0800,
+ gcv860 = 0x0860,
+ gcv1000 = 0x1000,
+}
+gceCHIPMODEL;
+
+/* Chip features. */
+typedef enum _gceFEATURE
+{
+ gcvFEATURE_PIPE_2D,
+ gcvFEATURE_PIPE_3D,
+ gcvFEATURE_PIPE_VG,
+ gcvFEATURE_DC,
+ gcvFEATURE_HIGH_DYNAMIC_RANGE,
+ gcvFEATURE_MODULE_CG,
+ gcvFEATURE_MIN_AREA,
+ gcvFEATURE_BUFFER_INTERLEAVING,
+ gcvFEATURE_BYTE_WRITE_2D,
+ gcvFEATURE_ENDIANNESS_CONFIG,
+ gcvFEATURE_DUAL_RETURN_BUS,
+ gcvFEATURE_DEBUG_MODE,
+ gcvFEATURE_YUY2_RENDER_TARGET,
+ gcvFEATURE_FRAGMENT_PROCESSOR,
+ gcvFEATURE_2DPE20,
+ gcvFEATURE_FAST_CLEAR,
+ gcvFEATURE_YUV420_TILER,
+ gcvFEATURE_YUY2_AVERAGING,
+ gcvFEATURE_FLIP_Y,
+ gcvFEATURE_EARLY_Z,
+ gcvFEATURE_Z_COMPRESSION,
+ gcvFEATURE_MSAA,
+ gcvFEATURE_SPECIAL_ANTI_ALIASING,
+ gcvFEATURE_SPECIAL_MSAA_LOD,
+ gcvFEATURE_422_TEXTURE_COMPRESSION,
+ gcvFEATURE_DXT_TEXTURE_COMPRESSION,
+ gcvFEATURE_ETC1_TEXTURE_COMPRESSION,
+ gcvFEATURE_CORRECT_TEXTURE_CONVERTER,
+ gcvFEATURE_TEXTURE_8K,
+ gcvFEATURE_SCALER,
+ gcvFEATURE_YUV420_SCALER,
+ gcvFEATURE_SHADER_HAS_W,
+ gcvFEATURE_SHADER_HAS_SIGN,
+ gcvFEATURE_SHADER_HAS_FLOOR,
+ gcvFEATURE_SHADER_HAS_CEIL,
+ gcvFEATURE_SHADER_HAS_SQRT,
+ gcvFEATURE_SHADER_HAS_TRIG,
+ gcvFEATURE_VAA,
+ gcvFEATURE_HZ,
+ gcvFEATURE_CORRECT_STENCIL,
+ gcvFEATURE_VG20,
+ gcvFEATURE_VG_FILTER,
+ gcvFEATURE_VG21,
+ gcvFEATURE_VG_DOUBLE_BUFFER,
+ gcvFEATURE_MC20,
+ gcvFEATURE_SUPER_TILED,
+}
+gceFEATURE;
+
+/* Chip Power Status. */
+typedef enum _gceCHIPPOWERSTATE
+{
+ gcvPOWER_ON,
+ gcvPOWER_OFF,
+ gcvPOWER_IDLE,
+ gcvPOWER_SUSPEND,
+ gcvPOWER_SUSPEND_ATPOWERON,
+ gcvPOWER_OFF_ATPOWERON,
+ gcvPOWER_IDLE_BROADCAST,
+ gcvPOWER_SUSPEND_BROADCAST,
+ gcvPOWER_OFF_BROADCAST,
+ gcvPOWER_OFF_RECOVERY,
+}
+gceCHIPPOWERSTATE;
+
+/* Surface types. */
+typedef enum _gceSURF_TYPE
+{
+ gcvSURF_TYPE_UNKNOWN,
+ gcvSURF_INDEX,
+ gcvSURF_VERTEX,
+ gcvSURF_TEXTURE,
+ gcvSURF_RENDER_TARGET,
+ gcvSURF_DEPTH,
+ gcvSURF_BITMAP,
+ gcvSURF_TILE_STATUS,
+ gcvSURF_MASK,
+ gcvSURF_SCISSOR,
+ gcvSURF_HIERARCHICAL_DEPTH,
+ gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
+
+ /* Combinations. */
+ gcvSURF_NO_TILE_STATUS = 0x100,
+ gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
+ | gcvSURF_NO_TILE_STATUS,
+ gcvSURF_DEPTH_NO_TILE_STATUS = gcvSURF_DEPTH
+ | gcvSURF_NO_TILE_STATUS,
+}
+gceSURF_TYPE;
+
+typedef enum _gceSURF_COLOR_TYPE
+{
+ gcvSURF_COLOR_UNKNOWN,
+ gcvSURF_COLOR_LINEAR = 0x01,
+ gcvSURF_COLOR_ALPHA_PRE = 0x02,
+}
+gceSURF_COLOR_TYPE;
+
+/* Rotation. */
+typedef enum _gceSURF_ROTATION
+{
+ gcvSURF_0_DEGREE,
+ gcvSURF_90_DEGREE,
+ gcvSURF_180_DEGREE,
+ gcvSURF_270_DEGREE
+}
+gceSURF_ROTATION;
+
+/* Surface formats. */
+typedef enum _gceSURF_FORMAT
+{
+ /* Unknown format. */
+ gcvSURF_UNKNOWN,
+
+ /* Palettized formats. */
+ gcvSURF_INDEX1 = 100,
+ gcvSURF_INDEX4,
+ gcvSURF_INDEX8,
+
+ /* RGB formats. */
+ gcvSURF_A2R2G2B2 = 200,
+ gcvSURF_R3G3B2,
+ gcvSURF_A8R3G3B2,
+ gcvSURF_X4R4G4B4,
+ gcvSURF_A4R4G4B4,
+ gcvSURF_R4G4B4A4,
+ gcvSURF_X1R5G5B5,
+ gcvSURF_A1R5G5B5,
+ gcvSURF_R5G5B5A1,
+ gcvSURF_R5G6B5,
+ gcvSURF_R8G8B8,
+ gcvSURF_X8R8G8B8,
+ gcvSURF_A8R8G8B8,
+ gcvSURF_R8G8B8A8,
+ gcvSURF_G8R8G8B8,
+ gcvSURF_R8G8B8G8,
+ gcvSURF_X2R10G10B10,
+ gcvSURF_A2R10G10B10,
+ gcvSURF_X12R12G12B12,
+ gcvSURF_A12R12G12B12,
+ gcvSURF_X16R16G16B16,
+ gcvSURF_A16R16G16B16,
+ gcvSURF_R8G8B8X8,
+ gcvSURF_R5G5B5X1,
+ gcvSURF_R4G4B4X4,
+
+ /* BGR formats. */
+ gcvSURF_A4B4G4R4 = 300,
+ gcvSURF_A1B5G5R5,
+ gcvSURF_B5G6R5,
+ gcvSURF_B8G8R8,
+ gcvSURF_X8B8G8R8,
+ gcvSURF_A8B8G8R8,
+ gcvSURF_A2B10G10R10,
+ gcvSURF_A16B16G16R16,
+ gcvSURF_G16R16,
+ gcvSURF_B4G4R4A4,
+ gcvSURF_B5G5R5A1,
+ gcvSURF_B8G8R8X8,
+ gcvSURF_B8G8R8A8,
+ gcvSURF_X4B4G4R4,
+ gcvSURF_X1B5G5R5,
+ gcvSURF_B4G4R4X4,
+ gcvSURF_B5G5R5X1,
+
+ /* Compressed formats. */
+ gcvSURF_DXT1 = 400,
+ gcvSURF_DXT2,
+ gcvSURF_DXT3,
+ gcvSURF_DXT4,
+ gcvSURF_DXT5,
+ gcvSURF_CXV8U8,
+ gcvSURF_ETC1,
+
+ /* YUV formats. */
+ gcvSURF_YUY2 = 500,
+ gcvSURF_UYVY,
+ gcvSURF_YV12,
+ gcvSURF_I420,
+ gcvSURF_NV12,
+ gcvSURF_NV21,
+ gcvSURF_NV16,
+ gcvSURF_NV61,
+ gcvSURF_YVYU,
+ gcvSURF_VYUY,
+
+ /* Depth formats. */
+ gcvSURF_D16 = 600,
+ gcvSURF_D24S8,
+ gcvSURF_D32,
+ gcvSURF_D24X8,
+
+ /* Alpha formats. */
+ gcvSURF_A4 = 700,
+ gcvSURF_A8,
+ gcvSURF_A12,
+ gcvSURF_A16,
+ gcvSURF_A32,
+ gcvSURF_A1,
+
+ /* Luminance formats. */
+ gcvSURF_L4 = 800,
+ gcvSURF_L8,
+ gcvSURF_L12,
+ gcvSURF_L16,
+ gcvSURF_L32,
+ gcvSURF_L1,
+
+ /* Alpha/Luminance formats. */
+ gcvSURF_A4L4 = 900,
+ gcvSURF_A2L6,
+ gcvSURF_A8L8,
+ gcvSURF_A4L12,
+ gcvSURF_A12L12,
+ gcvSURF_A16L16,
+
+ /* Bump formats. */
+ gcvSURF_L6V5U5 = 1000,
+ gcvSURF_V8U8,
+ gcvSURF_X8L8V8U8,
+ gcvSURF_Q8W8V8U8,
+ gcvSURF_A2W10V10U10,
+ gcvSURF_V16U16,
+ gcvSURF_Q16W16V16U16,
+
+ /* Floating point formats. */
+ gcvSURF_R16F = 1100,
+ gcvSURF_G16R16F,
+ gcvSURF_A16B16G16R16F,
+ gcvSURF_R32F,
+ gcvSURF_G32R32F,
+ gcvSURF_A32B32G32R32F,
+
+#if 0
+ /* FIXME: remove HDR support for now. */
+ /* HDR formats. */
+ gcvSURF_HDR7E3 = 1200,
+ gcvSURF_HDR6E4,
+ gcvSURF_HDR5E5,
+ gcvSURF_HDR6E5,
+#endif
+}
+gceSURF_FORMAT;
+
+/* Pixel swizzle modes. */
+typedef enum _gceSURF_SWIZZLE
+{
+ gcvSURF_NOSWIZZLE,
+ gcvSURF_ARGB,
+ gcvSURF_ABGR,
+ gcvSURF_RGBA,
+ gcvSURF_BGRA
+}
+gceSURF_SWIZZLE;
+
+/* Transparency modes. */
+typedef enum _gceSURF_TRANSPARENCY
+{
+ /* Valid only for PE 1.0 */
+ gcvSURF_OPAQUE,
+ gcvSURF_SOURCE_MATCH,
+ gcvSURF_SOURCE_MASK,
+ gcvSURF_PATTERN_MASK,
+}
+gceSURF_TRANSPARENCY;
+
+/* Transparency modes. */
+typedef enum _gce2D_TRANSPARENCY
+{
+ /* Valid only for PE 2.0 */
+ gcv2D_OPAQUE,
+ gcv2D_KEYED,
+ gcv2D_MASKED
+}
+gce2D_TRANSPARENCY;
+
+/* Mono packing modes. */
+typedef enum _gceSURF_MONOPACK
+{
+ gcvSURF_PACKED8,
+ gcvSURF_PACKED16,
+ gcvSURF_PACKED32,
+ gcvSURF_UNPACKED,
+}
+gceSURF_MONOPACK;
+
+/* Blending modes. */
+typedef enum _gceSURF_BLEND_MODE
+{
+ /* Porter-Duff blending modes. */
+ /* Fsrc Fdst */
+ gcvBLEND_CLEAR, /* 0 0 */
+ gcvBLEND_SRC, /* 1 0 */
+ gcvBLEND_DST, /* 0 1 */
+ gcvBLEND_SRC_OVER_DST, /* 1 1 - Asrc */
+ gcvBLEND_DST_OVER_SRC, /* 1 - Adst 1 */
+ gcvBLEND_SRC_IN_DST, /* Adst 0 */
+ gcvBLEND_DST_IN_SRC, /* 0 Asrc */
+ gcvBLEND_SRC_OUT_DST, /* 1 - Adst 0 */
+ gcvBLEND_DST_OUT_SRC, /* 0 1 - Asrc */
+ gcvBLEND_SRC_ATOP_DST, /* Adst 1 - Asrc */
+ gcvBLEND_DST_ATOP_SRC, /* 1 - Adst Asrc */
+ gcvBLEND_SRC_XOR_DST, /* 1 - Adst 1 - Asrc */
+
+ /* Special blending modes. */
+ gcvBLEND_SET, /* DST = 1 */
+ gcvBLEND_SUB /* DST = DST * (1 - SRC) */
+}
+gceSURF_BLEND_MODE;
+
+/* Per-pixel alpha modes. */
+typedef enum _gceSURF_PIXEL_ALPHA_MODE
+{
+ gcvSURF_PIXEL_ALPHA_STRAIGHT,
+ gcvSURF_PIXEL_ALPHA_INVERSED
+}
+gceSURF_PIXEL_ALPHA_MODE;
+
+/* Global alpha modes. */
+typedef enum _gceSURF_GLOBAL_ALPHA_MODE
+{
+ gcvSURF_GLOBAL_ALPHA_OFF,
+ gcvSURF_GLOBAL_ALPHA_ON,
+ gcvSURF_GLOBAL_ALPHA_SCALE
+}
+gceSURF_GLOBAL_ALPHA_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gceSURF_PIXEL_COLOR_MODE
+{
+ gcvSURF_COLOR_STRAIGHT,
+ gcvSURF_COLOR_MULTIPLY
+}
+gceSURF_PIXEL_COLOR_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_COLOR_MULTIPLY_DISABLE,
+ gcv2D_COLOR_MULTIPLY_ENABLE
+}
+gce2D_PIXEL_COLOR_MULTIPLY_MODE;
+
+/* Color component modes for alpha blending. */
+typedef enum _gce2D_GLOBAL_COLOR_MULTIPLY_MODE
+{
+ gcv2D_GLOBAL_COLOR_MULTIPLY_DISABLE,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
+ gcv2D_GLOBAL_COLOR_MULTIPLY_COLOR
+}
+gce2D_GLOBAL_COLOR_MULTIPLY_MODE;
+
+/* Alpha blending factor modes. */
+typedef enum _gceSURF_BLEND_FACTOR_MODE
+{
+ gcvSURF_BLEND_ZERO,
+ gcvSURF_BLEND_ONE,
+ gcvSURF_BLEND_STRAIGHT,
+ gcvSURF_BLEND_INVERSED,
+ gcvSURF_BLEND_COLOR,
+ gcvSURF_BLEND_COLOR_INVERSED,
+ gcvSURF_BLEND_SRC_ALPHA_SATURATED
+}
+gceSURF_BLEND_FACTOR_MODE;
+
+/* Alpha blending porter duff rules. */
+typedef enum _gce2D_PORTER_DUFF_RULE
+{
+ gcvPD_CLEAR,
+ gcvPD_SRC,
+ gcvPD_SRC_OVER,
+ gcvPD_DST_OVER,
+ gcvPD_SRC_IN,
+ gcvPD_DST_IN,
+ gcvPD_SRC_OUT,
+ gcvPD_DST_OUT,
+ gcvPD_SRC_ATOP,
+ gcvPD_DST_ATOP,
+ gcvPD_ADD,
+ gcvPD_XOR,
+ gcvPD_DST
+}
+gce2D_PORTER_DUFF_RULE;
+
+/* Alpha blending factor modes. */
+typedef enum _gce2D_YUV_COLOR_MODE
+{
+ gcv2D_YUV_601,
+ gcv2D_YUV_709
+}
+gce2D_YUV_COLOR_MODE;
+
+/* 2D Rotation and flipping. */
+typedef enum _gce2D_ORIENTATION
+{
+ gcv2D_0_DEGREE,
+ gcv2D_90_DEGREE,
+ gcv2D_180_DEGREE,
+ gcv2D_270_DEGREE,
+ gcv2D_X_FLIP,
+ gcv2D_Y_FLIP
+}
+gce2D_ORIENTATION;
+
+typedef enum _gce2D_COMMAND
+{
+ gcv2D_CLEAR,
+ gcv2D_LINE,
+ gcv2D_BLT,
+ gcv2D_STRETCH,
+ gcv2D_HOR_FILTER,
+ gcv2D_VER_FILTER,
+}
+gce2D_COMMAND;
+
+/* Texture functions. */
+typedef enum _gceTEXTURE_FUNCTION
+{
+ gcvTEXTURE_DUMMY = 0,
+ gcvTEXTURE_REPLACE = 0,
+ gcvTEXTURE_MODULATE,
+ gcvTEXTURE_ADD,
+ gcvTEXTURE_ADD_SIGNED,
+ gcvTEXTURE_INTERPOLATE,
+ gcvTEXTURE_SUBTRACT,
+ gcvTEXTURE_DOT3
+}
+gceTEXTURE_FUNCTION;
+
+/* Texture sources. */
+typedef enum _gceTEXTURE_SOURCE
+{
+ gcvCOLOR_FROM_TEXTURE,
+ gcvCOLOR_FROM_CONSTANT_COLOR,
+ gcvCOLOR_FROM_PRIMARY_COLOR,
+ gcvCOLOR_FROM_PREVIOUS_COLOR
+}
+gceTEXTURE_SOURCE;
+
+/* Texture source channels. */
+typedef enum _gceTEXTURE_CHANNEL
+{
+ gcvFROM_COLOR,
+ gcvFROM_ONE_MINUS_COLOR,
+ gcvFROM_ALPHA,
+ gcvFROM_ONE_MINUS_ALPHA
+}
+gceTEXTURE_CHANNEL;
+
+/* Filter types. */
+typedef enum _gceFILTER_TYPE
+{
+ gcvFILTER_SYNC,
+ gcvFILTER_BLUR,
+ gcvFILTER_USER
+}
+gceFILTER_TYPE;
+
+/* Filter pass types. */
+typedef enum _gceFILTER_PASS_TYPE
+{
+ gcvFILTER_HOR_PASS,
+ gcvFILTER_VER_PASS
+}
+gceFILTER_PASS_TYPE;
+
+/* Endian hints. */
+typedef enum _gceENDIAN_HINT
+{
+ gcvENDIAN_NO_SWAP = 0,
+ gcvENDIAN_SWAP_WORD,
+ gcvENDIAN_SWAP_DWORD
+}
+gceENDIAN_HINT;
+
+/* Endian hints. */
+typedef enum _gceTILING
+{
+ gcvLINEAR,
+ gcvTILED,
+ gcvSUPERTILED
+}
+gceTILING;
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoCONTEXT * gcoCONTEXT;
+typedef struct _gcoCMDBUF * gcoCMDBUF;
+typedef struct _gcoQUEUE * gcoQUEUE;
+typedef struct _gcsHAL_INTERFACE * gcsHAL_INTERFACE_PTR;
+typedef struct gcs2D_PROFILE * gcs2D_PROFILE_PTR;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_enum_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/*
+** Include file for the local memory management.
+*/
+
+#ifndef __gc_hal_mem_h_
+#define __gc_hal_mem_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+** Usage:
+
+ The macros to declare MemPool type and functions are
+ gcmMEM_DeclareFSMemPool (Type, TypeName, Prefix)
+ gcmMEM_DeclareVSMemPool (Type, TypeName, Prefix)
+ gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix)
+
+ The data structures for MemPool are
+ typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
+ typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
+ typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
+
+ The MemPool constructor and destructor functions are
+ gcfMEM_InitFSMemPool(gcsMEM_FS_MEM_POOL *, gcoOS, gctUINT, gctUINT);
+ gcfMEM_FreeFSMemPool(gcsMEM_FS_MEM_POOL *);
+ gcfMEM_InitVSMemPool(gcsMEM_VS_MEM_POOL *, gcoOS, gctUINT, gctBOOL);
+ gcfMEM_FreeVSMemPool(gcsMEM_VS_MEM_POOL *);
+ gcfMEM_InitAFSMemPool(gcsMEM_AFS_MEM_POOL *, gcoOS, gctUINT);
+ gcfMEM_FreeAFSMemPool(gcsMEM_AFS_MEM_POOL *);
+
+ FS: for Fixed-Size data structures
+ VS: for Variable-size data structures
+ AFS: for Array of Fixed-Size data structures
+
+
+ // Example 1: For a fixed-size data structure, struct gcsNode.
+ // It is used locally in a file, so the functions are static without prefix.
+ // At top level, declear allocate and free functions.
+ // The first argument is the data type.
+ // The second armument is the short name used in the fuctions.
+ gcmMEM_DeclareFSMemPool(struct gcsNode, Node, );
+
+ // The previous macro creates two inline functions,
+ // _AllocateNode and _FreeNode.
+
+ // In function or struct
+ gcsMEM_FS_MEM_POOL nodeMemPool;
+
+ // In function,
+ struct gcsNode * node;
+ gceSTATUS status;
+
+ // Before using the memory pool, initialize it.
+ // The second argument is the gcoOS object.
+ // The third argument is the number of data structures to allocate for each chunk.
+ status = gcfMEM_InitFSMemPool(&nodeMemPool, os, 100, sizeof(struct gcsNode));
+ ...
+
+ // Allocate a node.
+ status = _AllocateNode(nodeMemPool, &node);
+ ...
+ // Free a node.
+ _FreeNode(nodeMemPool, node);
+
+ // After using the memory pool, free it.
+ gcfMEM_FreeFSMemPool(&nodeMemPool);
+
+
+ // Example 2: For array of fixed-size data structures, struct gcsNode.
+ // It is used in several files, so the functions are extern with prefix.
+ // At top level, declear allocate and free functions.
+ // The first argument is the data type, and the second one is the short name
+ // used in the fuctions.
+ gcmMEM_DeclareAFSMemPool(struct gcsNode, NodeArray, gcfOpt);
+
+ // The previous macro creates two inline functions,
+ // gcfOpt_AllocateNodeArray and gcfOpt_FreeNodeArray.
+
+ // In function or struct
+ gcsMEM_AFS_MEM_POOL nodeArrayMemPool;
+
+ // In function,
+ struct gcsNode * nodeArray;
+ gceSTATUS status;
+
+ // Before using the array memory pool, initialize it.
+ // The second argument is the gcoOS object, the third is the number of data
+ // structures to allocate for each chunk.
+ status = gcfMEM_InitAFSMemPool(&nodeArrayMemPool, os, sizeof(struct gcsNode));
+ ...
+
+ // Allocate a node array of size 100.
+ status = gcfOpt_AllocateNodeArray(nodeArrayMemPool, &nodeArray, 100);
+ ...
+ // Free a node array.
+ gcfOpt_FreeNodeArray(&nodeArrayMemPool, nodeArray);
+
+ // After using the array memory pool, free it.
+ gcfMEM_FreeAFSMemPool(&nodeArrayMemPool);
+
+*******************************************************************************/
+
+/*******************************************************************************
+** To switch back to use gcoOS_Allocate and gcoOS_Free, add
+** #define USE_LOCAL_MEMORY_POOL 0
+** before including this file.
+*******************************************************************************/
+#ifndef USE_LOCAL_MEMORY_POOL
+/*
+ USE_LOCAL_MEMORY_POOL
+
+ This define enables the local memory management to improve performance.
+*/
+#define USE_LOCAL_MEMORY_POOL 1
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Structures
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+ typedef struct _gcsMEM_FS_MEM_POOL * gcsMEM_FS_MEM_POOL;
+ typedef struct _gcsMEM_VS_MEM_POOL * gcsMEM_VS_MEM_POOL;
+ typedef struct _gcsMEM_AFS_MEM_POOL * gcsMEM_AFS_MEM_POOL;
+#else
+ typedef gcoOS gcsMEM_FS_MEM_POOL;
+ typedef gcoOS gcsMEM_VS_MEM_POOL;
+ typedef gcoOS gcsMEM_AFS_MEM_POOL;
+#endif
+
+/*******************************************************************************
+** Memory Pool Macros
+*******************************************************************************/
+#if USE_LOCAL_MEMORY_POOL
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcfMEM_FSMemPoolGetANode(MemPool, (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName##List( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * FirstPointer, \
+ Type * LastPointer \
+ ) \
+{ \
+ return(gcfMEM_FSMemPoolFreeAList(MemPool, (gctPOINTER) FirstPointer, (gctPOINTER) LastPointer)); \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ return(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+ Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcfMEM_VSMemPoolGetANode(MemPool, Size, (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, size)); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcfMEM_VSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ return(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcfMEM_AFSMemPoolGetANode(MemPool, Count, (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcfMEM_AFSMemPoolFreeANode(MemPool, (gctPOINTER) Pointer)); \
+}
+
+#else
+
+#define gcmMEM_DeclareFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ return(gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type ** Pointer \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_FS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcoOS_Free(MemPool, Pointer)); \
+}
+
+#define gcmMEM_DeclareVSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ return(gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Size \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Size, \
+ (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Size)); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_VS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcoOS_Free(MemPool, Pointer)); \
+}
+
+#define gcmMEM_DeclareAFSMemPool(Type, TypeName, Prefix) \
+gceSTATUS \
+Prefix##_Allocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ return(gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+} \
+ \
+gceSTATUS \
+Prefix##_CAllocate##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type ** Pointer, \
+ gctUINT Count \
+ ) \
+{ \
+ gceSTATUS status; \
+ gcmERR_RETURN(gcoOS_Allocate(MemPool, \
+ Count * gcmSIZEOF(Type), \
+ (gctPOINTER *) Pointer)); \
+ gcmVERIFY_OK(gcoOS_ZeroMemory(*(gctPOINTER *) Pointer, Count * gcmSIZEOF(Type))); \
+ return gcvSTATUS_OK; \
+} \
+ \
+gceSTATUS \
+Prefix##_Free##TypeName( \
+ gcsMEM_AFS_MEM_POOL MemPool, \
+ Type * Pointer \
+ ) \
+{ \
+ return(gcoOS_Free(MemPool, Pointer)); \
+}
+#endif
+
+/*******************************************************************************
+** Memory Pool Data Functions
+*******************************************************************************/
+gceSTATUS
+gcfMEM_InitFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeFSMemPool(
+ IN gcsMEM_FS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolGetANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeANode(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_FSMemPoolFreeAList(
+ IN gcsMEM_FS_MEM_POOL MemPool,
+ IN gctPOINTER FirstNode,
+ IN gctPOINTER LastNode
+ );
+
+gceSTATUS
+gcfMEM_InitVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool,
+ IN gcoOS OS,
+ IN gctUINT BlockSize,
+ IN gctBOOL RecycleFreeNode
+ );
+
+gceSTATUS
+gcfMEM_FreeVSMemPool(
+ IN gcsMEM_VS_MEM_POOL * MemPool
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolGetANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctUINT Size,
+ IN gctUINT Alignment,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_VSMemPoolFreeANode(
+ IN gcsMEM_VS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+gceSTATUS
+gcfMEM_InitAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool,
+ IN gcoOS OS,
+ IN gctUINT NodeCount,
+ IN gctUINT NodeSize
+ );
+
+gceSTATUS
+gcfMEM_FreeAFSMemPool(
+ IN gcsMEM_AFS_MEM_POOL *MemPool
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolGetANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctUINT Count,
+ OUT gctPOINTER * Node
+ );
+
+gceSTATUS
+gcfMEM_AFSMemPoolFreeANode(
+ IN gcsMEM_AFS_MEM_POOL MemPool,
+ IN gctPOINTER Node
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_mem_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_options_h_
+#define __gc_hal_options_h_
+
+/*
+ USE_NEW_LINUX_SIGNAL
+
+ This define enables the Linux kernel signaling between kernel and user.
+*/
+#ifndef USE_NEW_LINUX_SIGNAL
+# define USE_NEW_LINUX_SIGNAL 0
+#endif
+
+/*
+ NO_USER_DIRECT_ACCESS_FROM_KERNEL
+
+ This define enables the Linux kernel behavior accessing user memory.
+*/
+#ifndef NO_USER_DIRECT_ACCESS_FROM_KERNEL
+# define NO_USER_DIRECT_ACCESS_FROM_KERNEL 0
+#endif
+
+/*
+ VIVANTE_PROFILER
+
+ This define enables the profiler.
+*/
+#ifndef VIVANTE_PROFILER
+# define VIVANTE_PROFILER 0
+#endif
+
+/*
+ gcdUSE_VG
+
+ Enable VG HAL layer (only for GC350).
+*/
+#ifndef gcdUSE_VG
+# define gcdUSE_VG 0
+#endif
+
+/*
+ USE_SW_FB
+
+ Set to 1 if the frame buffer memory cannot be accessed by the GPU.
+*/
+#ifndef USE_SW_FB
+#define USE_SW_FB 0
+#endif
+
+/*
+ USE_SHADER_SYMBOL_TABLE
+
+ This define enables the symbol table in shader object.
+*/
+#define USE_SHADER_SYMBOL_TABLE 1
+
+/*
+ USE_SUPER_SAMPLING
+
+ This define enables super-sampling support.
+*/
+#define USE_SUPER_SAMPLING 0
+
+/*
+ PROFILE_HAL_COUNTERS
+
+ This define enables HAL counter profiling support.
+ HW and SHADER Counter profiling depends on this.
+*/
+#define PROFILE_HAL_COUNTERS 1
+
+/*
+ PROFILE_HW_COUNTERS
+
+ This define enables HW counter profiling support.
+*/
+#define PROFILE_HW_COUNTERS 1
+
+/*
+ PROFILE_SHADER_COUNTERS
+
+ This define enables SHADER counter profiling support.
+*/
+#define PROFILE_SHADER_COUNTERS 1
+
+/*
+ COMMAND_PROCESSOR_VERSION
+
+ The version of the command buffer and task manager.
+*/
+#define COMMAND_PROCESSOR_VERSION 1
+
+/*
+ gcdDUMP
+
+ When set to 1, a dump of all states and memory uploads, as well as other
+ hardware related execution will be printed to the debug console. This
+ data can be used for playing back applications.
+*/
+#define gcdDUMP 0
+
+/*
+ gcdDUMP_API
+
+ When set to 1, a high level dump of the EGL and GL/VG APs's are
+ captured.
+*/
+#define gcdDUMP_API 0
+
+/*
+ gcdDUMP_IN_KERNEL
+
+ When set to 1, all dumps will happen in the kernel. This is handy if
+ you want the kernel to dump its command buffers as well and the data
+ needs to be in sync.
+*/
+#define gcdDUMP_IN_KERNEL 0
+
+/*
+ gcdDUMP_COMMAND
+
+ When set to non-zero, the command queue will dump all incoming command
+ and context buffers as well as all other modifications to the command
+ queue.
+*/
+#define gcdDUMP_COMMAND 0
+
+/*
+ gcdNULL_DRIVER
+*/
+#define gcdNULL_DRIVER 0
+
+/*
+ gcdENABLE_TIMEOUT_DETECTION
+
+ Enable timeout detection.
+*/
+#define gcdENABLE_TIMEOUT_DETECTION 0
+
+/*
+ gcdCMD_BUFFERS
+
+ Number of command buffers to use per client. Each command buffer is 32kB in
+ size.
+*/
+#define gcdCMD_BUFFERS 2
+
+/*
+ gcdPOWER_CONTROL_DELAY
+
+ The delay in milliseconds required to wait until the GPU has woke up from a
+ suspend or power-down state. This is system dependent because the bus clock
+ also needs to be stabalize.
+*/
+#define gcdPOWER_CONTROL_DELAY 1
+
+/*
+ gcdMMU_SIZE
+
+ Size of the MMU page table in bytes. Each 4 bytes can hold 4kB worth of
+ virtual data.
+*/
+#define gcdMMU_SIZE (128 << 10)
+
+/*
+ gcdSECURE_USER
+
+ Use logical addresses instead of physical addresses in user land. In this
+ case a hint table is created for both command buffers and context buffers,
+ and that hint table will be used to patch up those buffers in the kernel
+ when they are ready to submit.
+*/
+#define gcdSECURE_USER 0
+
+/*
+ gcdSECURE_CACHE_SLOTS
+
+ Number of slots in the logical to DMA address cache table. Each time a
+ logical address needs to be translated into a DMA address for the GPU, this
+ cache will be walked. The replacement scheme is LRU.
+*/
+#define gcdSECURE_CACHE_SLOTS 64
+
+/*
+ gcdREGISTER_ACCESS_FROM_USER
+
+ Set to 1 to allow IOCTL calls to get through from user land. This should
+ only be in debug or development drops.
+*/
+#ifndef gcdREGISTER_ACCESS_FROM_USER
+# define gcdREGISTER_ACCESS_FROM_USER 1
+#endif
+
+/*
+ gcdHEAP_SIZE
+
+ Set the allocation size for the internal heaps. Each time a heap is full,
+ a new heap will be allocated with this minmimum amount of bytes. The bigger
+ this size, the fewer heaps there are to allocate, the better the
+ performance. However, heaps won't be freed until they are completely free,
+ so there might be some more memory waste if the size is too big.
+*/
+#define gcdHEAP_SIZE (64 << 10)
+
+/*
+ gcdNO_POWER_MANAGEMENT
+
+ This define disables the power management code.
+*/
+#ifndef gcdNO_POWER_MANAGEMENT
+# define gcdNO_POWER_MANAGEMENT 0
+#endif
+
+/*
+ gcdFPGA_BUILD
+
+ This define enables work arounds for FPGA images.
+*/
+#if !defined(gcdFPGA_BUILD)
+# define gcdFPGA_BUILD 0
+#endif
+
+/*
+ gcdGPU_TIMEOUT
+
+ This define specified the number of milliseconds the system will wait before
+ it broadcasts the GPU is stuck. In other words, it will define the timeout
+ of any operation that needs to wait for the GPU.
+
+ If the value is 0, no timeout will be checked for.
+*/
+#if !defined(gcdGPU_TIMEOUT)
+# define gcdGPU_TIMEOUT 0
+#endif
+
+#endif /* __gc_hal_options_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+#ifndef __gc_hal_profiler_h_
+#define __gc_hal_profiler_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GLVERTEX_OBJECT 10
+#define GLVERTEX_OBJECT_BYTES 11
+
+#define GLINDEX_OBJECT 20
+#define GLINDEX_OBJECT_BYTES 21
+
+#define GLTEXTURE_OBJECT 30
+#define GLTEXTURE_OBJECT_BYTES 31
+
+#if VIVANTE_PROFILER
+#define gcmPROFILE_GC(Hal, Enum, Value) gcoPROFILER_Count(Hal, Enum, Value)
+#else
+#define gcmPROFILE_GC(Hal, Enum, Value) do { } while (gcvFALSE)
+#endif
+
+/* HW profile information. */
+typedef struct _gcsPROFILER_COUNTERS
+{
+ /* HW static counters. */
+ gctUINT32 gpuClock;
+ gctUINT32 axiClock;
+ gctUINT32 shaderClock;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuClockStart;
+ gctUINT32 gpuClockEnd;
+
+ /* HW vairable counters. */
+ gctUINT32 gpuCyclesCounter;
+ gctUINT32 gpuTotalRead64BytesPerFrame;
+ gctUINT32 gpuTotalWrite64BytesPerFrame;
+
+ /* PE */
+ gctUINT32 pe_pixel_count_killed_by_color_pipe;
+ gctUINT32 pe_pixel_count_killed_by_depth_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_color_pipe;
+ gctUINT32 pe_pixel_count_drawn_by_depth_pipe;
+
+ /* SH */
+ gctUINT32 ps_inst_counter;
+ gctUINT32 rendered_pixel_counter;
+ gctUINT32 vs_inst_counter;
+ gctUINT32 rendered_vertice_counter;
+ gctUINT32 vtx_branch_inst_counter;
+ gctUINT32 vtx_texld_inst_counter;
+ gctUINT32 pxl_branch_inst_counter;
+ gctUINT32 pxl_texld_inst_counter;
+
+ /* PA */
+ gctUINT32 pa_input_vtx_counter;
+ gctUINT32 pa_input_prim_counter;
+ gctUINT32 pa_output_prim_counter;
+ gctUINT32 pa_depth_clipped_counter;
+ gctUINT32 pa_trivial_rejected_counter;
+ gctUINT32 pa_culled_counter;
+
+ /* SE */
+ gctUINT32 se_culled_triangle_count;
+ gctUINT32 se_culled_lines_count;
+
+ /* RA */
+ gctUINT32 ra_valid_pixel_count;
+ gctUINT32 ra_total_quad_count;
+ gctUINT32 ra_valid_quad_count_after_early_z;
+ gctUINT32 ra_total_primitive_count;
+ gctUINT32 ra_pipe_cache_miss_counter;
+ gctUINT32 ra_prefetch_cache_miss_counter;
+ gctUINT32 ra_eez_culled_counter;
+
+ /* TX */
+ gctUINT32 tx_total_bilinear_requests;
+ gctUINT32 tx_total_trilinear_requests;
+ gctUINT32 tx_total_discarded_texture_requests;
+ gctUINT32 tx_total_texture_requests;
+ gctUINT32 tx_mem_read_count;
+ gctUINT32 tx_mem_read_in_8B_count;
+ gctUINT32 tx_cache_miss_count;
+ gctUINT32 tx_cache_hit_texel_count;
+ gctUINT32 tx_cache_miss_texel_count;
+
+ /* MC */
+ gctUINT32 mc_total_read_req_8B_from_pipeline;
+ gctUINT32 mc_total_read_req_8B_from_IP;
+ gctUINT32 mc_total_write_req_8B_from_pipeline;
+
+ /* HI */
+ gctUINT32 hi_axi_cycles_read_request_stalled;
+ gctUINT32 hi_axi_cycles_write_request_stalled;
+ gctUINT32 hi_axi_cycles_write_data_stalled;
+}
+gcsPROFILER_COUNTERS;
+
+/* HAL profile information. */
+typedef struct _gcsPROFILER
+{
+ gctFILE file;
+
+ /* Aggregate Information */
+
+ /* Clock Info */
+ gctUINT64 frameStart;
+ gctUINT64 frameEnd;
+
+ /* Current frame information */
+ gctUINT32 frameNumber;
+ gctUINT64 frameStartTimeusec;
+ gctUINT64 frameEndTimeusec;
+ gctUINT64 frameStartCPUTimeusec;
+ gctUINT64 frameEndCPUTimeusec;
+
+#if PROFILE_HAL_COUNTERS
+ gctUINT32 vertexBufferTotalBytesAlloc;
+ gctUINT32 vertexBufferNewBytesAlloc;
+ int vertexBufferTotalObjectsAlloc;
+ int vertexBufferNewObjectsAlloc;
+
+ gctUINT32 indexBufferTotalBytesAlloc;
+ gctUINT32 indexBufferNewBytesAlloc;
+ int indexBufferTotalObjectsAlloc;
+ int indexBufferNewObjectsAlloc;
+
+ gctUINT32 textureBufferTotalBytesAlloc;
+ gctUINT32 textureBufferNewBytesAlloc;
+ int textureBufferTotalObjectsAlloc;
+ int textureBufferNewObjectsAlloc;
+
+ gctUINT32 numCommits;
+ gctUINT32 drawPointCount;
+ gctUINT32 drawLineCount;
+ gctUINT32 drawTriangleCount;
+ gctUINT32 drawVertexCount;
+ gctUINT32 redundantStateChangeCalls;
+#endif
+}
+gcsPROFILER;
+
+/* Memory profile information. */
+struct _gcsMemProfile
+{
+ /* Memory Usage */
+ gctUINT32 videoMemUsed;
+ gctUINT32 systemMemUsed;
+ gctUINT32 commitBufferSize;
+ gctUINT32 contextBufferCopyBytes;
+};
+
+/* Shader profile information. */
+struct _gcsSHADER_PROFILER
+{
+ gctUINT32 shaderLength;
+ gctUINT32 shaderALUCycles;
+ gctUINT32 shaderTexLoadCycles;
+ gctUINT32 shaderTempRegCount;
+ gctUINT32 shaderSamplerRegCount;
+ gctUINT32 shaderInputRegCount;
+ gctUINT32 shaderOutputRegCount;
+};
+
+/* Initialize the gcsProfiler. */
+gceSTATUS
+gcoPROFILER_Initialize(
+ IN gcoHAL Hal,
+ IN gctFILE File
+ );
+
+/* Destroy the gcProfiler. */
+gceSTATUS
+gcoPROFILER_Destroy(
+ IN gcoHAL Hal
+ );
+
+/* Call to signal end of frame. */
+gceSTATUS
+gcoPROFILER_EndFrame(
+ IN gcoHAL Hal
+ );
+
+gceSTATUS
+gcoPROFILER_Count(
+ IN gcoHAL Hal,
+ IN gctUINT32 Enum,
+ IN gctINT Value
+ );
+
+/* Profile input vertex shader. */
+gceSTATUS
+gcoPROFILER_ShaderVS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Vs
+ );
+
+/* Profile input fragment shader. */
+gceSTATUS
+gcoPROFILER_ShaderFS(
+ IN gcoHAL Hal,
+ IN gctPOINTER Fs
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_profiler_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_raster_h_
+#define __gc_hal_raster_h_
+
+#include "gc_hal_enum.h"
+#include "gc_hal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+****************************** Object Declarations *****************************
+\******************************************************************************/
+
+typedef struct _gcoBRUSH * gcoBRUSH;
+typedef struct _gcoBRUSH_CACHE * gcoBRUSH_CACHE;
+
+/******************************************************************************\
+******************************** gcoBRUSH Object *******************************
+\******************************************************************************/
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructSingleColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructMonochrome(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_ConstructColor(
+ IN gcoHAL Hal,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Destroy an gcoBRUSH object. */
+gceSTATUS
+gcoBRUSH_Destroy(
+ IN gcoBRUSH Brush
+ );
+
+/******************************************************************************\
+******************************** gcoSURF Object *******************************
+\******************************************************************************/
+
+/* Set cipping rectangle. */
+gceSTATUS
+gcoSURF_SetClipping(
+ IN gcoSURF Surface
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gcoSURF_Clear2D(
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 LoColor,
+ IN gctUINT32 HiColor
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gcoSURF_Line(
+ IN gcoSURF Surface,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop
+ );
+
+/* Generic rectangular blit. */
+gceSTATUS
+gcoSURF_Blit(
+ IN OPTIONAL gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gctUINT32 RectCount,
+ IN OPTIONAL gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN OPTIONAL gceSURF_TRANSPARENCY Transparency,
+ IN OPTIONAL gctUINT32 TransparencyColor,
+ IN OPTIONAL gctPOINTER Mask,
+ IN OPTIONAL gceSURF_MONOPACK MaskPack
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gcoSURF_MonoBlit(
+ IN gcoSURF DestSurface,
+ IN gctPOINTER Source,
+ IN gceSURF_MONOPACK SourcePack,
+ IN gcsPOINT_PTR SourceSize,
+ IN gcsPOINT_PTR SourceOrigin,
+ IN gcsRECT_PTR DestRect,
+ IN OPTIONAL gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Filter blit. */
+gceSTATUS
+gcoSURF_FilterBlit(
+ IN gcoSURF SrcSurface,
+ IN gcoSURF DestSurface,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gcoSURF_EnableAlphaBlend(
+ IN gcoSURF Surface,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gcoSURF_DisableAlphaBlend(
+ IN gcoSURF Surface
+ );
+
+/* Copy a rectangular area with format conversion. */
+gceSTATUS
+gcoSURF_CopyPixels(
+ IN gcoSURF Source,
+ IN gcoSURF Target,
+ IN gctINT SourceX,
+ IN gctINT SourceY,
+ IN gctINT TargetX,
+ IN gctINT TargetY,
+ IN gctINT Width,
+ IN gctINT Height
+ );
+
+/* Read surface pixel. */
+gceSTATUS
+gcoSURF_ReadPixel(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gceSURF_FORMAT Format,
+ OUT gctPOINTER PixelValue
+ );
+
+/* Write surface pixel. */
+gceSTATUS
+gcoSURF_WritePixel(
+ IN gcoSURF Surface,
+ IN gctPOINTER Memory,
+ IN gctINT X,
+ IN gctINT Y,
+ IN gceSURF_FORMAT Format,
+ IN gctPOINTER PixelValue
+ );
+
+/******************************************************************************\
+********************************** gco2D Object *********************************
+\******************************************************************************/
+
+/* Construct a new gco2D object. */
+gceSTATUS
+gco2D_Construct(
+ IN gcoHAL Hal,
+ OUT gco2D * Hardware
+ );
+
+/* Destroy an gco2D object. */
+gceSTATUS
+gco2D_Destroy(
+ IN gco2D Hardware
+ );
+
+/* Sets the maximum number of brushes in the brush cache. */
+gceSTATUS
+gco2D_SetBrushLimit(
+ IN gco2D Hardware,
+ IN gctUINT MaxCount
+ );
+
+/* Flush the brush. */
+gceSTATUS
+gco2D_FlushBrush(
+ IN gco2D Engine,
+ IN gcoBRUSH Brush,
+ IN gceSURF_FORMAT Format
+ );
+
+/* Program the specified solid color brush. */
+gceSTATUS
+gco2D_LoadSolidBrush(
+ IN gco2D Engine,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask
+ );
+
+/* Configure monochrome source. */
+gceSTATUS
+gco2D_SetMonochromeSource(
+ IN gco2D Engine,
+ IN gctBOOL ColorConvert,
+ IN gctUINT8 MonoTransparency,
+ IN gceSURF_MONOPACK DataPack,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source extension for full rotation. */
+gceSTATUS
+gco2D_SetColorSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_TRANSPARENCY Transparency,
+ IN gctUINT32 TransparencyColor
+ );
+
+/* Configure color source. */
+gceSTATUS
+gco2D_SetColorSourceAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight,
+ IN gctBOOL CoordRelative
+ );
+
+/* Configure masked color source. */
+gceSTATUS
+gco2D_SetMaskedSource(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack
+ );
+
+/* Configure masked color source extension for full rotation. */
+gceSTATUS
+gco2D_SetMaskedSourceEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_FORMAT Format,
+ IN gctBOOL CoordRelative,
+ IN gceSURF_MONOPACK MaskPack,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Setup the source rectangle. */
+gceSTATUS
+gco2D_SetSource(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect
+ );
+
+/* Set clipping rectangle. */
+gceSTATUS
+gco2D_SetClipping(
+ IN gco2D Engine,
+ IN gcsRECT_PTR Rect
+ );
+
+/* Configure destination. */
+gceSTATUS
+gco2D_SetTarget(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth
+ );
+
+/* Configure destination extension for full rotation. */
+gceSTATUS
+gco2D_SetTargetEx(
+ IN gco2D Engine,
+ IN gctUINT32 Address,
+ IN gctUINT32 Stride,
+ IN gceSURF_ROTATION Rotation,
+ IN gctUINT32 SurfaceWidth,
+ IN gctUINT32 SurfaceHeight
+ );
+
+/* Calculate and program the stretch factors. */
+gceSTATUS
+gco2D_SetStretchFactors(
+ IN gco2D Engine,
+ IN gctUINT32 HorFactor,
+ IN gctUINT32 VerFactor
+ );
+
+/* Calculate and program the stretch factors based on the rectangles. */
+gceSTATUS
+gco2D_SetStretchRectFactors(
+ IN gco2D Engine,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect
+ );
+
+/* Create a new solid color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructSingleColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 Color,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a new monochrome gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructMonochromeBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctUINT32 ColorConvert,
+ IN gctUINT32 FgColor,
+ IN gctUINT32 BgColor,
+ IN gctUINT64 Bits,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Create a color gcoBRUSH object. */
+gceSTATUS
+gco2D_ConstructColorBrush(
+ IN gco2D Engine,
+ IN gctUINT32 OriginX,
+ IN gctUINT32 OriginY,
+ IN gctPOINTER Address,
+ IN gceSURF_FORMAT Format,
+ IN gctUINT64 Mask,
+ gcoBRUSH * Brush
+ );
+
+/* Clear one or more rectangular areas. */
+gceSTATUS
+gco2D_Clear(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines. */
+gceSTATUS
+gco2D_Line(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gcoBRUSH Brush,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Draw one or more Bresenham lines based on the 32-bit color. */
+gceSTATUS
+gco2D_ColorLine(
+ IN gco2D Engine,
+ IN gctUINT32 LineCount,
+ IN gcsRECT_PTR Position,
+ IN gctUINT32 Color32,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Generic blit. */
+gceSTATUS
+gco2D_Blit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Batch blit. */
+gceSTATUS
+gco2D_BatchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR SrcRect,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Stretch blit. */
+gceSTATUS
+gco2D_StretchBlit(
+ IN gco2D Engine,
+ IN gctUINT32 RectCount,
+ IN gcsRECT_PTR Rect,
+ IN gctUINT8 FgRop,
+ IN gctUINT8 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Monochrome blit. */
+gceSTATUS
+gco2D_MonoBlit(
+ IN gco2D Engine,
+ IN gctPOINTER StreamBits,
+ IN gcsPOINT_PTR StreamSize,
+ IN gcsRECT_PTR StreamRect,
+ IN gceSURF_MONOPACK SrcStreamPack,
+ IN gceSURF_MONOPACK DestStreamPack,
+ IN gcsRECT_PTR DestRect,
+ IN gctUINT32 FgRop,
+ IN gctUINT32 BgRop,
+ IN gceSURF_FORMAT DestFormat
+ );
+
+/* Set kernel size. */
+gceSTATUS
+gco2D_SetKernelSize(
+ IN gco2D Engine,
+ IN gctUINT8 HorKernelSize,
+ IN gctUINT8 VerKernelSize
+ );
+
+/* Set filter type. */
+gceSTATUS
+gco2D_SetFilterType(
+ IN gco2D Engine,
+ IN gceFILTER_TYPE FilterType
+ );
+
+/* Set the filter kernel by user. */
+gceSTATUS
+gco2D_SetUserFilterKernel(
+ IN gco2D Engine,
+ IN gceFILTER_PASS_TYPE PassType,
+ IN gctUINT16_PTR KernelArray
+ );
+
+/* Select the pass(es) to be done for user defined filter. */
+gceSTATUS
+gco2D_EnableUserFilterPasses(
+ IN gco2D Engine,
+ IN gctBOOL HorPass,
+ IN gctBOOL VerPass
+ );
+
+/* Frees the temporary buffer allocated by filter blit operation. */
+gceSTATUS
+gco2D_FreeFilterBuffer(
+ IN gco2D Engine
+ );
+
+/* Filter blit. */
+gceSTATUS
+gco2D_FilterBlit(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Filter blit extension for full rotation. */
+gceSTATUS
+gco2D_FilterBlitEx(
+ IN gco2D Engine,
+ IN gctUINT32 SrcAddress,
+ IN gctUINT SrcStride,
+ IN gctUINT32 SrcUAddress,
+ IN gctUINT SrcUStride,
+ IN gctUINT32 SrcVAddress,
+ IN gctUINT SrcVStride,
+ IN gceSURF_FORMAT SrcFormat,
+ IN gceSURF_ROTATION SrcRotation,
+ IN gctUINT32 SrcSurfaceWidth,
+ IN gctUINT32 SrcSurfaceHeight,
+ IN gcsRECT_PTR SrcRect,
+ IN gctUINT32 DestAddress,
+ IN gctUINT DestStride,
+ IN gceSURF_FORMAT DestFormat,
+ IN gceSURF_ROTATION DestRotation,
+ IN gctUINT32 DestSurfaceWidth,
+ IN gctUINT32 DestSurfaceHeight,
+ IN gcsRECT_PTR DestRect,
+ IN gcsRECT_PTR DestSubRect
+ );
+
+/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
+gceSTATUS
+gco2D_EnableAlphaBlend(
+ IN gco2D Engine,
+ IN gctUINT8 SrcGlobalAlphaValue,
+ IN gctUINT8 DstGlobalAlphaValue,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
+ IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
+ IN gceSURF_PIXEL_COLOR_MODE DstColorMode
+ );
+
+/* Enable alpha blending engine in the hardware. */
+gceSTATUS
+gco2D_EnableAlphaBlendAdvanced(
+ IN gco2D Engine,
+ IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
+ IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
+ IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
+ IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
+ IN gceSURF_BLEND_FACTOR_MODE DstFactorMode
+ );
+
+/* Enable alpha blending engine with Porter Duff rule. */
+gceSTATUS
+gco2D_SetPorterDuffBlending(
+ IN gco2D Engine,
+ IN gce2D_PORTER_DUFF_RULE Rule
+ );
+
+/* Disable alpha blending engine in the hardware and engage the ROP engine. */
+gceSTATUS
+gco2D_DisableAlphaBlend(
+ IN gco2D Engine
+ );
+
+/* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
+gctUINT32
+gco2D_GetMaximumDataCount(
+ void
+ );
+
+/* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
+gctUINT32
+gco2D_GetMaximumRectCount(
+ void
+ );
+
+/* Returns the pixel alignment of the surface. */
+gceSTATUS
+gco2D_GetPixelAlignment(
+ gceSURF_FORMAT Format,
+ gcsPOINT_PTR Alignment
+ );
+
+/* Retrieve monochrome stream pack size. */
+gceSTATUS
+gco2D_GetPackSize(
+ IN gceSURF_MONOPACK StreamPack,
+ OUT gctUINT32 * PackWidth,
+ OUT gctUINT32 * PackHeight
+ );
+
+/* Flush the 2D pipeline. */
+gceSTATUS
+gco2D_Flush(
+ IN gco2D Engine
+ );
+
+/* Load 256-entry color table for INDEX8 source surfaces. */
+gceSTATUS
+gco2D_LoadPalette(
+ IN gco2D Engine,
+ IN gctUINT FirstIndex,
+ IN gctUINT IndexCount,
+ IN gctPOINTER ColorTable,
+ IN gctBOOL ColorConvert
+ );
+
+/* Enable/disable 2D BitBlt mirrorring. */
+gceSTATUS
+gco2D_SetBitBlitMirror(
+ IN gco2D Engine,
+ IN gctBOOL HorizontalMirror,
+ IN gctBOOL VerticalMirror
+ );
+
+/* Set the transparency for source, destination and pattern. */
+gceSTATUS
+gco2D_SetTransparencyAdvanced(
+ IN gco2D Engine,
+ IN gce2D_TRANSPARENCY SrcTransparency,
+ IN gce2D_TRANSPARENCY DstTransparency,
+ IN gce2D_TRANSPARENCY PatTransparency
+ );
+
+/* Set the source color key. */
+gceSTATUS
+gco2D_SetSourceColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the source color key range. */
+gceSTATUS
+gco2D_SetSourceColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the target color key. */
+gceSTATUS
+gco2D_SetTargetColorKeyAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKey
+ );
+
+/* Set the target color key range. */
+gceSTATUS
+gco2D_SetTargetColorKeyRangeAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 ColorKeyLow,
+ IN gctUINT32 ColorKeyHigh
+ );
+
+/* Set the YUV color space mode. */
+gceSTATUS
+gco2D_SetYUVColorMode(
+ IN gco2D Engine,
+ IN gce2D_YUV_COLOR_MODE Mode
+ );
+
+/* Setup the source global color value in ARGB8 format. */
+gceSTATUS gco2D_SetSourceGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the target global color value in ARGB8 format. */
+gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
+ IN gco2D Engine,
+ IN gctUINT32 Color32
+ );
+
+/* Setup the source and target pixel multiply modes. */
+gceSTATUS
+gco2D_SetPixelMultiplyModeAdvanced(
+ IN gco2D Engine,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE SrcPremultiplySrcAlpha,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstPremultiplyDstAlpha,
+ IN gce2D_GLOBAL_COLOR_MULTIPLY_MODE SrcPremultiplyGlobalMode,
+ IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstDemultiplyDstAlpha
+ );
+
+/* Set the GPU clock cycles after which the idle engine will keep auto-flushing. */
+gceSTATUS
+gco2D_SetAutoFlushCycles(
+ IN gco2D Engine,
+ IN gctUINT32 Cycles
+ );
+
+/* Read the profile registers available in the 2D engine and sets them in the profile.
+ The function will also reset the pixelsRendered counter every time.
+*/
+gceSTATUS
+gco2D_ProfileEngine(
+ IN gco2D Engine,
+ OPTIONAL gcs2D_PROFILE_PTR Profile
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_raster_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_types_h_
+#define __gc_hal_types_h_
+
+#include "gc_hal_options.h"
+
+#ifdef _WIN32
+#pragma warning(disable:4127) /* Conditional expression is constant (do { }
+ ** while(0)). */
+#pragma warning(disable:4100) /* Unreferenced formal parameter. */
+#pragma warning(disable:4204) /* Non-constant aggregate initializer (C99). */
+#pragma warning(disable:4131) /* Uses old-style declarator (for Bison and
+ ** Flex generated files). */
+#pragma warning(disable:4206) /* Translation unit is empty. */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+** Platform macros.
+*/
+
+#if defined(__GNUC__)
+# define gcdHAS_ELLIPSES 1 /* GCC always has it. */
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define gcdHAS_ELLIPSES 1 /* C99 has it. */
+#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
+# define gcdHAS_ELLIPSES 1 /* MSVC 2007+ has it. */
+#elif defined(UNDER_CE)
+# define gcdHAS_ELLIPSES 0 /* Windows CE doesn't have it. */
+#else
+# error "gcdHAS_ELLIPSES: Platform could not be determined"
+#endif
+
+/******************************************************************************\
+************************************ Keyword ***********************************
+\******************************************************************************/
+
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))
+# define gcmINLINE inline /* C99 keyword. */
+#elif defined(__GNUC__)
+# define gcmINLINE __inline__ /* GNU keyword. */
+#elif defined(_MSC_VER) || defined(UNDER_CE)
+# define gcmINLINE __inline /* Internal keyword. */
+#else
+# error "gcmINLINE: Platform could not be determined"
+#endif
+
+#ifndef gcdDEBUG
+# if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
+# define gcdDEBUG 1
+# else
+# define gcdDEBUG 0
+# endif
+#endif
+
+#ifdef _USRDLL
+# ifdef _MSC_VER
+# ifdef HAL_EXPORTS
+# define HALAPI __declspec(dllexport)
+# else
+# define HALAPI __declspec(dllimport)
+# endif
+# define HALDECL __cdecl
+# else
+# ifdef HAL_EXPORTS
+# define HALAPI
+# else
+# define HALAPI extern
+# endif
+# endif
+#else
+# define HALAPI
+# define HALDECL
+#endif
+
+/******************************************************************************\
+********************************** Common Types ********************************
+\******************************************************************************/
+
+#define gcvFALSE 0
+#define gcvTRUE 1
+
+#define gcvINFINITE ((gctUINT32) ~0U)
+
+typedef int gctBOOL;
+typedef gctBOOL * gctBOOL_PTR;
+
+typedef int gctINT;
+typedef signed char gctINT8;
+typedef signed short gctINT16;
+typedef signed int gctINT32;
+typedef signed long long gctINT64;
+
+typedef gctINT * gctINT_PTR;
+typedef gctINT8 * gctINT8_PTR;
+typedef gctINT16 * gctINT16_PTR;
+typedef gctINT32 * gctINT32_PTR;
+typedef gctINT64 * gctINT64_PTR;
+
+typedef unsigned int gctUINT;
+typedef unsigned char gctUINT8;
+typedef unsigned short gctUINT16;
+typedef unsigned int gctUINT32;
+typedef unsigned long long gctUINT64;
+
+typedef gctUINT * gctUINT_PTR;
+typedef gctUINT8 * gctUINT8_PTR;
+typedef gctUINT16 * gctUINT16_PTR;
+typedef gctUINT32 * gctUINT32_PTR;
+typedef gctUINT64 * gctUINT64_PTR;
+
+typedef unsigned long gctSIZE_T;
+typedef gctSIZE_T * gctSIZE_T_PTR;
+
+#ifdef __cplusplus
+# define gcvNULL 0
+#else
+# define gcvNULL ((void *) 0)
+#endif
+
+typedef float gctFLOAT;
+typedef signed int gctFIXED_POINT;
+typedef float * gctFLOAT_PTR;
+
+typedef void * gctPHYS_ADDR;
+typedef void * gctHANDLE;
+typedef void * gctFILE;
+typedef void * gctSIGNAL;
+typedef void * gctWINDOW;
+typedef void * gctIMAGE;
+
+typedef void * gctPOINTER;
+typedef const void * gctCONST_POINTER;
+
+typedef char gctCHAR;
+typedef char * gctSTRING;
+typedef const char * gctCONST_STRING;
+
+typedef struct _gcsCOUNT_STRING
+{
+ gctSIZE_T Length;
+ gctCONST_STRING String;
+}
+gcsCOUNT_STRING;
+
+/* Fixed point constants. */
+#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
+#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
+#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
+#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
+#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
+
+/******************************************************************************\
+******************************* Fixed Point Math *******************************
+\******************************************************************************/
+
+#define gcmXMultiply(x1, x2) \
+ (gctFIXED_POINT) (((gctINT64) (x1) * (x2)) >> 16)
+
+#define gcmXDivide(x1, x2) \
+ (gctFIXED_POINT) ((((gctINT64) (x1)) << 16) / (x2))
+
+#define gcmXMultiplyDivide(x1, x2, x3) \
+ (gctFIXED_POINT) ((gctINT64) (x1) * (x2) / (x3))
+
+/* 2D Engine profile. */
+struct gcs2D_PROFILE
+{
+ /* Cycle count.
+ 32bit counter incremented every 2D clock cycle.
+ Wraps back to 0 when the counter overflows.
+ */
+ gctUINT32 cycleCount;
+
+ /* Pixels rendered by the 2D engine.
+ Resets to 0 every time it is read. */
+ gctUINT32 pixelsRendered;
+};
+
+
+/* Macro to combine four characters into a Charcater Code. */
+#define gcmCC(c1, c2, c3, c4) \
+( \
+ (char) (c1) \
+ | \
+ ((char) (c2) << 8) \
+ | \
+ ((char) (c3) << 16) \
+ | \
+ ((char) (c4) << 24) \
+)
+
+#define gcmPRINTABLE(c) ((((c) >= ' ') && ((c) <= '}')) ? (c) : ' ')
+
+#define gcmCC_PRINT(cc) \
+ gcmPRINTABLE((char) ( (cc) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 8) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 16) & 0xFF)), \
+ gcmPRINTABLE((char) (((cc) >> 24) & 0xFF))
+
+/******************************************************************************\
+****************************** Function Parameters *****************************
+\******************************************************************************/
+
+#define IN
+#define OUT
+#define OPTIONAL
+
+/******************************************************************************\
+********************************* Status Codes *********************************
+\******************************************************************************/
+
+typedef enum _gceSTATUS
+{
+ gcvSTATUS_OK = 0,
+ gcvSTATUS_FALSE = 0,
+ gcvSTATUS_TRUE = 1,
+ gcvSTATUS_NO_MORE_DATA = 2,
+ gcvSTATUS_CACHED = 3,
+ gcvSTATUS_MIPMAP_TOO_LARGE = 4,
+ gcvSTATUS_NAME_NOT_FOUND = 5,
+ gcvSTATUS_NOT_OUR_INTERRUPT = 6,
+ gcvSTATUS_MISMATCH = 7,
+ gcvSTATUS_MIPMAP_TOO_SMALL = 8,
+ gcvSTATUS_LARGER = 9,
+ gcvSTATUS_SMALLER = 10,
+ gcvSTATUS_CHIP_NOT_READY = 11,
+ gcvSTATUS_NEED_CONVERSION = 12,
+ gcvSTATUS_SKIP = 13,
+ gcvSTATUS_DATA_TOO_LARGE = 14,
+ gcvSTATUS_INVALID_CONFIG = 15,
+ gcvSTATUS_CHANGED = 16,
+
+ gcvSTATUS_INVALID_ARGUMENT = -1,
+ gcvSTATUS_INVALID_OBJECT = -2,
+ gcvSTATUS_OUT_OF_MEMORY = -3,
+ gcvSTATUS_MEMORY_LOCKED = -4,
+ gcvSTATUS_MEMORY_UNLOCKED = -5,
+ gcvSTATUS_HEAP_CORRUPTED = -6,
+ gcvSTATUS_GENERIC_IO = -7,
+ gcvSTATUS_INVALID_ADDRESS = -8,
+ gcvSTATUS_CONTEXT_LOSSED = -9,
+ gcvSTATUS_TOO_COMPLEX = -10,
+ gcvSTATUS_BUFFER_TOO_SMALL = -11,
+ gcvSTATUS_INTERFACE_ERROR = -12,
+ gcvSTATUS_NOT_SUPPORTED = -13,
+ gcvSTATUS_MORE_DATA = -14,
+ gcvSTATUS_TIMEOUT = -15,
+ gcvSTATUS_OUT_OF_RESOURCES = -16,
+ gcvSTATUS_INVALID_DATA = -17,
+ gcvSTATUS_INVALID_MIPMAP = -18,
+ gcvSTATUS_NOT_FOUND = -19,
+ gcvSTATUS_NOT_ALIGNED = -20,
+ gcvSTATUS_INVALID_REQUEST = -21,
+ gcvSTATUS_GPU_NOT_RESPONDING = -22,
+
+ /* Linker errors. */
+ gcvSTATUS_GLOBAL_TYPE_MISMATCH = -1000,
+ gcvSTATUS_TOO_MANY_ATTRIBUTES = -1001,
+ gcvSTATUS_TOO_MANY_UNIFORMS = -1002,
+ gcvSTATUS_TOO_MANY_VARYINGS = -1003,
+ gcvSTATUS_UNDECLARED_VARYING = -1004,
+ gcvSTATUS_VARYING_TYPE_MISMATCH = -1005,
+ gcvSTATUS_MISSING_MAIN = -1006,
+ gcvSTATUS_NAME_MISMATCH = -1007,
+ gcvSTATUS_INVALID_INDEX = -1008,
+}
+gceSTATUS;
+
+/******************************************************************************\
+********************************* Status Macros ********************************
+\******************************************************************************/
+
+#define gcmIS_ERROR(status) (status < 0)
+#define gcmNO_ERROR(status) (status >= 0)
+#define gcmIS_SUCCESS(status) (status == gcvSTATUS_OK)
+
+/******************************************************************************\
+********************************* Field Macros *********************************
+\******************************************************************************/
+
+#define __gcmSTART(reg_field) \
+ (0 ? reg_field)
+
+#define __gcmEND(reg_field) \
+ (1 ? reg_field)
+
+#define __gcmGETSIZE(reg_field) \
+ (__gcmEND(reg_field) - __gcmSTART(reg_field) + 1)
+
+#define __gcmALIGN(data, reg_field) \
+ (((gctUINT32) (data)) << __gcmSTART(reg_field))
+
+#define __gcmMASK(reg_field) \
+ ((gctUINT32) ((__gcmGETSIZE(reg_field) == 32) \
+ ? ~0 \
+ : (~(~0 << __gcmGETSIZE(reg_field)))))
+
+/*******************************************************************************
+**
+** gcmFIELDMASK
+**
+** Get aligned field mask.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmFIELDMASK(reg, field) \
+( \
+ __gcmALIGN(__gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmGETFIELD
+**
+** Extract the value of a field from specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+*/
+#define gcmGETFIELD(data, reg, field) \
+( \
+ ((((gctUINT32) (data)) >> __gcmSTART(reg##_##field)) \
+ & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELD
+**
+** Set the value of a field within specified data.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETFIELD(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN((gctUINT32) (value) \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmSETFIELDVALUE
+**
+** Set the value of a field within specified data with a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmSETFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) \
+ & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
+ | __gcmALIGN(reg##_##field##_##value \
+ & __gcmMASK(reg##_##field), reg##_##field) \
+)
+
+/*******************************************************************************
+**
+** gcmSETMASKEDFIELD
+**
+** Set the value of a masked field with specified data.
+**
+** ARGUMENTS:
+**
+** reg Name of register.
+** field Name of field within register.
+** value Value for field.
+*/
+#define gcmSETMASKEDFIELD(reg, field, value) \
+( \
+ gcmSETFIELD(~0, reg, field, value) & \
+ gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
+)
+
+/*******************************************************************************
+**
+** gcmVERIFYFIELDVALUE
+**
+** Verify if the value of a field within specified data equals a
+** predefined value.
+**
+** ARGUMENTS:
+**
+** data Data value.
+** reg Name of register.
+** field Name of field within register.
+** value Name of the value within the field.
+*/
+#define gcmVERIFYFIELDVALUE(data, reg, field, value) \
+( \
+ (((gctUINT32) (data)) >> __gcmSTART(reg##_##field) & \
+ __gcmMASK(reg##_##field)) \
+ == \
+ (reg##_##field##_##value & __gcmMASK(reg##_##field)) \
+)
+
+/*******************************************************************************
+** Bit field macros.
+*/
+
+#define __gcmSTARTBIT(Field) \
+ ( 1 ? Field )
+
+#define __gcmBITSIZE(Field) \
+ ( 0 ? Field )
+
+#define __gcmBITMASK(Field) \
+( \
+ (1 << __gcmBITSIZE(Field)) - 1 \
+)
+
+#define gcmGETBITS(Value, Type, Field) \
+( \
+ ( ((Type) (Value)) >> __gcmSTARTBIT(Field) ) \
+ & \
+ __gcmBITMASK(Field) \
+)
+
+#define gcmSETBITS(Value, Type, Field, NewValue) \
+( \
+ ( ((Type) (Value)) \
+ & ~(__gcmBITMASK(Field) << __gcmSTARTBIT(Field)) \
+ ) \
+ | \
+ ( ( ((Type) (NewValue)) \
+ & __gcmBITMASK(Field) \
+ ) << __gcmSTARTBIT(Field) \
+ ) \
+)
+
+/******************************************************************************\
+******************************** Min/Max Macros ********************************
+\******************************************************************************/
+
+#define gcmMIN(x, y) (((x) <= (y)) ? (x) : (y))
+#define gcmMAX(x, y) (((x) >= (y)) ? (x) : (y))
+#define gcmCLAMP(x, min, max) (((x) < (min)) ? (min) : \
+ ((x) > (max)) ? (max) : (x))
+#define gcmABS(x) (((x) < 0) ? -(x) : (x))
+#define gcmNEG(x) (((x) < 0) ? (x) : -(x))
+
+/*******************************************************************************
+**
+** gcmPTR2INT
+**
+** Convert a pointer to an integer value.
+**
+** ARGUMENTS:
+**
+** p Pointer value.
+*/
+#if defined(_WIN32) || (defined(__LP64__) && __LP64__)
+# define gcmPTR2INT(p) \
+ ( \
+ (gctUINT32) (gctUINT64) (p) \
+ )
+#else
+# define gcmPTR2INT(p) \
+ ( \
+ (gctUINT32) (p) \
+ )
+#endif
+
+/*******************************************************************************
+**
+** gcmINT2PTR
+**
+** Convert an integer value into a pointer.
+**
+** ARGUMENTS:
+**
+** v Integer value.
+*/
+#define gcmINT2PTR(i) \
+( \
+ (gctPOINTER) (i) \
+)
+
+/*******************************************************************************
+**
+** gcmOFFSETOF
+**
+** Compute the byte offset of a field inside a structure.
+**
+** ARGUMENTS:
+**
+** s Structure name.
+** field Field name.
+*/
+#define gcmOFFSETOF(s, field) \
+( \
+ gcmPTR2INT(& (((struct s *) 0)->field)) \
+)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_types_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_Construct
+**
+** Construct a new gckKERNEL object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN gctPOINTER Context
+** Pointer to a driver defined context.
+**
+** OUTPUT:
+**
+** gckKERNEL * Kernel
+** Pointer to a variable that will hold the pointer to the gckKERNEL
+** object.
+*/
+
+#ifdef ANDROID
+#define DEFAULT_PROFILE_FILE_NAME "/sdcard/vprofiler.xml"
+#else
+#define DEFAULT_PROFILE_FILE_NAME "vprofiler.xml"
+#endif
+
+gceSTATUS
+gckKERNEL_Construct(
+ IN gckOS Os,
+ IN gctPOINTER Context,
+ OUT gckKERNEL * Kernel
+ )
+{
+ gckKERNEL kernel = gcvNULL;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
+
+ /* Allocate the gckKERNEL object. */
+ gcmkONERROR(
+ gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckKERNEL),
+ (gctPOINTER *) &kernel));
+
+ /* Zero the object pointers. */
+ kernel->hardware = gcvNULL;
+ kernel->command = gcvNULL;
+ kernel->event = gcvNULL;
+ kernel->mmu = gcvNULL;
+
+ /* Initialize the gckKERNEL object. */
+ kernel->object.type = gcvOBJ_KERNEL;
+ kernel->os = Os;
+
+ /* Save context. */
+ kernel->context = Context;
+
+ /* Construct atom holding number of clients. */
+ kernel->atomClients = gcvNULL;
+ gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
+
+#if gcdSECURE_USER
+ kernel->cacheSlots = 0;
+ kernel->cacheTimeStamp = 0;
+#endif
+
+ /* Construct the gckHARDWARE object. */
+ gcmkONERROR(
+ gckHARDWARE_Construct(Os, &kernel->hardware));
+
+ /* Set pointer to gckKERNEL object in gckHARDWARE object. */
+ kernel->hardware->kernel = kernel;
+
+ /* Initialize the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_InitializeHardware(kernel->hardware));
+
+ /* Construct the gckCOMMAND object. */
+ gcmkONERROR(
+ gckCOMMAND_Construct(kernel, &kernel->command));
+
+ /* Construct the gckEVENT object. */
+ gcmkONERROR(
+ gckEVENT_Construct(kernel, &kernel->event));
+
+ /* Construct the gckMMU object. */
+ gcmkONERROR(
+ gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
+
+#if VIVANTE_PROFILER
+ /* Initialize profile setting */
+#if defined ANDROID
+ kernel->profileEnable = gcvFALSE;
+#else
+ kernel->profileEnable = gcvTRUE;
+#endif
+
+ gcmkVERIFY_OK(
+ gckOS_MemCopy(kernel->profileFileName,
+ DEFAULT_PROFILE_FILE_NAME,
+ gcmSIZEOF(DEFAULT_PROFILE_FILE_NAME) + 1));
+#endif
+
+ /* Return pointer to the gckKERNEL object. */
+ *Kernel = kernel;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (kernel != gcvNULL)
+ {
+ if (kernel->event != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_Destroy(kernel->event));
+ }
+
+ if (kernel->command != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel->command));
+ }
+
+ if (kernel->hardware != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel->hardware));
+ }
+
+ if (kernel->atomClients != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(Os, kernel));
+ }
+
+ /* Return the error. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Destroy
+**
+** Destroy an gckKERNEL object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Destroy(
+ IN gckKERNEL Kernel
+ )
+{
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Destroy the gckMMU object. */
+ gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
+
+ /* Destroy the gckEVENT object. */
+ gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->event));
+
+ /* Destroy the gckCOMMNAND object. */
+ gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
+
+ /* Destroy the gckHARDWARE object. */
+ gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
+
+ /* Detsroy the client atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
+
+ /* Mark the gckKERNEL object as unknown. */
+ Kernel->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckKERNEL object. */
+ gcmkVERIFY_OK(gckOS_Free(Kernel->os, Kernel));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** _AllocateMemory
+**
+** Private function to walk all required memory pools to allocate the requested
+** amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+static gceSTATUS
+_AllocateMemory(
+ IN gckKERNEL Kernel,
+ IN OUT gcePOOL * Pool,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gcePOOL pool;
+ gceSTATUS status;
+ gckVIDMEM videoMemory;
+
+ gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
+
+ /* Get initial pool. */
+ switch (pool = *Pool)
+ {
+ case gcvPOOL_DEFAULT:
+ case gcvPOOL_LOCAL:
+ pool = gcvPOOL_LOCAL_INTERNAL;
+ break;
+
+ case gcvPOOL_UNIFIED:
+ pool = gcvPOOL_SYSTEM;
+ break;
+
+ default:
+ break;
+ }
+
+ do
+ {
+ /* Verify the number of bytes to allocate. */
+ if (Bytes == 0)
+ {
+ gcmkERR_BREAK(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (pool == gcvPOOL_VIRTUAL)
+ {
+ /* Create a gcuVIDMEM_NODE for virtual memory. */
+#ifdef __QNXNTO__
+ gcmkERR_BREAK(
+ gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Handle, Node));
+#else
+ gcmkERR_BREAK(
+ gckVIDMEM_ConstructVirtual(Kernel, gcvFALSE, Bytes, Node));
+#endif
+
+ /* Success. */
+ break;
+ }
+ else if (pool == gcvPOOL_CONTIGUOUS)
+ {
+ /* Create a gcuVIDMEM_NODE for contiguous memory. */
+#ifdef __QNXNTO__
+ status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Handle, Node);
+#else
+ status = gckVIDMEM_ConstructVirtual(Kernel, gcvTRUE, Bytes, Node);
+#endif
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Memory allocated. */
+ break;
+ }
+ }
+ else
+ {
+ /* Get pointer to gckVIDMEM object for pool. */
+ status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Allocate memory. */
+ status = gckVIDMEM_AllocateLinear(videoMemory,
+ Bytes,
+ Alignment,
+ Type,
+#ifdef __QNXNTO__
+ Handle,
+#endif
+ Node);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Memory allocated. */
+ (*Node)->VidMem.pool = pool;
+ break;
+ }
+ }
+ }
+
+ if (pool == gcvPOOL_LOCAL_INTERNAL)
+ {
+ /* Advance to external memory. */
+ pool = gcvPOOL_LOCAL_EXTERNAL;
+ }
+ else
+ if (pool == gcvPOOL_LOCAL_EXTERNAL)
+ {
+ /* Advance to contiguous system memory. */
+ pool = gcvPOOL_SYSTEM;
+ }
+ else
+ if (pool == gcvPOOL_SYSTEM)
+ {
+ /* Advance to contiguous memory. */
+ pool = gcvPOOL_CONTIGUOUS;
+ }
+ else
+ if ((pool == gcvPOOL_CONTIGUOUS)
+ && (Type != gcvSURF_TILE_STATUS)
+ )
+ {
+ /* Advance to virtual memory. */
+ pool = gcvPOOL_VIRTUAL;
+ }
+ else
+ {
+ /* Out of pools. */
+ break;
+ }
+ }
+ /* Loop only for multiple selection pools. */
+ while ((*Pool == gcvPOOL_DEFAULT)
+ || (*Pool == gcvPOOL_LOCAL)
+ || (*Pool == gcvPOOL_UNIFIED)
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Return pool used for allocation. */
+ *Pool = pool;
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Dispatch
+**
+** Dispatch a command received from the user HAL layer.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL FromUser
+** whether the call is from the user space.
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that defines the command to
+** be dispatched.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
+** returned.
+*/
+gceSTATUS
+gckKERNEL_Dispatch(
+ IN gckKERNEL Kernel,
+ IN gctBOOL FromUser,
+ IN OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gceSTATUS status;
+ gctUINT32 bitsPerPixel;
+ gctSIZE_T bytes;
+ gcuVIDMEM_NODE_PTR node;
+ gctBOOL locked = gcvFALSE;
+ gctPHYS_ADDR physical;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
+ Kernel, FromUser, Interface);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
+ "Dispatching command %d", Interface->command);
+
+ /* Dispatch on command. */
+ switch (Interface->command)
+ {
+ case gcvHAL_GET_BASE_ADDRESS:
+ /* Get base address. */
+ gcmkONERROR(
+ gckOS_GetBaseAddress(Kernel->os,
+ &Interface->u.GetBaseAddress.baseAddress));
+ break;
+
+ case gcvHAL_QUERY_VIDEO_MEMORY:
+ /* Query video memory size. */
+ gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
+ break;
+
+ case gcvHAL_QUERY_CHIP_IDENTITY:
+ /* Query chip identity. */
+ gcmkONERROR(
+ gckHARDWARE_QueryChipIdentity(
+ Kernel->hardware,
+ &Interface->u.QueryChipIdentity.chipModel,
+ &Interface->u.QueryChipIdentity.chipRevision,
+ &Interface->u.QueryChipIdentity.chipFeatures,
+ &Interface->u.QueryChipIdentity.chipMinorFeatures,
+ &Interface->u.QueryChipIdentity.chipMinorFeatures1));
+
+ /* Query chip specifications. */
+ gcmkONERROR(
+ gckHARDWARE_QueryChipSpecs(
+ Kernel->hardware,
+ &Interface->u.QueryChipIdentity.streamCount,
+ &Interface->u.QueryChipIdentity.registerMax,
+ &Interface->u.QueryChipIdentity.threadCount,
+ &Interface->u.QueryChipIdentity.shaderCoreCount,
+ &Interface->u.QueryChipIdentity.vertexCacheSize,
+ &Interface->u.QueryChipIdentity.vertexOutputBufferSize));
+ break;
+
+ case gcvHAL_MAP_MEMORY:
+ physical = Interface->u.MapMemory.physical;
+
+ /* Map memory. */
+ gcmkONERROR(
+ gckKERNEL_MapMemory(Kernel,
+ physical,
+ Interface->u.MapMemory.bytes,
+ &Interface->u.MapMemory.logical));
+ break;
+
+ case gcvHAL_UNMAP_MEMORY:
+ physical = Interface->u.UnmapMemory.physical;
+
+ /* Unmap memory. */
+ gcmkONERROR(
+ gckKERNEL_UnmapMemory(Kernel,
+ physical,
+ Interface->u.UnmapMemory.bytes,
+ Interface->u.UnmapMemory.logical));
+ break;
+
+ case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
+ /* Allocate non-paged memory. */
+#ifdef __QNXNTO__
+ if (FromUser)
+ {
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemoryShmPool(
+ Kernel->os,
+ FromUser,
+ Interface->pid,
+ Interface->handle,
+ &Interface->u.AllocateNonPagedMemory.bytes,
+ &Interface->u.AllocateNonPagedMemory.physical,
+ &Interface->u.AllocateNonPagedMemory.logical));
+ break;
+ }
+#endif
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemory(
+ Kernel->os,
+ FromUser,
+ &Interface->u.AllocateNonPagedMemory.bytes,
+ &Interface->u.AllocateNonPagedMemory.physical,
+ &Interface->u.AllocateNonPagedMemory.logical));
+ break;
+
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ physical = Interface->u.FreeNonPagedMemory.physical;
+
+ /* Free non-paged memory. */
+ gcmkONERROR(
+ gckOS_FreeNonPagedMemory(Kernel->os,
+ Interface->u.FreeNonPagedMemory.bytes,
+ physical,
+ Interface->u.FreeNonPagedMemory.logical));
+ break;
+
+ case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
+ /* Allocate contiguous memory. */
+#ifdef __QNXNTO__
+ if (FromUser)
+ {
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemoryShmPool(
+ Kernel->os,
+ FromUser,
+ Interface->pid,
+ Interface->handle,
+ &Interface->u.AllocateNonPagedMemory.bytes,
+ &Interface->u.AllocateNonPagedMemory.physical,
+ &Interface->u.AllocateNonPagedMemory.logical));
+ break;
+ }
+#endif
+ gcmkONERROR(
+ gckOS_AllocateContiguous(
+ Kernel->os,
+ FromUser,
+ &Interface->u.AllocateContiguousMemory.bytes,
+ &Interface->u.AllocateContiguousMemory.physical,
+ &Interface->u.AllocateContiguousMemory.logical));
+
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ physical = Interface->u.FreeContiguousMemory.physical;
+
+ /* Free contiguous memory. */
+ gcmkONERROR(
+ gckOS_FreeContiguous(Kernel->os,
+ physical,
+ Interface->u.FreeContiguousMemory.logical,
+ Interface->u.FreeContiguousMemory.bytes));
+ break;
+
+ case gcvHAL_ALLOCATE_VIDEO_MEMORY:
+ /* Align width and height to tiles. */
+ gcmkONERROR(
+ gckHARDWARE_AlignToTile(Kernel->hardware,
+ Interface->u.AllocateVideoMemory.type,
+ &Interface->u.AllocateVideoMemory.width,
+ &Interface->u.AllocateVideoMemory.height,
+ gcvNULL));
+
+ /* Convert format into bytes per pixel and bytes per tile. */
+ gcmkONERROR(
+ gckHARDWARE_ConvertFormat(Kernel->hardware,
+ Interface->u.AllocateVideoMemory.format,
+ &bitsPerPixel,
+ gcvNULL));
+
+ /* Compute number of bytes for the allocation. */
+ bytes = Interface->u.AllocateVideoMemory.width * bitsPerPixel
+ * Interface->u.AllocateVideoMemory.height
+ * Interface->u.AllocateVideoMemory.depth / 8;
+
+ /* Allocate memory. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateVideoMemory.pool,
+ bytes,
+ 64,
+ Interface->u.AllocateVideoMemory.type,
+ Interface->handle,
+ &Interface->u.AllocateVideoMemory.node));
+#else
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateVideoMemory.pool,
+ bytes,
+ 64,
+ Interface->u.AllocateVideoMemory.type,
+ &Interface->u.AllocateVideoMemory.node));
+#endif
+ break;
+
+ case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+ /* Allocate memory. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateLinearVideoMemory.pool,
+ Interface->u.AllocateLinearVideoMemory.bytes,
+ Interface->u.AllocateLinearVideoMemory.alignment,
+ Interface->u.AllocateLinearVideoMemory.type,
+ Interface->handle,
+ &Interface->u.AllocateLinearVideoMemory.node));
+
+ /* Set the current user pid in the node,
+ * which is used while locking memory. */
+ gcmkVERIFY_OK(gckVIDMEM_SetPID(
+ Interface->u.AllocateLinearVideoMemory.node,
+ Interface->pid));
+#else
+ gcmkONERROR(
+ _AllocateMemory(Kernel,
+ &Interface->u.AllocateLinearVideoMemory.pool,
+ Interface->u.AllocateLinearVideoMemory.bytes,
+ Interface->u.AllocateLinearVideoMemory.alignment,
+ Interface->u.AllocateLinearVideoMemory.type,
+ &Interface->u.AllocateLinearVideoMemory.node));
+#endif
+ break;
+
+ case gcvHAL_FREE_VIDEO_MEMORY:
+#ifdef __QNXNTO__
+ node = Interface->u.FreeVideoMemory.node;
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM
+ && node->VidMem.logical != gcvNULL)
+ {
+ gcmkONERROR(
+ gckKERNEL_UnmapVideoMemory(Kernel,
+ node->VidMem.logical,
+ Interface->pid,
+ node->VidMem.bytes));
+ node->VidMem.logical = gcvNULL;
+ }
+#endif
+ /* Free video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Free(Interface->u.FreeVideoMemory.node));
+ break;
+
+ case gcvHAL_LOCK_VIDEO_MEMORY:
+ /* Lock video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Lock(Interface->u.LockVideoMemory.node,
+ &Interface->u.LockVideoMemory.address));
+
+ locked = gcvTRUE;
+
+ node = Interface->u.LockVideoMemory.node;
+ if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ /* Map video memory address into user space. */
+#ifdef __QNXNTO__
+ if (node->VidMem.logical == gcvNULL)
+ {
+ gcmkONERROR(
+ gckKERNEL_MapVideoMemory(Kernel,
+ FromUser,
+ Interface->u.LockVideoMemory.address,
+ Interface->pid,
+ node->VidMem.bytes,
+ &node->VidMem.logical));
+ }
+ Interface->u.LockVideoMemory.memory = node->VidMem.logical;
+#else
+ gcmkONERROR(
+ gckKERNEL_MapVideoMemory(Kernel,
+ FromUser,
+ Interface->u.LockVideoMemory.address,
+ &Interface->u.LockVideoMemory.memory));
+#endif
+
+#ifdef __QNXNTO__
+ /* Add more information to node, which is used while unmapping. */
+ gcmkVERIFY_OK(gckVIDMEM_SetPID(
+ Interface->u.LockVideoMemory.node,
+ Interface->pid));
+#endif
+ }
+
+ else
+ {
+ /* Copy logical memory for virtual memory. */
+ Interface->u.LockVideoMemory.memory = node->Virtual.logical;
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+
+#if gcdSECURE_USER
+ /* Return logical address as physical address. */
+ Interface->u.LockVideoMemory.address =
+ gcmPTR2INT(Interface->u.LockVideoMemory.memory);
+#endif
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ /* Unlock video memory. */
+ node = Interface->u.UnlockVideoMemory.node;
+
+ /* Unlock video memory. */
+ gcmkONERROR(
+ gckVIDMEM_Unlock(node,
+ Interface->u.UnlockVideoMemory.type,
+ &Interface->u.UnlockVideoMemory.asynchroneous));
+ break;
+
+ case gcvHAL_EVENT_COMMIT:
+ /* Commit an event queue. */
+ gcmkONERROR(
+ gckEVENT_Commit(Kernel->event,
+ Interface->u.Event.queue));
+ break;
+
+ case gcvHAL_COMMIT:
+ /* Commit a command and context buffer. */
+ gcmkONERROR(
+ gckCOMMAND_Commit(Kernel->command,
+ Interface->u.Commit.commandBuffer,
+ Interface->u.Commit.contextBuffer,
+ Interface->u.Commit.process));
+ break;
+
+ case gcvHAL_STALL:
+ /* Stall the command queue. */
+ gcmkONERROR(gckCOMMAND_Stall(Kernel->command));
+ break;
+
+ case gcvHAL_MAP_USER_MEMORY:
+ /* Map user memory to DMA. */
+ gcmkONERROR(
+ gckOS_MapUserMemory(Kernel->os,
+ Interface->u.MapUserMemory.memory,
+ Interface->u.MapUserMemory.size,
+ &Interface->u.MapUserMemory.info,
+ &Interface->u.MapUserMemory.address));
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ address = Interface->u.MapUserMemory.address;
+
+ /* Unmap user memory. */
+ gcmkONERROR(
+ gckOS_UnmapUserMemory(Kernel->os,
+ Interface->u.UnmapUserMemory.memory,
+ Interface->u.UnmapUserMemory.size,
+ Interface->u.UnmapUserMemory.info,
+ address));
+ break;
+
+#if !USE_NEW_LINUX_SIGNAL
+ case gcvHAL_USER_SIGNAL:
+ /* Dispatch depends on the user signal subcommands. */
+ switch(Interface->u.UserSignal.command)
+ {
+ case gcvUSER_SIGNAL_CREATE:
+ /* Create a signal used in the user space. */
+ gcmkONERROR(
+ gckOS_CreateUserSignal(Kernel->os,
+ Interface->u.UserSignal.manualReset,
+ &Interface->u.UserSignal.id));
+ break;
+
+ case gcvUSER_SIGNAL_DESTROY:
+ /* Destroy the signal. */
+ gcmkONERROR(
+ gckOS_DestroyUserSignal(Kernel->os,
+ Interface->u.UserSignal.id));
+ break;
+
+ case gcvUSER_SIGNAL_SIGNAL:
+ /* Signal the signal. */
+ gcmkONERROR(
+ gckOS_SignalUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.state));
+ break;
+
+ case gcvUSER_SIGNAL_WAIT:
+ /* Wait on the signal. */
+ status = gckOS_WaitUserSignal(Kernel->os,
+ Interface->u.UserSignal.id,
+ Interface->u.UserSignal.wait);
+ break;
+
+ default:
+ /* Invalid user signal command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ break;
+#endif
+
+ case gcvHAL_SET_POWER_MANAGEMENT_STATE:
+ /* Set the power management state. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(
+ Kernel->hardware,
+ Interface->u.SetPowerManagement.state));
+ break;
+
+ case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
+ /* Chip is not idle. */
+ Interface->u.QueryPowerManagement.isIdle = gcvFALSE;
+
+ /* Query the power management state. */
+ gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
+ Kernel->hardware,
+ &Interface->u.QueryPowerManagement.state));
+
+ /* Query the idle state. */
+ gcmkONERROR(
+ gckHARDWARE_QueryIdle(Kernel->hardware,
+ &Interface->u.QueryPowerManagement.isIdle));
+ break;
+
+ case gcvHAL_READ_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ /* Read a register. */
+ gcmkONERROR(
+ gckOS_ReadRegister(Kernel->os,
+ Interface->u.ReadRegisterData.address,
+ &Interface->u.ReadRegisterData.data));
+#else
+ /* No access from user land to read registers. */
+ Interface->u.ReadRegisterData.data = 0;
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_WRITE_REGISTER:
+#if gcdREGISTER_ACCESS_FROM_USER
+ /* Write a register. */
+ gcmkONERROR(
+ gckOS_WriteRegister(Kernel->os,
+ Interface->u.WriteRegisterData.address,
+ Interface->u.WriteRegisterData.data));
+#else
+ /* No access from user land to write registers. */
+ status = gcvSTATUS_NOT_SUPPORTED;
+#endif
+ break;
+
+ case gcvHAL_READ_ALL_PROFILE_REGISTERS:
+#if VIVANTE_PROFILER
+ /* Read all 3D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_QueryProfileRegisters(
+ Kernel->hardware,
+ &Interface->u.RegisterProfileData.counters));
+#else
+ status = gcvSTATUS_OK;
+#endif
+ break;
+
+ case gcvHAL_PROFILE_REGISTERS_2D:
+#if VIVANTE_PROFILER
+ /* Read all 2D profile registers. */
+ gcmkONERROR(
+ gckHARDWARE_ProfileEngine2D(
+ Kernel->hardware,
+ Interface->u.RegisterProfileData2D.hwProfile2D));
+#else
+ status = gcvSTATUS_OK;
+#endif
+ break;
+
+ case gcvHAL_GET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+ /* Get profile setting */
+ Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
+
+ gcmkVERIFY_OK(
+ gckOS_MemCopy(Interface->u.GetProfileSetting.fileName,
+ Kernel->profileFileName,
+ gcdMAX_PROFILE_FILE_NAME));
+#endif
+
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_SET_PROFILE_SETTING:
+#if VIVANTE_PROFILER
+ /* Set profile setting */
+ Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
+
+ gcmkVERIFY_OK(
+ gckOS_MemCopy(Kernel->profileFileName,
+ Interface->u.SetProfileSetting.fileName,
+ gcdMAX_PROFILE_FILE_NAME));
+#endif
+
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_QUERY_KERNEL_SETTINGS:
+ /* Get kernel settings. */
+ gcmkONERROR(
+ gckKERNEL_QuerySettings(Kernel,
+ &Interface->u.QueryKernelSettings.settings));
+ break;
+
+ case gcvHAL_RESET:
+ /* Reset the hardware. */
+ gcmkONERROR(
+ gckHARDWARE_Reset(Kernel->hardware));
+ break;
+
+ case gcvHAL_DEBUG:
+ /* Set debug level and zones. */
+ if (Interface->u.Debug.set)
+ {
+ gckOS_SetDebugLevel(Interface->u.Debug.level);
+ gckOS_SetDebugZones(Interface->u.Debug.zones,
+ Interface->u.Debug.enable);
+ }
+
+ if (Interface->u.Debug.message[0] != '\0')
+ {
+ /* Print a message to the debugger. */
+ gcmkPRINT(Interface->u.Debug.message);
+ }
+ status = gcvSTATUS_OK;
+ break;
+
+ case gcvHAL_CACHE:
+ if (Interface->u.Cache.invalidate)
+ {
+ /* Flush and invalidate the cache. */
+ status = gckOS_CacheInvalidate(Kernel->os,
+ Interface->u.Cache.process,
+ Interface->u.Cache.logical,
+ Interface->u.Cache.bytes);
+ }
+ else
+ {
+ /* Flush the cache. */
+ status = gckOS_CacheFlush(Kernel->os,
+ Interface->u.Cache.process,
+ Interface->u.Cache.logical,
+ Interface->u.Cache.bytes);
+ }
+ break;
+
+ default:
+ /* Invalid command. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+OnError:
+ /* Save status. */
+ Interface->status = status;
+
+ if (gcmIS_ERROR(status))
+ {
+ if (locked)
+ {
+ /* Roll back the lock. */
+ gcmkVERIFY_OK(
+ gckVIDMEM_Unlock(Interface->u.LockVideoMemory.node,
+ gcvSURF_TYPE_UNKNOWN,
+ gcvNULL));
+ }
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ )
+{
+ gceSTATUS status;
+ gctINT32 old;
+
+ gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (Attach)
+ {
+ /* Increment the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 0)
+ {
+ gcmkONERROR(gckOS_Broadcast(Kernel->os,
+ Kernel->hardware,
+ gcvBROADCAST_FIRST_PROCESS));
+ }
+ }
+
+ else
+ {
+ /* Decrement the number of clients attached. */
+ gcmkONERROR(
+ gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
+
+ if (old == 1)
+ {
+ /* Last client detached, switch to SUSPEND power state. */
+ gcmkONERROR(gckOS_Broadcast(Kernel->os,
+ Kernel->hardware,
+ gcvBROADCAST_LAST_PROCESS));
+
+ /* Flush the debug cache. */
+ gcmkPRINT("$$FLUSH$$");
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gctHANDLE Process,
+ IN OUT gctPOINTER * Data
+ )
+{
+ gctUINT i, oldest;
+ gceSTATUS status;
+ gctUINT32 baseAddress;
+
+ gcmkHEADER_ARG("Kernel=0x%x Process=0x%x *Data=0x%x",
+ Kernel, Process, gcmOPT_POINTER(Data));
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Data != gcvNULL);
+
+ /* Get base address. */
+ gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
+
+ /* Walk all used cache slots. */
+ for (i = oldest = 0; i < Kernel->cacheSlots; ++i)
+ {
+ if ((Kernel->cache[i].logical == *Data)
+ && (Kernel->cache[i].process == Process)
+ )
+ {
+ /* Bail out. */
+ break;
+ }
+
+ if (i == 0)
+ {
+ /* First slot. */
+ oldest = i;
+ }
+
+ /* Test if this cache slot is older. */
+ else if (Kernel->cache[i].stamp < Kernel->cache[oldest].stamp)
+ {
+ oldest = i;
+ }
+ }
+
+ /* See if we had a match. */
+ if (i == Kernel->cacheSlots)
+ {
+ /* See if there is room in the cache. */
+ if (i < gcmCOUNTOF(Kernel->cache))
+ {
+ /* Just append to the cache. */
+ i = Kernel->cacheSlots++;
+ }
+
+ else
+ {
+ /* Evict the oldest cache line. */
+ i = oldest;
+ }
+
+ /* Initialize the cache line. */
+ Kernel->cache[i].logical = *Data;
+ Kernel->cache[i].process = Process;
+
+ /* Map the logical address to a DMA address. */
+ gcmkONERROR(gckOS_GetPhysicalAddress(Kernel->os,
+ *Data,
+ &Kernel->cache[i].dma));
+
+ if (baseAddress != 0)
+ {
+ gctBOOL needBase;
+
+ /* Does this state load need a base address? */
+ gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
+ ((gctUINT32_PTR) Data)[-1],
+ &needBase));
+
+ if (needBase)
+ {
+ /* Add the base address. */
+ Kernel->cache[i].dma += baseAddress;
+ }
+ }
+ }
+
+ /* Increment time stamp of the cache slot. */
+ Kernel->cache[i].stamp = Kernel->cacheTimeStamp++;
+
+ /* Return DMA address. */
+ *Data = gcmINT2PTR(Kernel->cache[i].dma);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Data=0x%08x", *Data);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckKERNEL_Recovery
+**
+** Try to recover the GPU from a fatal error.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Recovery(
+ IN gckKERNEL Kernel
+ )
+{
+ gceSTATUS status;
+ gckEVENT event;
+ gckHARDWARE hardware;
+#if gcdSECURE_USER
+ gctUINT32 processID;
+#endif
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Validate the arguemnts. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Grab gckEVENT object. */
+ event = Kernel->event;
+ gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+ /* Grab gckHARDWARE object. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Handle all outstanding events now. */
+ event->pending = ~0U;
+ gcmkONERROR(gckEVENT_Notify(event, 1));
+
+ /* Again in case more events got submitted. */
+ event->pending = ~0U;
+ gcmkONERROR(gckEVENT_Notify(event, 2));
+
+#if gcdSECURE_USER
+ /* Flush the secure mapping cache. */
+ gcmkONERROR(gckOS_GetProcessID(&processID));
+ gcmkONERROR(gckKERNEL_MapLogicalToPhysical(Kernel, processID, gcvNULL));
+#endif
+
+ /* Try issuing a soft reset for the GPU. */
+ status = gckHARDWARE_Reset(hardware);
+ if (status == gcvSTATUS_NOT_SUPPORTED)
+ {
+ /* Switch to OFF power. The next submit should return the GPU to ON
+ ** state. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(hardware,
+ gcvPOWER_OFF_RECOVERY));
+ }
+ else
+ {
+ /* Bail out on reset error. */
+ gcmkONERROR(status);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_h_
+#define __gc_hal_kernel_h_
+
+#include "gc_hal.h"
+#include "gc_hal_kernel_hardware.h"
+#include "gc_hal_driver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+#if gcdSECURE_USER
+typedef struct _gckLOGICAL_CACHE
+{
+ gctHANDLE process;
+ gctPOINTER logical;
+ gctUINT32 dma;
+ gctUINT64 stamp;
+}
+gckLOGICAL_CACHE;
+#endif
+
+/* gckKERNEL object. */
+struct _gckKERNEL
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* Pointer to gckCOMMAND object. */
+ gckCOMMAND command;
+
+ /* Pointer to gckEVENT object. */
+ gckEVENT event;
+
+ /* Pointer to context. */
+ gctPOINTER context;
+
+ /* Pointer to gckMMU object. */
+ gckMMU mmu;
+
+ /* Arom holding number of clients. */
+ gctPOINTER atomClients;
+
+#if VIVANTE_PROFILER
+ /* Enable profiling */
+ gctBOOL profileEnable;
+
+ /* The profile file name */
+ gctCHAR profileFileName[gcdMAX_PROFILE_FILE_NAME];
+#endif
+
+#if gcdSECURE_USER
+ gckLOGICAL_CACHE cache[gcdSECURE_CACHE_SLOTS];
+ gctUINT cacheSlots;
+ gctUINT64 cacheTimeStamp;
+#endif
+};
+
+#define gcdCOMMAND_QUEUES 2
+
+/* gckCOMMAND object. */
+struct _gckCOMMAND
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to required object. */
+ gckKERNEL kernel;
+ gckOS os;
+
+ /* Number of bytes per page. */
+ gctSIZE_T pageSize;
+
+ /* Current pipe select. */
+ gctUINT32 pipeSelect;
+
+ /* Command queue running flag. */
+ gctBOOL running;
+
+ /* Idle flag and commit stamp. */
+ gctBOOL idle;
+ gctUINT64 commitStamp;
+
+ /* Command queue mutex. */
+ gctPOINTER mutexQueue;
+
+ /* Context switching mutex. */
+ gctPOINTER mutexContext;
+
+ /* Command queue power semaphore. */
+ gctPOINTER powerSemaphore;
+
+ /* Current command queue. */
+ struct _gcskCOMMAND_QUEUE
+ {
+ gctSIGNAL signal;
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ }
+ queues[gcdCOMMAND_QUEUES];
+
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+ gctINT index;
+ gctUINT32 offset;
+
+ /* The command queue is new. */
+ gctBOOL newQueue;
+ gctBOOL submit;
+
+ /* Context counter used for unique ID. */
+ gctUINT64 contextCounter;
+
+ /* Current context ID. */
+ gctUINT64 currentContext;
+
+ /* Pointer to last WAIT command. */
+ gctPOINTER wait;
+ gctSIZE_T waitSize;
+
+ /* Command buffer alignment. */
+ gctSIZE_T alignment;
+ gctSIZE_T reservedHead;
+ gctSIZE_T reservedTail;
+
+ /* Commit counter. */
+ gctPOINTER atomCommit;
+};
+
+typedef struct _gcsEVENT * gcsEVENT_PTR;
+
+/* Structure holding one event to be processed. */
+typedef struct _gcsEVENT
+{
+ /* Pointer to next event in queue. */
+ gcsEVENT_PTR next;
+
+ /* Event information. */
+ gcsHAL_INTERFACE event;
+
+#ifdef __QNXNTO__
+ /* Kernel. */
+ gckKERNEL kernel;
+#endif
+}
+gcsEVENT;
+
+/* Structure holding a list of events to be processed by an interrupt. */
+typedef struct _gcsEVENT_QUEUE
+{
+ /* Time stamp. */
+ gctUINT64 stamp;
+
+ /* Source of the event. */
+ gceKERNEL_WHERE source;
+
+ /* Pointer to head of event queue. */
+ gcsEVENT_PTR head;
+
+ /* Pointer to tail of event queue. */
+ gcsEVENT_PTR tail;
+
+ /* Process ID owning the event queue. */
+ gctUINT32 processID;
+}
+gcsEVENT_QUEUE;
+
+/* gckEVENT object. */
+struct _gckEVENT
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to required objects. */
+ gckOS os;
+ gckKERNEL kernel;
+
+ /* Time stamp. */
+ gctUINT64 stamp;
+ gctUINT64 lastCommitStamp;
+
+ /* Queue mutex. */
+ gctPOINTER mutexQueue;
+
+ /* Array of event queues. */
+ gcsEVENT_QUEUE queues[31];
+ gctUINT8 lastID;
+
+ /* Pending events. */
+ volatile gctUINT pending;
+
+ /* List of free event structures and its mutex. */
+ gcsEVENT_PTR freeList;
+ gctSIZE_T freeCount;
+ gctPOINTER freeMutex;
+
+ /* Events queued to be added to an event queue and its mutex. */
+ gcsEVENT_QUEUE list;
+ gctPOINTER listMutex;
+};
+
+/* gcuVIDMEM_NODE structure. */
+typedef union _gcuVIDMEM_NODE
+{
+ /* Allocated from gckVIDMEM. */
+ struct _gcsVIDMEM_NODE_VIDMEM
+ {
+ /* Owner of this node. */
+ gckVIDMEM memory;
+
+ /* Dual-linked list of nodes. */
+ gcuVIDMEM_NODE_PTR next;
+ gcuVIDMEM_NODE_PTR prev;
+
+ /* Dual linked list of free nodes. */
+ gcuVIDMEM_NODE_PTR nextFree;
+ gcuVIDMEM_NODE_PTR prevFree;
+
+ /* Information for this node. */
+ gctUINT32 offset;
+ gctSIZE_T bytes;
+ gctUINT32 alignment;
+
+#ifdef __QNXNTO__
+ /* Client/server vaddr (mapped using mmap_join). */
+ gctPOINTER logical;
+
+ /* Unique handle of the caller process channel. */
+ gctHANDLE handle;
+#endif
+
+ /* Locked counter. */
+ gctINT32 locked;
+
+ /* Memory pool. */
+ gcePOOL pool;
+ gctUINT32 physical;
+ }
+ VidMem;
+
+ /* Allocated from gckOS. */
+ struct _gcsVIDMEM_NODE_VIRTUAL
+ {
+ /* Pointer to gckKERNEL object. */
+ gckKERNEL kernel;
+
+ /* Information for this node. */
+ gctBOOL contiguous;
+ gctPHYS_ADDR physical;
+ gctSIZE_T bytes;
+ gctPOINTER logical;
+
+ /* Page table information. */
+ gctSIZE_T pageCount;
+ gctPOINTER pageTable;
+ gctUINT32 address;
+
+ /* Mutex. */
+ gctPOINTER mutex;
+
+ /* Locked counter. */
+ gctINT32 locked;
+
+#ifdef __QNXNTO__
+ /* Single linked list of nodes. */
+ gcuVIDMEM_NODE_PTR next;
+
+ /* PID of the caller process channel. */
+ gctUINT32 userPID;
+
+ /* Unique handle of the caller process channel. */
+ gctHANDLE handle;
+
+ /* Unlock pending flag. */
+ gctBOOL unlockPending;
+
+ /* Free pending flag. */
+ gctBOOL freePending;
+#else
+ /* Pending flag. */
+ gctBOOL pending;
+#endif
+ }
+ Virtual;
+}
+gcuVIDMEM_NODE;
+
+/* gckVIDMEM object. */
+struct _gckVIDMEM
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Information for this video memory heap. */
+ gctUINT32 baseAddress;
+ gctSIZE_T bytes;
+ gctSIZE_T freeBytes;
+
+ /* Mapping for each type of surface. */
+ gctINT mapping[gcvSURF_NUM_TYPES];
+
+ /* Sentinel nodes for up to 8 banks. */
+ gcuVIDMEM_NODE sentinel[8];
+
+ /* Allocation threshold. */
+ gctSIZE_T threshold;
+
+ /* The heap mutex. */
+ gctPOINTER mutex;
+};
+
+/* gckMMU object. */
+struct _gckMMU
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gckOS object. */
+ gckOS os;
+
+ /* Pointer to gckHARDWARE object. */
+ gckHARDWARE hardware;
+
+ /* The page table mutex. */
+ gctPOINTER pageTableMutex;
+
+ /* Page table information. */
+ gctSIZE_T pageTableSize;
+ gctPHYS_ADDR pageTablePhysical;
+ gctUINT32_PTR pageTableLogical;
+ gctUINT32 pageTableEntries;
+
+ /* Free entries. */
+ gctUINT32 heapList;
+ gctBOOL freeNodes;
+
+#ifdef __QNXNTO__
+ /* Single linked list of all allocated nodes. */
+ gctPOINTER nodeMutex;
+ gcuVIDMEM_NODE_PTR nodeList;
+#endif
+};
+
+gceSTATUS
+gckKERNEL_AttachProcess(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Attach
+ );
+
+#if gcdSECURE_USER
+gceSTATUS
+gckKERNEL_MapLogicalToPhysical(
+ IN gckKERNEL Kernel,
+ IN gctHANDLE Process,
+ IN OUT gctPOINTER * Data
+ );
+#endif
+
+gceSTATUS
+gckHARDWARE_QueryIdle(
+ IN gckHARDWARE Hardware,
+ OUT gctBOOL_PTR IsIdle
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_kernel_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_user_context.h"
+
+#if defined(__QNXNTO__)
+#include <sys/slog.h>
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_COMMAND
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+#if gcdDUMP_COMMAND
+static void
+_DumpCommand(
+ IN gckCOMMAND Command,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Bytes
+ )
+{
+ gctUINT32_PTR data = (gctUINT32_PTR) Pointer;
+ gctUINT32 address;
+
+ gckOS_GetPhysicalAddress(Command->os, Pointer, &address);
+
+ gcmkPRINT("@[kernel.command %08X %08X", address, Bytes);
+ while (Bytes >= 8*4)
+ {
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6],
+ data[7]);
+ data += 8;
+ Bytes -= 32;
+ }
+
+ switch (Bytes)
+ {
+ case 7*4:
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4], data[5],
+ data[6]);
+ break;
+
+ case 6*4:
+ gcmkPRINT(" %08X %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4], data[5]);
+ break;
+
+ case 5*4:
+ gcmkPRINT(" %08X %08X %08X %08X %08X",
+ data[0], data[1], data[2], data[3], data[4]);
+ break;
+
+ case 4*4:
+ gcmkPRINT(" %08X %08X %08X %08X", data[0], data[1], data[2], data[3]);
+ break;
+
+ case 3*4:
+ gcmkPRINT(" %08X %08X %08X", data[0], data[1], data[2]);
+ break;
+
+ case 2*4:
+ gcmkPRINT(" %08X %08X", data[0], data[1]);
+ break;
+
+ case 1*4:
+ gcmkPRINT(" %08X", data[0]);
+ break;
+ }
+
+ gcmkPRINT("] -- command");
+}
+#endif
+
+/*******************************************************************************
+**
+** _NewQueue
+**
+** Allocate a new command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** gckCOMMAND Command
+** gckCOMMAND object has been updated with a new command queue.
+*/
+static gceSTATUS
+_NewQueue(
+ IN OUT gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctINT currentIndex, newIndex;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Switch to the next command buffer. */
+ currentIndex = Command->index;
+ newIndex = (currentIndex + 1) % gcdCOMMAND_QUEUES;
+
+ /* Wait for availability. */
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.waitsignal]");
+#endif
+
+ gcmkONERROR(
+ gckOS_WaitSignal(Command->os,
+ Command->queues[newIndex].signal,
+ gcvINFINITE));
+
+ if (currentIndex >= 0)
+ {
+ /* Mark the command queue as available. */
+ gcmkONERROR(gckEVENT_Signal(Command->kernel->event,
+ Command->queues[currentIndex].signal,
+ gcvKERNEL_COMMAND));
+ }
+
+ /* Update gckCOMMAND object with new command queue. */
+ Command->index = newIndex;
+ Command->newQueue = gcvTRUE;
+ Command->physical = Command->queues[newIndex].physical;
+ Command->logical = Command->queues[newIndex].logical;
+ Command->offset = 0;
+
+ if (currentIndex >= 0)
+ {
+ /* Submit the event queue. */
+ Command->submit = gcvTRUE;
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("Command->index=%d", Command->index);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/******************************************************************************\
+****************************** gckCOMMAND API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckCOMMAND_Construct
+**
+** Construct a new gckCOMMAND object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gckCOMMAND * Command
+** Pointer to a variable that will hold the pointer to the gckCOMMAND
+** object.
+*/
+gceSTATUS
+gckCOMMAND_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckCOMMAND * Command
+ )
+{
+ gckOS os;
+ gckCOMMAND command = gcvNULL;
+ gceSTATUS status;
+ gctINT i;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Command != gcvNULL);
+
+ /* Extract the gckOS object. */
+ os = Kernel->os;
+
+ /* Allocate the gckCOMMAND structure. */
+ gcmkONERROR(
+ gckOS_Allocate(os,
+ gcmSIZEOF(struct _gckCOMMAND),
+ (gctPOINTER *) &command));
+
+ /* Initialize the gckCOMMAND object.*/
+ command->object.type = gcvOBJ_COMMAND;
+ command->kernel = Kernel;
+ command->os = os;
+ command->mutexQueue = gcvNULL;
+ command->mutexContext = gcvNULL;
+ command->powerSemaphore = gcvNULL;
+ command->atomCommit = gcvNULL;
+
+ /* No command queues created yet. */
+ command->index = 0;
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ command->queues[i].signal = gcvNULL;
+ command->queues[i].logical = gcvNULL;
+ }
+
+ /* Get the command buffer requirements. */
+ gcmkONERROR(
+ gckHARDWARE_QueryCommandBuffer(Kernel->hardware,
+ &command->alignment,
+ &command->reservedHead,
+ &command->reservedTail));
+
+ /* No contexts available yet. */
+ command->contextCounter = command->currentContext = 0;
+
+ /* Create the command queue mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &command->mutexQueue));
+
+ /* Create the context switching mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &command->mutexContext));
+
+ /* Create the power management semaphore. */
+ gcmkONERROR(
+ gckOS_CreateSemaphore(os, &command->powerSemaphore));
+
+ /* Create the commit atom. */
+ gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
+
+ /* Get the page size from teh OS. */
+ gcmkONERROR(
+ gckOS_GetPageSize(os, &command->pageSize));
+
+ /* Set hardware to pipe 0. */
+ command->pipeSelect = 0;
+
+ /* Pre-allocate the command queues. */
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ gcmkONERROR(
+ gckOS_AllocateNonPagedMemory(os,
+ gcvFALSE,
+ &command->pageSize,
+ &command->queues[i].physical,
+ &command->queues[i].logical));
+ gcmkONERROR(
+ gckOS_CreateSignal(os, gcvFALSE, &command->queues[i].signal));
+
+ gcmkONERROR(
+ gckOS_Signal(os, command->queues[i].signal, gcvTRUE));
+ }
+
+ /* No command queue in use yet. */
+ command->index = -1;
+ command->logical = gcvNULL;
+ command->newQueue = gcvFALSE;
+ command->submit = gcvFALSE;
+
+ /* Command is not yet running. */
+ command->running = gcvFALSE;
+
+ /* Command queue is idle. */
+ command->idle = gcvTRUE;
+
+ /* Commit stamp is zero. */
+ command->commitStamp = 0;
+
+ /* Return pointer to the gckCOMMAND object. */
+ *Command = command;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Command=0x%x", *Command);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (command != gcvNULL)
+ {
+ if (command->atomCommit != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_AtomDestroy(os, command->atomCommit));
+ }
+
+ if (command->powerSemaphore != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(os, command->powerSemaphore));
+ }
+
+ if (command->mutexContext != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexContext));
+ }
+
+ if (command->mutexQueue != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, command->mutexQueue));
+ }
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ if (command->queues[i].signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DestroySignal(os, command->queues[i].signal));
+ }
+
+ if (command->queues[i].logical != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeNonPagedMemory(os,
+ command->pageSize,
+ command->queues[i].physical,
+ command->queues[i].logical));
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(os, command));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Destroy
+**
+** Destroy an gckCOMMAND object.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Destroy(
+ IN gckCOMMAND Command
+ )
+{
+ gctINT i;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Stop the command queue. */
+ gcmkVERIFY_OK(gckCOMMAND_Stop(Command));
+
+ for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
+ {
+ gcmkASSERT(Command->queues[i].signal != gcvNULL);
+ gcmkVERIFY_OK(
+ gckOS_DestroySignal(Command->os, Command->queues[i].signal));
+
+ gcmkASSERT(Command->queues[i].logical != gcvNULL);
+ gcmkVERIFY_OK(
+ gckOS_FreeNonPagedMemory(Command->os,
+ Command->pageSize,
+ Command->queues[i].physical,
+ Command->queues[i].logical));
+ }
+
+ /* Delete the context switching mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext));
+
+ /* Delete the command queue mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue));
+
+ /* Destroy the power management semaphore. */
+ gcmkVERIFY_OK(gckOS_DestroySemaphore(Command->os, Command->powerSemaphore));
+
+ /* Destroy the commit atom. */
+ gcmkVERIFY_OK(gckOS_AtomDestroy(Command->os, Command->atomCommit));
+
+ /* Mark object as unknown. */
+ Command->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckCOMMAND object. */
+ gcmkVERIFY_OK(gckOS_Free(Command->os, Command));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Start
+**
+** Start up the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to start.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Start(
+ IN gckCOMMAND Command
+ )
+{
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gctSIZE_T bytes;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (Command->running)
+ {
+ /* Command queue already running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ if (Command->logical == gcvNULL)
+ {
+ /* Start at beginning of a new queue. */
+ gcmkONERROR(_NewQueue(Command));
+ }
+
+ /* Start at beginning of page. */
+ Command->offset = 0;
+
+ /* Append WAIT/LINK. */
+ bytes = Command->pageSize;
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(hardware,
+ Command->logical,
+ 0,
+ &bytes,
+ &Command->wait,
+ &Command->waitSize));
+
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ Command->logical,
+ bytes));
+
+ /* Adjust offset. */
+ Command->offset = bytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Enable command processor. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckHARDWARE_Execute(hardware,
+ Command->logical,
+ Command->physical,
+ gcvTRUE,
+ bytes));
+#else
+ gcmkONERROR(
+ gckHARDWARE_Execute(hardware,
+ Command->logical,
+ bytes));
+#endif
+ /* Command queue is running. */
+ Command->running = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stop
+**
+** Stop the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object to stop.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stop(
+ IN gckCOMMAND Command
+ )
+{
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gctUINT32 idle;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ if (!Command->running)
+ {
+ /* Command queue is not running. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /* Extract the gckHARDWARE object. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Replace last WAIT with END. */
+ gcmkONERROR(
+ gckHARDWARE_End(hardware,
+ Command->wait,
+ &Command->waitSize));
+
+ /* Wait for idle. */
+ gcmkONERROR(
+ gckHARDWARE_GetIdle(hardware, gcvTRUE, &idle));
+
+ /* Command queue is no longer running. */
+ Command->running = gcvFALSE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+typedef struct _gcsMAPPED * gcsMAPPED_PTR;
+struct _gcsMAPPED
+{
+ gcsMAPPED_PTR next;
+ gctPOINTER pointer;
+ gctPOINTER kernelPointer;
+ gctSIZE_T bytes;
+};
+
+static gceSTATUS
+_AddMap(
+ IN gckOS Os,
+ IN gctPOINTER Source,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Destination,
+ IN OUT gcsMAPPED_PTR * Stack
+ )
+{
+ gcsMAPPED_PTR map = gcvNULL;
+ gceSTATUS status;
+
+ /* Don't try to map NULL pointers. */
+ if (Source == gcvNULL)
+ {
+ *Destination = gcvNULL;
+ return gcvSTATUS_OK;
+ }
+
+ /* Allocate the gcsMAPPED structure. */
+ gcmkONERROR(
+ gckOS_Allocate(Os, gcmSIZEOF(*map), (gctPOINTER *) &map));
+
+ /* Map the user pointer into kernel addressing space. */
+ gcmkONERROR(
+ gckOS_MapUserPointer(Os, Source, Bytes, Destination));
+
+ /* Save mapping. */
+ map->pointer = Source;
+ map->kernelPointer = *Destination;
+ map->bytes = Bytes;
+
+ /* Push structure on top of the stack. */
+ map->next = *Stack;
+ *Stack = map;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ if (gcmIS_ERROR(status) && (map != gcvNULL))
+ {
+ /* Roll back on error. */
+ gcmkVERIFY_OK(gckOS_Free(Os, map));
+ }
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Commit
+**
+** Commit a command buffer to the command queue.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gcoCMDBUF CommandBuffer
+** Pointer to an gcoCMDBUF object.
+**
+** gcoCONTEXT Context
+** Pointer to an gcoCONTEXT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Commit(
+ IN gckCOMMAND Command,
+ IN gcoCMDBUF CommandBuffer,
+ IN gcoCONTEXT Context,
+ IN gctHANDLE Process
+ )
+{
+ gcoCMDBUF commandBuffer;
+ gcoCONTEXT context;
+ gckHARDWARE hardware = gcvNULL;
+ gceSTATUS status;
+ gctPOINTER initialLink, link;
+ gctSIZE_T bytes, initialSize, lastRun;
+ gcoCMDBUF buffer;
+ gctPOINTER wait;
+ gctSIZE_T waitSize;
+ gctUINT32 offset;
+ gctPOINTER fetchAddress;
+ gctSIZE_T fetchSize;
+ gctUINT8_PTR logical;
+ gcsMAPPED_PTR stack = gcvNULL;
+ gctINT acquired = 0;
+#if gcdSECURE_USER
+ gctUINT32_PTR hint;
+#endif
+#if gcdDUMP_COMMAND
+ gctPOINTER dataPointer;
+ gctSIZE_T dataBytes;
+#endif
+ gctPOINTER flushPointer;
+ gctSIZE_T flushSize;
+ gctBOOL semaAcquired = gcvFALSE;
+ gctINT32 atomValue;
+ gctBOOL atomIncremented = gcvFALSE;
+ gctBOOL powerAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x CommandBuffer=0x%x Context=0x%x",
+ Command, CommandBuffer, Context);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if gcdNULL_DRIVER == 2
+ /* Do nothing with infinite hardware. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#endif
+
+ gcmkONERROR(
+ _AddMap(Command->os,
+ CommandBuffer,
+ gcmSIZEOF(struct _gcoCMDBUF),
+ (gctPOINTER *) &commandBuffer,
+ &stack));
+ gcmkVERIFY_OBJECT(commandBuffer, gcvOBJ_COMMANDBUFFER);
+ gcmkONERROR(
+ _AddMap(Command->os,
+ Context,
+ gcmSIZEOF(struct _gcoCONTEXT),
+ (gctPOINTER *) &context,
+ &stack));
+ gcmkVERIFY_OBJECT(context, gcvOBJ_CONTEXT);
+
+ /* Extract the gckHARDWARE and gckEVENT objects. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Grab the power mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Command->os, hardware->powerMutex, gcvINFINITE));
+ powerAcquired = gcvTRUE;
+
+ /* Increment the commit atom. */
+ gcmkONERROR(gckOS_AtomIncrement(Command->os,
+ Command->atomCommit,
+ &atomValue));
+ atomIncremented = gcvTRUE;
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, hardware->powerMutex));
+ powerAcquired = gcvFALSE;
+
+ /* Notify the system the GPU has a commit. */
+ gcmkONERROR(gckOS_Broadcast(Command->os,
+ hardware,
+ gcvBROADCAST_GPU_COMMIT));
+
+ /* Acquire the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(Command->os, Command->powerSemaphore));
+ semaAcquired = gcvTRUE;
+
+ /* Acquire the context switching mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Command->os,
+ Command->mutexContext,
+ gcvINFINITE));
+
+ ++acquired;
+
+ /* Reserved slot in the context or command buffer. */
+ gcmkONERROR(
+ gckHARDWARE_PipeSelect(hardware, gcvNULL, 0, &bytes));
+
+ /* Test if we need to switch to this context. */
+ if ((context->id != 0)
+ && (context->id != Command->currentContext)
+ )
+ {
+ /* Map the context buffer. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ context->logical,
+ context->bufferSize,
+ (gctPOINTER *) &logical,
+ &stack));
+
+#if gcdSECURE_USER
+ /* Map the hint array. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ context->hintArray,
+ context->hintCount * gcmSIZEOF(gctUINT32),
+ (gctPOINTER *) &hint,
+ &stack));
+
+ /* Loop while we have valid hints. */
+ while (*hint != 0)
+ {
+ /* Map handle into physical address. */
+ gcmkONERROR(
+ gckKERNEL_MapLogicalToPhysical(
+ Command->kernel,
+ Process,
+ (gctPOINTER *) (logical + *hint)));
+
+ /* Next hint. */
+ ++hint;
+ }
+#endif
+
+ /* See if we have to check pipes. */
+ if (context->pipe2DIndex != 0)
+ {
+ /* See if we are in the correct pipe. */
+ if (context->initialPipe == Command->pipeSelect)
+ {
+ gctUINT32 reserved = bytes;
+ gctUINT8_PTR nop = logical;
+
+ /* Already in the correct pipe, fill context buffer with NOP. */
+ while (reserved > 0)
+ {
+ bytes = reserved;
+ gcmkONERROR(
+ gckHARDWARE_Nop(hardware, nop, &bytes));
+
+ gcmkASSERT(reserved >= bytes);
+ reserved -= bytes;
+ nop += bytes;
+ }
+ }
+ else
+ {
+ /* Switch to the correct pipe. */
+ gcmkONERROR(
+ gckHARDWARE_PipeSelect(hardware,
+ logical,
+ context->initialPipe,
+ &bytes));
+ }
+ }
+
+ /* Save initial link pointer. */
+ initialLink = logical;
+ initialSize = context->bufferSize;
+
+ /* Save initial buffer to flush. */
+ flushPointer = initialLink;
+ flushSize = initialSize;
+
+ /* Save pointer to next link. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ context->link,
+ 8,
+ &link,
+ &stack));
+
+ /* Start parsing CommandBuffer. */
+ buffer = commandBuffer;
+
+ /* Mark context buffer as used. */
+ if (context->inUse != gcvNULL)
+ {
+ gctBOOL_PTR inUse;
+
+ gcmkONERROR(
+ _AddMap(Command->os,
+ (gctPOINTER) context->inUse,
+ gcmSIZEOF(gctBOOL),
+ (gctPOINTER *) &inUse,
+ &stack));
+
+ *inUse = gcvTRUE;
+ }
+ }
+
+ else
+ {
+ /* Test if this is a new context. */
+ if (context->id == 0)
+ {
+ /* Generate unique ID for the context buffer. */
+ context->id = ++ Command->contextCounter;
+
+ if (context->id == 0)
+ {
+ /* Context counter overflow (wow!) */
+ gcmkONERROR(gcvSTATUS_TOO_COMPLEX);
+ }
+ }
+
+ /* Map the command buffer. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ commandBuffer->logical,
+ commandBuffer->offset,
+ (gctPOINTER *) &logical,
+ &stack));
+
+#if gcdSECURE_USER
+ /* Map the hint table. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ commandBuffer->hintCommit,
+ commandBuffer->offset - commandBuffer->startOffset,
+ (gctPOINTER *) &hint,
+ &stack));
+
+ /* Walk while we have valid hints. */
+ while (*hint != 0)
+ {
+ /* Map the handle to a physical address. */
+ gcmkONERROR(
+ gckKERNEL_MapLogicalToPhysical(
+ Command->kernel,
+ Process,
+ (gctPOINTER *) (logical + *hint)));
+
+ /* Next hint. */
+ ++hint;
+ }
+#endif
+
+ if (context->entryPipe == Command->pipeSelect)
+ {
+ gctUINT32 reserved = Command->reservedHead;
+ gctUINT8_PTR nop = logical + commandBuffer->startOffset;
+
+ /* Already in the correct pipe, fill context buffer with NOP. */
+ while (reserved > 0)
+ {
+ bytes = reserved;
+ gcmkONERROR(
+ gckHARDWARE_Nop(hardware, nop, &bytes));
+
+ gcmkASSERT(reserved >= bytes);
+ reserved -= bytes;
+ nop += bytes;
+ }
+ }
+ else
+ {
+ /* Switch to the correct pipe. */
+ gcmkONERROR(
+ gckHARDWARE_PipeSelect(hardware,
+ logical + commandBuffer->startOffset,
+ context->entryPipe,
+ &bytes));
+ }
+
+ /* Save initial link pointer. */
+ initialLink = logical + commandBuffer->startOffset;
+ initialSize = commandBuffer->offset
+ - commandBuffer->startOffset
+ + Command->reservedTail;
+
+ /* Save initial buffer to flush. */
+ flushPointer = initialLink;
+ flushSize = initialSize;
+
+ /* Save pointer to next link. */
+ link = logical + commandBuffer->offset;
+
+ /* No more data. */
+ buffer = gcvNULL;
+ }
+
+#if gcdDUMP_COMMAND
+ dataPointer = initialLink;
+ dataBytes = initialSize;
+#endif
+
+ /* Loop through all remaining command buffers. */
+ if (buffer != gcvNULL)
+ {
+ /* Map the command buffer. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ buffer->logical,
+ buffer->offset + Command->reservedTail,
+ (gctPOINTER *) &logical,
+ &stack));
+
+#if gcdSECURE_USER
+ /* Map the hint table. */
+ gcmkONERROR(
+ _AddMap(Command->os,
+ buffer->hintCommit,
+ buffer->offset - buffer->startOffset,
+ (gctPOINTER *) &hint,
+ &stack));
+
+ /* Walk while we have valid hints. */
+ while (*hint != 0)
+ {
+ /* Map the handle to a physical address. */
+ gcmkONERROR(
+ gckKERNEL_MapLogicalToPhysical(
+ Command->kernel,
+ Process,
+ (gctPOINTER *) (logical + *hint)));
+
+ /* Next hint. */
+ ++hint;
+ }
+#endif
+
+ /* First slot becomes a NOP. */
+ {
+ gctUINT32 reserved = Command->reservedHead;
+ gctUINT8_PTR nop = logical + buffer->startOffset;
+
+ /* Already in the correct pipe, fill context buffer with NOP. */
+ while (reserved > 0)
+ {
+ bytes = reserved;
+ gcmkONERROR(
+ gckHARDWARE_Nop(hardware, nop, &bytes));
+
+ gcmkASSERT(reserved >= bytes);
+ reserved -= bytes;
+ nop += bytes;
+ }
+ }
+
+ /* Generate the LINK to this command buffer. */
+ gcmkONERROR(
+ gckHARDWARE_Link(hardware,
+ link,
+ logical + buffer->startOffset,
+ buffer->offset
+ - buffer->startOffset
+ + Command->reservedTail,
+ &bytes));
+
+ /* Flush the initial buffer. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ Process,
+ flushPointer,
+ flushSize));
+
+ /* Save new flush pointer. */
+ flushPointer = logical + buffer->startOffset;
+ flushSize = buffer->offset
+ - buffer->startOffset
+ + Command->reservedTail;
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, dataPointer, dataBytes);
+ dataPointer = logical + buffer->startOffset;
+ dataBytes = buffer->offset - buffer->startOffset
+ + Command->reservedTail;
+#endif
+
+ /* Save pointer to next link. */
+ link = logical + buffer->offset;
+ }
+
+ /* Compute number of bytes required for WAIT/LINK. */
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(hardware,
+ gcvNULL,
+ Command->offset,
+ &bytes,
+ gcvNULL,
+ gcvNULL));
+
+ lastRun = bytes;
+
+ /* Grab the command queue mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Command->os,
+ Command->mutexQueue,
+ gcvINFINITE));
+
+ ++acquired;
+
+ /* Compute number of bytes left in current command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ if (bytes < lastRun)
+ {
+ /* Create a new command queue. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Adjust run size with any extra commands inserted. */
+ lastRun += Command->offset;
+ }
+
+ /* Get current offset. */
+ offset = Command->offset;
+
+ /* Append WAIT/LINK in command queue. */
+ bytes = Command->pageSize - offset;
+
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(hardware,
+ (gctUINT8 *) Command->logical + offset,
+ offset,
+ &bytes,
+ &wait,
+ &waitSize));
+
+ /* Flush the cache for the wait/link. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ (gctUINT8 *) Command->logical + offset,
+ bytes));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, (gctUINT8 *) Command->logical + offset, bytes);
+#endif
+
+ /* Adjust offset. */
+ offset += bytes;
+
+ if (Command->newQueue)
+ {
+ /* Compute fetch location and size for a new command queue. */
+ fetchAddress = Command->logical;
+ fetchSize = offset;
+ }
+ else
+ {
+ /* Compute fetch location and size for an existing command queue. */
+ fetchAddress = (gctUINT8 *) Command->logical + Command->offset;
+ fetchSize = offset - Command->offset;
+ }
+
+ bytes = 8;
+
+ /* Link in WAIT/LINK. */
+ gcmkONERROR(
+ gckHARDWARE_Link(hardware,
+ link,
+ fetchAddress,
+ fetchSize,
+ &bytes));
+
+ /* Flush the cache for the command buffer. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ Process,
+ flushPointer,
+ flushSize));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, dataPointer, dataBytes);
+#endif
+
+ /* Execute the entire sequence. */
+ gcmkONERROR(
+ gckHARDWARE_Link(hardware,
+ Command->wait,
+ initialLink,
+ initialSize,
+ &Command->waitSize));
+
+ /* Flush the cache for the link. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ Command->wait,
+ Command->waitSize));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, Command->wait, Command->waitSize);
+#endif
+
+ /* Update command queue offset. */
+ Command->offset = offset;
+ Command->newQueue = gcvFALSE;
+
+ /* Update address of last WAIT. */
+ Command->wait = wait;
+ Command->waitSize = waitSize;
+
+ /* Update context and pipe select. */
+ Command->currentContext = context->id;
+ Command->pipeSelect = context->currentPipe;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(
+ gckHARDWARE_UpdateQueueTail(hardware,
+ Command->logical,
+ Command->offset));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.commit]");
+#endif
+
+ /* Release the command queue mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+ --acquired;
+
+ /* Release the context switching mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ --acquired;
+
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+ semaAcquired = gcvFALSE;
+
+ /* Submit events if asked for. */
+ if (Command->submit)
+ {
+ /* Submit events. */
+ status = gckEVENT_Submit(Command->kernel->event, gcvFALSE);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Success. */
+ Command->submit = gcvFALSE;
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND,
+ "gckEVENT_Submit returned %d",
+ status);
+ }
+ }
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+
+OnError:
+ if (acquired > 1)
+ {
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+ }
+
+ if (acquired > 0)
+ {
+ /* Release the context switching mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Command->os, Command->mutexContext));
+ }
+
+ if (semaAcquired)
+ {
+ /* Release the power management semaphore. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+ }
+
+ if (atomIncremented)
+ {
+ /* Decrement the commit atom. */
+ gcmkVERIFY_OK(gckOS_AtomDecrement(Command->os,
+ Command->atomCommit,
+ &atomValue));
+ }
+
+ /* Unmap all mapped pointers. */
+ while (stack != gcvNULL)
+ {
+ gcsMAPPED_PTR map = stack;
+ stack = map->next;
+
+ gcmkVERIFY_OK(
+ gckOS_UnmapUserPointer(Command->os,
+ map->pointer,
+ map->bytes,
+ map->kernelPointer));
+
+ gcmkVERIFY_OK(
+ gckOS_Free(Command->os, map));
+ }
+
+ if (powerAcquired)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, hardware->powerMutex));
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Reserve
+**
+** Reserve space in the command queue. Also acquire the command queue mutex.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** gctPOINTER * Buffer
+** Pointer to a variable that will receive the address of the reserved
+** space.
+**
+** gctSIZE_T * BufferSize
+** Pointer to a variable that will receive the number of bytes
+** available in the command queue.
+*/
+gceSTATUS
+gckCOMMAND_Reserve(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequestedBytes,
+ OUT gctPOINTER * Buffer,
+ OUT gctSIZE_T * BufferSize
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T requiredBytes, bytes;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL semaAcquired = gcvTRUE;
+ gctINT32 atomValue;
+ gctBOOL atomIncremented = gcvFALSE;
+ gctBOOL powerAcquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Grab the power mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Command->os,
+ Command->kernel->hardware->powerMutex,
+ gcvINFINITE));
+ powerAcquired = gcvTRUE;
+
+ /* Increment the commit atom. */
+ gcmkONERROR(
+ gckOS_AtomIncrement(Command->os, Command->atomCommit, &atomValue));
+ atomIncremented = gcvTRUE;
+
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os,
+ Command->kernel->hardware->powerMutex));
+ powerAcquired = gcvFALSE;
+
+ /* Notify the system the GPU has a commit. */
+ gcmkONERROR(gckOS_Broadcast(Command->os,
+ Command->kernel->hardware,
+ gcvBROADCAST_GPU_COMMIT));
+
+ /* Grab the power management semaphore. */
+ gcmkONERROR(gckOS_AcquireSemaphore(Command->os, Command->powerSemaphore));
+ semaAcquired = gcvTRUE;
+
+ /* Grab the conmmand queue mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Command->os,
+ Command->mutexQueue,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Compute number of bytes required for WAIT/LINK. */
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(Command->kernel->hardware,
+ gcvNULL,
+ Command->offset + gcmALIGN(RequestedBytes,
+ Command->alignment),
+ &requiredBytes,
+ gcvNULL,
+ gcvNULL));
+
+ /* Compute total number of bytes required. */
+ requiredBytes += gcmALIGN(RequestedBytes, Command->alignment);
+
+ /* Compute number of bytes available in command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ if (bytes < requiredBytes)
+ {
+ /* Create a new command queue. */
+ gcmkONERROR(_NewQueue(Command));
+
+ /* Recompute number of bytes available in command queue. */
+ bytes = Command->pageSize - Command->offset;
+
+ if (bytes < requiredBytes)
+ {
+ /* Rare case, not enough room in command queue. */
+ gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
+ }
+ }
+
+ /* Return pointer to empty slot command queue. */
+ *Buffer = (gctUINT8 *) Command->logical + Command->offset;
+
+ /* Return number of bytes left in command queue. */
+ *BufferSize = bytes;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Buffer=0x%x *BufferSize=%lu", *Buffer, *BufferSize);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release command queue mutex on error. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+ }
+
+ if (semaAcquired)
+ {
+ /* Release the power management semaphore. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+ }
+
+ if (atomIncremented)
+ {
+ /* Decrement the commit atom. */
+ gcmkVERIFY_OK(
+ gckOS_AtomDecrement(Command->os, Command->atomCommit, &atomValue));
+ }
+
+ if (powerAcquired)
+ {
+ /* Release the power mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os,
+ Command->kernel->hardware->powerMutex));
+ }
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Release
+**
+** Release a previously reserved command queue. The command FIFO mutex will be
+** released.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Release(
+ IN gckCOMMAND Command
+ )
+{
+ gceSTATUS status;
+ gctINT32 atomValue;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Release the command queue mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+
+ /* Decrement the commit atom. */
+ gcmkONERROR(
+ gckOS_AtomDecrement(Command->os, Command->atomCommit, &atomValue));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Execute
+**
+** Execute a previously reserved command queue by appending a WAIT/LINK command
+** sequence after it and modifying the last WAIT into a LINK command. The
+** command FIFO mutex will be released whether this function succeeds or not.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** gctSIZE_T RequestedBytes
+** Number of bytes previously reserved.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Execute(
+ IN gckCOMMAND Command,
+ IN gctSIZE_T RequestedBytes
+ )
+{
+ gctUINT32 offset;
+ gctPOINTER address;
+ gctSIZE_T bytes;
+ gceSTATUS status;
+ gctPOINTER wait;
+ gctSIZE_T waitBytes;
+ gctINT32 atomValue;
+
+ gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+ /* Compute offset for WAIT/LINK. */
+ offset = Command->offset + RequestedBytes;
+
+ /* Compute number of byts left in command queue. */
+ bytes = Command->pageSize - offset;
+
+ /* Append WAIT/LINK in command queue. */
+ gcmkONERROR(
+ gckHARDWARE_WaitLink(Command->kernel->hardware,
+ (gctUINT8 *) Command->logical + offset,
+ offset,
+ &bytes,
+ &wait,
+ &waitBytes));
+
+ if (Command->newQueue)
+ {
+ /* For a new command queue, point to the start of the command
+ ** queue and include both the commands inserted at the head of it
+ ** and the WAIT/LINK. */
+ address = Command->logical;
+ bytes += offset;
+ }
+ else
+ {
+ /* For an existing command queue, point to the current offset and
+ ** include the WAIT/LINK. */
+ address = (gctUINT8 *) Command->logical + Command->offset;
+ bytes += RequestedBytes;
+ }
+
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os, gcvNULL, address, bytes));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, address, bytes);
+#endif
+
+ /* Convert the last WAIT into a LINK. */
+ gcmkONERROR(gckHARDWARE_Link(Command->kernel->hardware,
+ Command->wait,
+ address,
+ bytes,
+ &Command->waitSize));
+
+ /* Flush the cache. */
+ gcmkONERROR(gckOS_CacheFlush(Command->os,
+ gcvNULL,
+ Command->wait,
+ Command->waitSize));
+
+#if gcdDUMP_COMMAND
+ _DumpCommand(Command, Command->wait, 8);
+#endif
+
+ /* Update the pointer to the last WAIT. */
+ Command->wait = wait;
+ Command->waitSize = waitBytes;
+
+ /* Update the command queue. */
+ Command->offset += bytes;
+ Command->newQueue = gcvFALSE;
+
+ /* Update queue tail pointer. */
+ gcmkONERROR(
+ gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
+ Command->logical,
+ Command->offset));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.execute]");
+#endif
+
+ /* Release the command queue mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+ /* Release the power management semaphore. */
+ gcmkONERROR(gckOS_ReleaseSemaphore(Command->os, Command->powerSemaphore));
+
+ /* Submit events if asked for. */
+ if (Command->submit)
+ {
+ /* Submit events. */
+ status = gckEVENT_Submit(Command->kernel->event, gcvFALSE);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Success. */
+ Command->submit = gcvFALSE;
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_COMMAND,
+ "gckEVENT_Submit returned %d",
+ status);
+ }
+ }
+
+ /* Decrement the commit atom. */
+ gcmkONERROR(
+ gckOS_AtomDecrement(Command->os, Command->atomCommit, &atomValue));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Release the command queue mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckCOMMAND_Stall
+**
+** The calling thread will be suspended until the command queue has been
+** completed.
+**
+** INPUT:
+**
+** gckCOMMAND Command
+** Pointer to an gckCOMMAND object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckCOMMAND_Stall(
+ IN gckCOMMAND Command
+ )
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gckEVENT event;
+ gceSTATUS status;
+ gctSIGNAL signal = gcvNULL;
+ gctUINT timer = 0;
+
+ gcmkHEADER_ARG("Command=0x%x", Command);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
+
+#if gcdNULL_DRIVER == 2
+ /* Do nothing with infinite hardware. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#endif
+
+ /* Extract the gckOS object pointer. */
+ os = Command->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Command->kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Extract the gckEVENT object pointer. */
+ event = Command->kernel->event;
+ gcmkVERIFY_OBJECT(event, gcvOBJ_EVENT);
+
+ /* Allocate the signal. */
+ gcmkONERROR(
+ gckOS_CreateSignal(os, gcvTRUE, &signal));
+
+ /* Append the EVENT command to trigger the signal. */
+ gcmkONERROR(gckEVENT_Signal(event,
+ signal,
+ gcvKERNEL_PIXEL));
+
+ /* Submit the event queue. */
+ gcmkONERROR(gckEVENT_Submit(event, gcvTRUE));
+
+#if gcdDUMP_COMMAND
+ gcmkPRINT("@[kernel.stall]");
+#endif
+
+ if (status == gcvSTATUS_CHIP_NOT_READY)
+ {
+ /* Error. */
+ goto OnError;
+ }
+
+ do
+ {
+ /* Wait for the signal. */
+ status = gckOS_WaitSignal(os, signal, 250);
+
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+#if gcdDEBUG
+ gctUINT32 idle;
+
+ /* Read idle register. */
+ gcmkVERIFY_OK(
+ gckHARDWARE_GetIdle(Command->kernel->hardware,
+ gcvFALSE,
+ &idle));
+
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "%s(%d): idle=%08x",
+ __FUNCTION__, __LINE__, idle);
+
+ gcmkVERIFY_OK(
+ gckOS_MemoryBarrier(os, gcvNULL));
+
+#ifdef __QNXNTO__
+ gctUINT32 reg_cmdbuf_fetch;
+ gctUINT32 reg_intr;
+
+ gcmkVERIFY_OK(
+ gckOS_ReadRegister(Command->kernel->hardware->os, 0x0664, ®_cmdbuf_fetch));
+
+ if (idle == 0x7FFFFFFE)
+ {
+ /*
+ * GPU is idle so there should not be pending interrupts.
+ * Just double check.
+ *
+ * Note that reading interrupt register clears it.
+ * That's why we don't read it in all cases.
+ */
+ gcmkVERIFY_OK(
+ gckOS_ReadRegister(Command->kernel->hardware->os, 0x10, ®_intr));
+
+ slogf(
+ _SLOG_SETCODE(1, 0),
+ _SLOG_CRITICAL,
+ "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X, interrupt = 0x%X)",
+ idle, reg_cmdbuf_fetch, reg_intr);
+ }
+ else
+ {
+ slogf(
+ _SLOG_SETCODE(1, 0),
+ _SLOG_CRITICAL,
+ "GALcore: Stall timeout (idle = 0x%X, command buffer fetch = 0x%X)",
+ idle, reg_cmdbuf_fetch);
+ }
+#endif
+#endif
+ /* Advance timer. */
+ timer += 250;
+ }
+ }
+ while (gcmIS_ERROR(status)
+#if gcdGPU_TIMEOUT
+ && (timer < gcdGPU_TIMEOUT)
+#endif
+ );
+
+ /* Bail out on timeout. */
+ if (gcmIS_ERROR(status))
+ {
+ /* Broadcast the stuck GPU. */
+ gcmkONERROR(gckOS_Broadcast(os,
+ Command->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK));
+
+ gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+ }
+
+ /* Delete the signal. */
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Free the signal. */
+ if (signal != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+#include "gc_hal_user_context.h"
+
+#define _GC_OBJ_ZONE gcvZONE_EVENT
+
+#define gcdEVENT_ALLOCATION_COUNT (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
+#define gcdEVENT_MIN_THRESHOLD 4
+
+/******************************************************************************\
+********************************* Support Code *********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _GetEvent
+**
+** Get an empty event ID.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** gctUINT8 * EventID
+** Pointer to a variable that receives an empty event ID.
+*/
+static gceSTATUS
+_GetEvent(
+ IN gckEVENT Event,
+ OUT gctUINT8 * EventID,
+ IN gceKERNEL_WHERE Source
+ )
+{
+ gctINT i, id;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
+
+ /* Grab the queue mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->mutexQueue,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Walk through all events. */
+ id = Event->lastID;
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[id].head == gcvNULL)
+ {
+ *EventID = (gctUINT8) id;
+
+ Event->lastID = (id + 1) % gcmCOUNTOF(Event->queues);
+
+ /* Save time stamp of event. */
+ Event->queues[id].stamp = ++(Event->stamp);
+ Event->queues[id].source = Source;
+
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*EventID=%u", *EventID);
+ return gcvSTATUS_OK;
+ }
+
+ id = (id + 1) % gcmCOUNTOF(Event->queues);
+ }
+
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ acquired = gcvFALSE;
+
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+
+OnError:
+ if (acquired)
+ {
+ /* Release the queue mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+_IsEmpty(
+ IN gckEVENT Event,
+ OUT gctBOOL_PTR IsEmpty
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T i;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
+
+ /* Assume the event queue is empty. */
+ *IsEmpty = gcvTRUE;
+
+ /* Walk the event queue. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ /* Check whether this event is in use. */
+ if (Event->queues[i].head != gcvNULL)
+ {
+ /* The event is in use, hence the queue is not empty. */
+ *IsEmpty = gcvFALSE;
+ break;
+ }
+ }
+
+ /* Try acquiring the mutex. */
+ status = gckOS_AcquireMutex(Event->os, Event->mutexQueue, 0);
+ if (status == gcvSTATUS_TIMEOUT)
+ {
+ /* Timeout - queue is no longer empty. */
+ *IsEmpty = gcvFALSE;
+ }
+ else
+ {
+ /* Bail out on error. */
+ gcmkONERROR(status);
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/******************************************************************************\
+******************************* gckEVENT API Code *******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckEVENT_Construct
+**
+** Construct a new gckEVENT object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gckEVENT * Event
+** Pointer to a variable that receives the gckEVENT object pointer.
+*/
+gceSTATUS
+gckEVENT_Construct(
+ IN gckKERNEL Kernel,
+ OUT gckEVENT * Event
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gckEVENT event = gcvNULL;
+ int i;
+ gcsEVENT_PTR record;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Event != gcvNULL);
+
+ /* Extract the pointer to the gckOS object. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate the gckEVENT object. */
+ gcmkONERROR(
+ gckOS_Allocate(os,
+ gcmSIZEOF(struct _gckEVENT),
+ (gctPOINTER *) &event));
+
+ /* Initialize the gckEVENT object. */
+ event->object.type = gcvOBJ_EVENT;
+ event->kernel = Kernel;
+ event->os = os;
+ event->mutexQueue = gcvNULL;
+ event->freeList = gcvNULL;
+ event->freeCount = 0;
+ event->freeMutex = gcvNULL;
+ event->list.head = gcvNULL;
+ event->list.tail = gcvNULL;
+ event->listMutex = gcvNULL;
+ event->lastID = 0;
+
+ /* Create the mutexes. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &event->mutexQueue));
+
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &event->freeMutex));
+
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &event->listMutex));
+
+ /* Create a bunch of event reccords. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; ++i)
+ {
+ /* Allocate an event record. */
+ gcmkONERROR(
+ gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), (gctPOINTER *) &record));
+
+ /* Push it on the free list. */
+ record->next = event->freeList;
+ event->freeList = record;
+ event->freeCount += 1;
+ }
+
+ /* Zero out the entire event queue. */
+ for (i = 0; i < gcmCOUNTOF(event->queues); ++i)
+ {
+ event->queues[i].head = gcvNULL;
+ }
+
+ /* Zero out the time stamp. */
+ event->stamp = 0;
+
+ /* No events to handle. */
+ event->pending = 0;
+
+ /* Return pointer to the gckEVENT object. */
+ *Event = event;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Event=0x%x", *Event);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (event != gcvNULL)
+ {
+ if (event->mutexQueue != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->mutexQueue));
+ }
+
+ if (event->freeMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->freeMutex));
+ }
+
+ if (event->listMutex != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, event->listMutex));
+ }
+
+ while (event->freeList != gcvNULL)
+ {
+ record = event->freeList;
+ event->freeList = record->next;
+
+ gcmkVERIFY_OK(gckOS_Free(os, record));
+ }
+
+ gcmkVERIFY_OK(gckOS_Free(os, event));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Destroy
+**
+** Destroy an gckEVENT object.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckEVENT_Destroy(
+ IN gckEVENT Event
+ )
+{
+ gcsEVENT_PTR record;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Delete the queue mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->mutexQueue));
+
+ /* Free all free events. */
+ while (Event->freeList != gcvNULL)
+ {
+ record = Event->freeList;
+ Event->freeList = record->next;
+
+ gcmkVERIFY_OK(gckOS_Free(Event->os, record));
+ }
+
+ /* Delete the free mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeMutex));
+
+ /* Free all pending events. */
+ while (Event->list.head != gcvNULL)
+ {
+ record = Event->list.head;
+ Event->list.head = record->next;
+
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_EVENT,
+ "Event record 0x%x is still pending for %d.",
+ record, Event->list.source);
+ gcmkVERIFY_OK(gckOS_Free(Event->os, record));
+ }
+
+ /* Delete the list mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->listMutex));
+
+ /* Mark the gckEVENT object as unknown. */
+ Event->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckEVENT object. */
+ gcmkVERIFY_OK(gckOS_Free(Event->os, Event));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckEVENT_AllocateRecord(
+ IN gckEVENT Event,
+ IN gctBOOL AllocateAllowed,
+ OUT gcsEVENT_PTR * Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctINT i;
+ gcsEVENT_PTR record;
+
+ gcmkHEADER_ARG("Event=0x%x AllocateAllowed=%d", Event, AllocateAllowed);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Test if we are below the allocation threshold. */
+ if (AllocateAllowed
+ && (Event->freeCount < gcdEVENT_MIN_THRESHOLD)
+ )
+ {
+ /* Allocate a bunch of records. */
+ for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; ++i)
+ {
+ /* Allocate an event record. */
+ status = gckOS_Allocate(Event->os,
+ gcmSIZEOF(gcsEVENT),
+ (gctPOINTER *) &record);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_EVENT,
+ "Out of memory allocating event records.");
+ break;
+ }
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->freeMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Push it on the free list. */
+ record->next = Event->freeList;
+ Event->freeList = record;
+ Event->freeCount += 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+ }
+ }
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ *Record = Event->freeList;
+ Event->freeList = Event->freeList->next;
+ Event->freeCount -= 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gceSTATUS
+gckEVENT_FreeRecord(
+ IN gckEVENT Event,
+ IN gcsEVENT_PTR Record
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Record != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Push the record on the free list. */
+ Record->next = Event->freeList;
+ Event->freeList = Record;
+ Event->freeCount += 1;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+gckEVENT_AddList(
+ IN gckEVENT Event,
+ IN gcsHAL_INTERFACE_PTR Interface,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gctBOOL AllocateAllowed
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcsEVENT_PTR record = gcvNULL;
+
+ gcmkHEADER_ARG("Event=0x%x Interface=0x%x FromWhere=%d AllocateAllowed=%d",
+ Event, Interface, FromWhere, AllocateAllowed);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
+
+ switch (FromWhere)
+ {
+ case gcvKERNEL_COMMAND:
+ case gcvKERNEL_PIXEL:
+ /* Check if the requested source matches the list. */
+ if ((Event->list.head != gcvNULL)
+ && (Event->list.source != FromWhere)
+ )
+ {
+ /* No match - auto-submit the list. */
+ status = gckEVENT_Submit(Event, gcvFALSE);
+
+ if (status == gcvSTATUS_OUT_OF_RESOURCES)
+ {
+ /* When we are out of resources, just convert to submit from
+ ** PIXEL. */
+ Event->list.source = FromWhere = gcvKERNEL_PIXEL;
+ }
+
+ else
+ {
+ /* Check for error. */
+ gcmkONERROR(status);
+ }
+ }
+ break;
+
+ default:
+ /* Invalid argument. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Allocate a free record. */
+ gcmkONERROR(gckEVENT_AllocateRecord(Event, AllocateAllowed, &record));
+
+ /* Copy the event interface into the record. */
+ gcmkONERROR(gckOS_MemCopy(&record->event,
+ Interface,
+ gcmSIZEOF(record->event)));
+
+ gcmkASSERT
+ ( (Interface->command == gcvHAL_FREE_NON_PAGED_MEMORY)
+ || (Interface->command == gcvHAL_FREE_CONTIGUOUS_MEMORY)
+ || (Interface->command == gcvHAL_FREE_VIDEO_MEMORY)
+ || (Interface->command == gcvHAL_WRITE_DATA)
+ || (Interface->command == gcvHAL_UNLOCK_VIDEO_MEMORY)
+ || (Interface->command == gcvHAL_SIGNAL)
+ || (Interface->command == gcvHAL_UNMAP_USER_MEMORY)
+ );
+
+ record->next = gcvNULL;
+
+ /* Acquire the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->listMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (Event->list.head == gcvNULL)
+ {
+ /* List doesn't exist yet. */
+ Event->list.head = record;
+ Event->list.tail = record;
+ }
+ else
+ {
+ /* Append to the current list. */
+ Event->list.tail->next = record;
+ Event->list.tail = record;
+ }
+
+ /* Mark the source of this event. */
+ Event->list.source = FromWhere;
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+ }
+
+ if (record != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeNonPagedMemory
+**
+** Schedule an event to free non-paged memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of non-paged memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of non-paged memory to free.
+**
+** gctPOINTER Logical
+** Logical address of non-paged memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeNonPagedMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
+ iface.u.FreeNonPagedMemory.bytes = Bytes;
+ iface.u.FreeNonPagedMemory.physical = Physical;
+ iface.u.FreeNonPagedMemory.logical = Logical;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeContigiuousMemory
+**
+** Schedule an event to free contiguous memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIZE_T Bytes
+** Number of bytes of contiguous memory to free.
+**
+** gctPHYS_ADDR Physical
+** Physical address of contiguous memory to free.
+**
+** gctPOINTER Logical
+** Logical address of contiguous memory to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeContiguousMemory(
+ IN gckEVENT Event,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
+ "FromWhere=%d",
+ Event, Bytes, Physical, Logical, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY;
+ iface.u.FreeContiguousMemory.bytes = Bytes;
+ iface.u.FreeContiguousMemory.physical = Physical;
+ iface.u.FreeContiguousMemory.logical = Logical;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_FreeVideoMemory
+**
+** Schedule an event to free video memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gcuVIDMEM_NODE_PTR VideoMemory
+** Pointer to a gcuVIDMEM_NODE object to free.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+*/
+gceSTATUS
+gckEVENT_FreeVideoMemory(
+ IN gckEVENT Event,
+ IN gcuVIDMEM_NODE_PTR VideoMemory,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x VideoMemory=0x%x FromWhere=%d",
+ Event, VideoMemory, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(VideoMemory != gcvNULL);
+
+ /* Create an event. */
+ iface.command = gcvHAL_FREE_VIDEO_MEMORY;
+ iface.u.FreeVideoMemory.node = VideoMemory;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Signal
+**
+** Schedule an event to trigger a signal.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gctSIGNAL Signal
+** Pointer to the signal to trigger.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+*/
+gceSTATUS
+gckEVENT_Signal(
+ IN gckEVENT Event,
+ IN gctSIGNAL Signal,
+ IN gceKERNEL_WHERE FromWhere
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x Signal=0x%x FromWhere=%d",
+ Event, Signal, FromWhere);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ /* Mark the event as a signal. */
+ iface.command = gcvHAL_SIGNAL;
+ iface.u.Signal.signal = Signal;
+#ifdef __QNXNTO__
+ iface.u.Signal.coid = 0;
+ iface.u.Signal.rcvid = 0;
+#else
+ iface.u.Signal.auxSignal = gcvNULL;
+ iface.u.Signal.process = gcvNULL;
+#endif
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckEVENT_Unlock
+**
+** Schedule an event to unlock virtual memory.
+**
+** INPUT:
+**
+** gckEVENT Event
+** Pointer to an gckEVENT object.
+**
+** gceKERNEL_WHERE FromWhere
+** Place in the pipe where the event needs to be generated.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union that specifies the virtual memory
+** to unlock.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+*/
+gceSTATUS
+gckEVENT_Unlock(
+ IN gckEVENT Event,
+ IN gceKERNEL_WHERE FromWhere,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type
+ )
+{
+ gceSTATUS status;
+ gcsHAL_INTERFACE iface;
+
+ gcmkHEADER_ARG("Event=0x%x FromWhere=%d Node=0x%x Type=%d",
+ Event, FromWhere, Node, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+
+ /* Mark the event as an unlock. */
+ iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
+ iface.u.UnlockVideoMemory.node = Node;
+ iface.u.UnlockVideoMemory.type = Type;
+ iface.u.UnlockVideoMemory.asynchroneous = 0;
+
+ /* Append it to the queue. */
+ gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckEVENT_Commit(
+ IN gckEVENT Event,
+ IN gcsQUEUE_PTR Queue
+ )
+{
+ gceSTATUS status;
+ gcsQUEUE_PTR record = gcvNULL, next;
+
+ gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Loop while there are records in the queue. */
+ while (Queue != gcvNULL)
+ {
+ /* Map record into kernel memory. */
+ gcmkONERROR(gckOS_MapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) &record));
+
+ /* Append event record to event queue. */
+ gcmkONERROR(
+ gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL, gcvTRUE));
+
+ /* Next record in the queue. */
+ next = record->next;
+
+ /* Unmap record from kernel memory. */
+ gcmkONERROR(
+ gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ record = gcvNULL;
+
+ Queue = next;
+ }
+
+ /* Submit the event list. */
+ gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE));
+
+ /* Success */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (record != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
+ Queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckEVENT_Interrupt(
+ IN gckEVENT Event,
+ IN gctUINT32 Data
+ )
+{
+ gcmkHEADER_ARG("Event=0x%x Data=%08x", Event, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ /* Combine current interrupt status with pending flags. */
+ Event->pending |= Data;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckEVENT_Notify(
+ IN gckEVENT Event,
+ IN gctUINT32 IDs
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctINT i;
+ gcsEVENT_QUEUE * queue;
+ gctUINT mask = 0;
+ gctBOOL acquired = gcvFALSE;
+#ifdef __QNXNTO__
+ gcuVIDMEM_NODE_PTR node;
+#endif
+ gctUINT pending;
+ gctBOOL suspended = gcvFALSE;
+ gctBOOL empty = gcvFALSE, idle = gcvFALSE;
+
+ gcmkHEADER_ARG("Event=0x%x", Event);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
+
+ for (;;)
+ {
+ /* Suspend interrupts. */
+ gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+ suspended = gcvTRUE;
+
+ /* Get current interrupts. */
+ pending = Event->pending;
+
+ /* Resume interrupts. */
+ gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+ suspended = gcvFALSE;
+
+ if (pending == 0)
+ {
+ /* No more pending interrupts - done. */
+ break;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Pending interrupts 0x%08x", pending);
+
+ queue = gcvNULL;
+
+#if gcdDEBUG
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if (Event->queues[i].head != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Queue(%d): stamp=%llu source=%d",
+ i,
+ Event->queues[i].stamp,
+ Event->queues[i].source);
+ }
+ }
+#endif
+
+ /* Find the oldest pending interrupt. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if ((Event->queues[i].head != gcvNULL)
+ && (pending & (1 << i))
+ )
+ {
+ if ((queue == gcvNULL)
+ || (Event->queues[i].stamp < queue->stamp)
+ )
+ {
+ queue = &Event->queues[i];
+ mask = 1 << i;
+ }
+ }
+ }
+
+ if (queue == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_EVENT,
+ "Interrupts 0x08x are not pending.", pending);
+
+ /* Suspend interrupts. */
+ gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+ suspended = gcvTRUE;
+
+ /* Mark pending interrupts as handled. */
+ Event->pending &= ~pending;
+
+ /* Resume interrupts. */
+ gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+ suspended = gcvFALSE;
+
+ break;
+ }
+
+ /* Check whether there is a missed interrupt. */
+ for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
+ {
+ if ((Event->queues[i].head != gcvNULL)
+ && (Event->queues[i].stamp < queue->stamp)
+ && (Event->queues[i].source == queue->source)
+ )
+ {
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "Event %d lost (stamp %llu)",
+ i, Event->queues[i].stamp);
+
+ /* Use this event instead. */
+ queue = &Event->queues[i];
+ mask = 0;
+ }
+ }
+
+ /* Walk all events for this interrupt. */
+ while (queue->head != gcvNULL)
+ {
+ gcsEVENT_PTR event;
+#ifndef __QNXNTO__
+ gctPOINTER logical;
+#endif
+
+ event = queue->head;
+
+ /* Dispatch on event type. */
+ switch (event->event.command)
+ {
+ case gcvHAL_FREE_NON_PAGED_MEMORY:
+ /* Free non-paged memory. */
+ status = gckOS_FreeNonPagedMemory(
+ Event->os,
+ event->event.u.FreeNonPagedMemory.bytes,
+ event->event.u.FreeNonPagedMemory.physical,
+ event->event.u.FreeNonPagedMemory.logical);
+ break;
+
+ case gcvHAL_FREE_CONTIGUOUS_MEMORY:
+ /* Unmap the user memory. */
+ status = gckOS_FreeContiguous(
+ Event->os,
+ event->event.u.FreeContiguousMemory.physical,
+ event->event.u.FreeContiguousMemory.logical,
+ event->event.u.FreeContiguousMemory.bytes);
+ break;
+
+ case gcvHAL_FREE_VIDEO_MEMORY:
+#ifdef __QNXNTO__
+ node = event->event.u.FreeVideoMemory.node;
+ if ((node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ && (node->VidMem.logical != gcvNULL)
+ )
+ {
+ gcmkERR_BREAK(
+ gckKERNEL_UnmapVideoMemory(event->kernel,
+ node->VidMem.logical,
+ event->event.pid,
+ node->VidMem.bytes));
+ node->VidMem.logical = gcvNULL;
+ }
+#endif
+
+ /* Free video memory. */
+ status = gckVIDMEM_Free(event->event.u.FreeVideoMemory.node);
+ break;
+
+ case gcvHAL_WRITE_DATA:
+#ifndef __QNXNTO__
+ /* Convert physical into logical address. */
+ gcmkERR_BREAK(
+ gckOS_MapPhysical(Event->os,
+ event->event.u.WriteData.address,
+ gcmSIZEOF(gctUINT32),
+ &logical));
+
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ logical,
+ event->event.u.WriteData.data));
+
+ /* Unmap the physical memory. */
+ gcmkERR_BREAK(
+ gckOS_UnmapPhysical(Event->os,
+ logical,
+ gcmSIZEOF(gctUINT32)));
+#else
+ /* Write data. */
+ gcmkERR_BREAK(
+ gckOS_WriteMemory(Event->os,
+ (gctPOINTER)
+ event->event.u.WriteData.address,
+ event->event.u.WriteData.data));
+#endif
+ break;
+
+ case gcvHAL_UNLOCK_VIDEO_MEMORY:
+ /* Unlock. */
+ status = gckVIDMEM_Unlock(event->event.u.UnlockVideoMemory.node,
+ event->event.u.UnlockVideoMemory.type,
+ gcvNULL);
+ break;
+
+ case gcvHAL_SIGNAL:
+#ifdef __QNXNTO__
+ if ((event->event.u.Signal.coid == 0)
+ && (event->event.u.Signal.rcvid == 0)
+ )
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_Signal(Event->os,
+ event->event.u.Signal.signal,
+ gcvTRUE));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ event->event.u.Signal.signal,
+ event->event.u.Signal.rcvid,
+ event->event.u.Signal.coid));
+ }
+#else
+ /* Set signal. */
+ if (event->event.u.Signal.process == gcvNULL)
+ {
+ /* Kernel signal. */
+ gcmkERR_BREAK(
+ gckOS_Signal(Event->os,
+ event->event.u.Signal.signal,
+ gcvTRUE));
+ }
+ else
+ {
+ /* User signal. */
+ gcmkERR_BREAK(
+ gckOS_UserSignal(Event->os,
+ event->event.u.Signal.signal,
+ event->event.u.Signal.process));
+ }
+
+ gcmkASSERT(event->event.u.Signal.auxSignal == gcvNULL);
+#endif
+ break;
+
+ case gcvHAL_UNMAP_USER_MEMORY:
+ /* Unmap the user memory. */
+ status =
+ gckOS_UnmapUserMemory(Event->os,
+ event->event.u.UnmapUserMemory.memory,
+ event->event.u.UnmapUserMemory.size,
+ event->event.u.UnmapUserMemory.info,
+ event->event.u.UnmapUserMemory.address);
+ break;
+
+ default:
+ /* Invalid argument. */
+ gcmkFATAL("Unknown event type: %d", event->event.command);
+ status = gcvSTATUS_INVALID_ARGUMENT;
+ break;
+ }
+
+ /* Make sure there are no errors generated. */
+ gcmkASSERT(gcmNO_ERROR(status));
+
+ /* Pop the event from the event queue. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Event->os, Event->mutexQueue, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Unlink head from chain. */
+ queue->head = event->next;
+
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ acquired = gcvFALSE;
+
+ /* Free the event. */
+ gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, event));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
+ "Handled interrupt 0x%08x", mask);
+
+ /* Suspend interrupts. */
+ gcmkONERROR(gckOS_SuspendInterrupt(Event->os));
+ suspended = gcvTRUE;
+
+ /* Mark pending interrupt as handled. */
+ Event->pending &= ~mask;
+
+ /* Resume interrupts. */
+ gcmkONERROR(gckOS_ResumeInterrupt(Event->os));
+ suspended = gcvFALSE;
+ }
+
+ /* Check whether the event queue is empty. */
+ gcmkONERROR(_IsEmpty(Event, &empty));
+
+ if (empty)
+ {
+ /* Query whether the hardware is idle. */
+ gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
+
+ if (idle)
+ {
+ /* Inform the system of idle GPU. */
+ gcmkONERROR(gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_IDLE));
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->mutexQueue));
+ }
+
+ if (suspended)
+ {
+ /* Resume interrupts. */
+ gcmkVERIFY_OK(gckOS_ResumeInterrupt(Event->os));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckEVENT_Submit(
+ IN gckEVENT Event,
+ IN gctBOOL Wait
+ )
+{
+ gctUINT8 id = 0xFF;
+ gctSIZE_T bytes;
+ gctPOINTER buffer;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL reserved = gcvFALSE;
+#if gcdGPU_TIMEOUT
+ gctUINT32 timer = 0;
+#endif
+
+ gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
+
+ /* Only process if we have events queued. */
+ if (Event->list.head != gcvNULL)
+ {
+ for (;;)
+ {
+ /* Allocate an event ID. */
+ status = _GetEvent(Event, &id, Event->list.source);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Out of resources? */
+ if (Wait && (status == gcvSTATUS_OUT_OF_RESOURCES))
+ {
+ /* Delay a while. */
+ gcmkONERROR(gckOS_Delay(Event->os, 1));
+
+#if gcdGPU_TIMEOUT
+ /* Increment the wait timer. */
+ timer += 1;
+
+ if (timer == gcdGPU_TIMEOUT)
+ {
+ /* Try to call any outstanding events. */
+ gcmkONERROR(
+ gckHARDWARE_Interrupt(Event->kernel->hardware,
+ gcvTRUE));
+ }
+ else if (timer > gcdGPU_TIMEOUT)
+ {
+ /* Broadcast GPU stuck. */
+ gcmkONERROR(gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK));
+
+ /* Bail out. */
+ gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
+ }
+#endif
+ }
+ else
+ {
+ gcmkONERROR(status);
+ }
+ }
+ else
+ {
+ /* Got en event ID. */
+ break;
+ }
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_EVENT, "Using id=%d", id);
+
+ /* Acquire the list mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Event->os,
+ Event->listMutex,
+ gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Copy event list to event ID queue. */
+ Event->queues[id].source = Event->list.source;
+ Event->queues[id].head = Event->list.head;
+
+ /* Get process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&Event->queues[id].processID));
+
+ /* Mark event list as empty. */
+ Event->list.head = gcvNULL;
+
+ /* Release the list mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+ acquired = gcvFALSE;
+
+#if gcdNULL_DRIVER == 2
+ /* Notify immediately on infinite hardware. */
+ gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
+
+ gcmkONERROR(gckEVENT_Notify(Event, 0));
+#else
+ /* Get the size of the hardware event. */
+ gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
+ gcvNULL,
+ id,
+ gcvKERNEL_PIXEL,
+ &bytes));
+
+ /* Reserve space in the command queue. */
+ gcmkONERROR(gckCOMMAND_Reserve(Event->kernel->command,
+ bytes,
+ &buffer,
+ &bytes));
+ reserved = gcvTRUE;
+
+ /* Set the hardware event in the command queue. */
+ gcmkONERROR(gckHARDWARE_Event(Event->kernel->hardware,
+ buffer,
+ id,
+ Event->queues[id].source,
+ &bytes));
+
+ /* Execute the hardware event. */
+ gcmkONERROR(gckCOMMAND_Execute(Event->kernel->command, bytes));
+ reserved = gcvFALSE;
+#endif
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Need to unroll the mutex acquire. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->listMutex));
+ }
+
+ if (reserved)
+ {
+ /* Need to release the command buffer. */
+ gcmkVERIFY_OK(gckCOMMAND_Release(Event->kernel->command));
+ }
+
+ if (id != 0xFF)
+ {
+ /* Need to unroll the event allocation. */
+ Event->queues[id].head = gcvNULL;
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+/**
+** @file
+** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
+** based memory allocation. An arena-based memory heap allocates data quickly
+** from specified arenas and reduces memory fragmentation.
+**
+*/
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_HEAP
+
+/*******************************************************************************
+***** Structures ***************************************************************
+*******************************************************************************/
+
+#define gcdIN_USE ((gcskNODE_PTR) ~0)
+
+typedef struct _gcskNODE * gcskNODE_PTR;
+typedef struct _gcskNODE
+{
+ /* Number of byets in node. */
+ gctSIZE_T bytes;
+
+ /* Pointer to next free node, or gcvNULL to mark the node as freed, or
+ ** gcdIN_USE to mark the node as used. */
+ gcskNODE_PTR next;
+
+#if gcdDEBUG
+ /* Time stamp of allocation. */
+ gctUINT64 timeStamp;
+#endif
+}
+gcskNODE;
+
+typedef struct _gcskHEAP * gcskHEAP_PTR;
+typedef struct _gcskHEAP
+{
+ /* Linked list. */
+ gcskHEAP_PTR next;
+ gcskHEAP_PTR prev;
+
+ /* Heap size. */
+ gctSIZE_T size;
+
+ /* Free list. */
+ gcskNODE_PTR freeList;
+}
+gcskHEAP;
+
+struct _gckHEAP
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to a gckOS object. */
+ gckOS os;
+
+ /* Locking mutex. */
+ gctPOINTER mutex;
+
+ /* Allocation parameters. */
+ gctSIZE_T allocationSize;
+
+ /* Heap list. */
+ gcskHEAP_PTR heap;
+#if gcdDEBUG
+ gctUINT64 timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Profile information. */
+ gctUINT32 allocCount;
+ gctUINT64 allocBytes;
+ gctUINT64 allocBytesMax;
+ gctUINT64 allocBytesTotal;
+ gctUINT32 heapCount;
+ gctUINT32 heapCountMax;
+ gctUINT64 heapMemory;
+ gctUINT64 heapMemoryMax;
+#endif
+};
+
+/*******************************************************************************
+***** Static Support Functions *************************************************
+*******************************************************************************/
+
+#if gcdDEBUG
+static gctSIZE_T
+_DumpHeap(
+ IN gcskHEAP_PTR Heap
+ )
+{
+ gctPOINTER p;
+ gctSIZE_T leaked = 0;
+
+ /* Start at first node. */
+ for (p = Heap + 1;;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ /* Check if this is a used node. */
+ if (node->next == gcdIN_USE)
+ {
+ /* Print the leaking node. */
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
+ "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
+ "(%08X %c%c%c%c)",
+ node, node->bytes, node->timeStamp,
+ ((gctUINT32_PTR) (node + 1))[0],
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
+ gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
+
+ /* Add leaking byte count. */
+ leaked += node->bytes;
+ }
+
+ /* Test for end of heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ else
+ {
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+ }
+
+ /* Return the number of leaked bytes. */
+ return leaked;
+}
+#endif
+
+static gceSTATUS
+_CompactKernelHeap(
+ IN gckHEAP Heap
+ )
+{
+ gcskHEAP_PTR heap, next;
+ gctPOINTER p;
+ gcskHEAP_PTR freeList = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = next)
+ {
+ gcskNODE_PTR lastFree = gcvNULL;
+
+ /* Zero out the free list. */
+ heap->freeList = gcvNULL;
+
+ /* Start at the first node. */
+ for (p = (gctUINT8_PTR) (heap + 1);;)
+ {
+ /* Convert the pointer. */
+ gcskNODE_PTR node = (gcskNODE_PTR) p;
+
+ gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
+
+ /* Test if this node not used. */
+ if (node->next != gcdIN_USE)
+ {
+ /* Test if this is the end of the heap. */
+ if (node->bytes == 0)
+ {
+ break;
+ }
+
+ /* Test of this is the first free node. */
+ else if (lastFree == gcvNULL)
+ {
+ /* Initialzie the free list. */
+ heap->freeList = node;
+ lastFree = node;
+ }
+
+ else
+ {
+ /* Test if this free node is contiguous with the previous
+ ** free node. */
+ if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
+ {
+ /* Just increase the size of the previous free node. */
+ lastFree->bytes += node->bytes;
+ }
+ else
+ {
+ /* Add to linked list. */
+ lastFree->next = node;
+ lastFree = node;
+ }
+ }
+ }
+
+ /* Move to next node. */
+ p = (gctUINT8_PTR) node + node->bytes;
+ }
+
+ /* Mark the end of the chain. */
+ if (lastFree != gcvNULL)
+ {
+ lastFree->next = gcvNULL;
+ }
+
+ /* Get next heap. */
+ next = heap->next;
+
+ /* Check if the entire heap is free. */
+ if ((heap->freeList != gcvNULL)
+ && (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
+ )
+ {
+ /* Remove the heap from the linked list. */
+ if (heap->prev == gcvNULL)
+ {
+ Heap->heap = next;
+ }
+ else
+ {
+ heap->prev->next = next;
+ }
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profiling. */
+ Heap->heapCount -= 1;
+ Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
+#endif
+
+ /* Add this heap to the list of heaps that need to be freed. */
+ heap->next = freeList;
+ freeList = heap;
+ }
+ }
+
+ if (freeList != gcvNULL)
+ {
+ /* Release the mutex, remove any chance for a dead lock. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Free all heaps in the free list. */
+ for (heap = freeList; heap != gcvNULL; heap = next)
+ {
+ /* Get pointer to the next heap. */
+ next = heap->next;
+
+ /* Free the heap. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Freeing heap 0x%x (%lu bytes)",
+ heap, heap->size + gcmSIZEOF(gcskHEAP));
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Acquire the mutex again. */
+ gcmkVERIFY_OK(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+***** gckHEAP API Code *********************************************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckHEAP_Construct
+**
+** Construct a new gckHEAP object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctSIZE_T AllocationSize
+** Minimum size per arena.
+**
+** OUTPUT:
+**
+** gckHEAP * Heap
+** Pointer to a variable that will hold the pointer to the gckHEAP
+** object.
+*/
+gceSTATUS
+gckHEAP_Construct(
+ IN gckOS Os,
+ IN gctSIZE_T AllocationSize,
+ OUT gckHEAP * Heap
+ )
+{
+ gceSTATUS status;
+ gckHEAP heap = gcvNULL;
+
+ gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
+
+ /* Allocate the gckHEAP object. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Os,
+ gcmSIZEOF(struct _gckHEAP),
+ (gctPOINTER *) &heap));
+
+ /* Initialize the gckHEAP object. */
+ heap->object.type = gcvOBJ_HEAP;
+ heap->os = Os;
+ heap->allocationSize = AllocationSize;
+ heap->heap = gcvNULL;
+#if gcdDEBUG
+ heap->timeStamp = 0;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Zero the counters. */
+ heap->allocCount = 0;
+ heap->allocBytes = 0;
+ heap->allocBytesMax = 0;
+ heap->allocBytesTotal = 0;
+ heap->heapCount = 0;
+ heap->heapCountMax = 0;
+ heap->heapMemory = 0;
+ heap->heapMemoryMax = 0;
+#endif
+
+ /* Create the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
+
+ /* Return the pointer to the gckHEAP object. */
+ *Heap = heap;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Heap=0x%x", Heap);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (heap != gcvNULL)
+ {
+ /* Free the heap structure. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Destroy
+**
+** Destroy a gckHEAP object.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckHEAP_Destroy(
+ IN gckHEAP Heap
+ )
+{
+ gcskHEAP_PTR heap;
+#if gcdDEBUG
+ gctSIZE_T leaked = 0;
+#endif
+
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
+ {
+ /* Unlink heap from linked list. */
+ Heap->heap = heap->next;
+
+#if gcdDEBUG
+ /* Check for leaked memory. */
+ leaked += _DumpHeap(heap);
+#endif
+
+ /* Free the heap. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
+ }
+
+ /* Free the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
+
+ /* Free the heap structure. */
+ gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
+
+ /* Success. */
+#if gcdDEBUG
+ gcmkFOOTER_ARG("leaked=%lu", leaked);
+#else
+ gcmkFOOTER_NO();
+#endif
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Allocate
+**
+** Allocate data from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the address of the allocated
+** memory.
+*/
+gceSTATUS
+gckHEAP_Allocate(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctBOOL acquired = gcvFALSE;
+ gcskHEAP_PTR heap;
+ gceSTATUS status;
+ gctSIZE_T bytes;
+ gcskNODE_PTR node, used, prevFree = gcvNULL;
+ gctPOINTER memory = gcvNULL;
+
+ gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Determine number of bytes required for a node. */
+ bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Check if this allocation is bigger than the default allocation size. */
+ if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP))
+ {
+ /* Adjust allocation size. */
+ Heap->allocationSize = bytes * 2;
+ }
+
+ else if (Heap->heap != gcvNULL)
+ {
+ gctINT i;
+
+ /* 2 retries, since we might need to compact. */
+ for (i = 0; i < 2; ++i)
+ {
+ /* Walk all the heaps. */
+ for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
+ {
+ /* Check if this heap has enough bytes to hold the request. */
+ if (bytes < heap->size)
+ {
+ prevFree = gcvNULL;
+
+ /* Walk the chain of free nodes. */
+ for (node = heap->freeList;
+ node != gcvNULL;
+ node = node->next
+ )
+ {
+ gcmkASSERT(node->next != gcdIN_USE);
+
+ /* Check if this free node has enough bytes. */
+ if (node->bytes >= bytes)
+ {
+ /* Use the node. */
+ goto UseNode;
+ }
+
+ /* Save current free node for linked list management. */
+ prevFree = node;
+ }
+ }
+ }
+
+ if (i == 0)
+ {
+ /* Compact the heap. */
+ gcmkVERIFY_OK(_CompactKernelHeap(Heap));
+
+#if gcdDEBUG
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "===== KERNEL HEAP =====");
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of allocations : %12u",
+ Heap->allocCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of bytes allocated : %12llu",
+ Heap->allocBytes);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum allocation size : %12llu",
+ Heap->allocBytesMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Total number of bytes allocated : %12llu",
+ Heap->allocBytesTotal);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Number of heaps : %12u",
+ Heap->heapCount);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Heap memory in bytes : %12llu",
+ Heap->heapMemory);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum number of heaps : %12u",
+ Heap->heapCountMax);
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
+ "Maximum heap memory in bytes : %12llu",
+ Heap->heapMemoryMax);
+#endif
+ }
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ acquired = gcvFALSE;
+
+ /* Allocate a new heap. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Heap->os,
+ Heap->allocationSize,
+ &memory));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
+ "Allocated heap 0x%x (%lu bytes)",
+ memory, Heap->allocationSize);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ /* Use the allocated memory as the heap. */
+ heap = (gcskHEAP_PTR) memory;
+
+ /* Insert this heap to the head of the chain. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
+
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap;
+ }
+ Heap->heap = heap;
+
+ /* Mark the end of the heap. */
+ node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
+ + Heap->allocationSize
+ - gcmSIZEOF(gcskNODE)
+ );
+ node->bytes = 0;
+ node->next = gcvNULL;
+
+ /* Create a free list. */
+ node = (gcskNODE_PTR) (heap + 1);
+ heap->freeList = node;
+
+ /* Initialize the free list. */
+ node->bytes = heap->size - gcmSIZEOF(gcskNODE);
+ node->next = gcvNULL;
+
+ /* No previous free. */
+ prevFree = gcvNULL;
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profiling. */
+ Heap->heapCount += 1;
+ Heap->heapMemory += Heap->allocationSize;
+
+ if (Heap->heapCount > Heap->heapCountMax)
+ {
+ Heap->heapCountMax = Heap->heapCount;
+ }
+ if (Heap->heapMemory > Heap->heapMemoryMax)
+ {
+ Heap->heapMemoryMax = Heap->heapMemory;
+ }
+#endif
+
+UseNode:
+ /* Verify some stuff. */
+ gcmkASSERT(heap != gcvNULL);
+ gcmkASSERT(node != gcvNULL);
+ gcmkASSERT(node->bytes >= bytes);
+
+ if (heap->prev != gcvNULL)
+ {
+ /* Unlink the heap from the linked list. */
+ heap->prev->next = heap->next;
+ if (heap->next != gcvNULL)
+ {
+ heap->next->prev = heap->prev;
+ }
+
+ /* Move the heap to the front of the list. */
+ heap->next = Heap->heap;
+ heap->prev = gcvNULL;
+ Heap->heap = heap;
+ heap->next->prev = heap;
+ }
+
+ /* Check if there is enough free space left after usage for another free
+ ** node. */
+ if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
+ {
+ /* Allocated used space from the back of the free list. */
+ used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
+
+ /* Adjust the number of free bytes. */
+ node->bytes -= bytes;
+ gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
+ }
+ else
+ {
+ /* Remove this free list from the chain. */
+ if (prevFree == gcvNULL)
+ {
+ heap->freeList = node->next;
+ }
+ else
+ {
+ prevFree->next = node->next;
+ }
+
+ /* Consume the entire free node. */
+ used = (gcskNODE_PTR) node;
+ bytes = node->bytes;
+ }
+
+ /* Mark node as used. */
+ used->bytes = bytes;
+ used->next = gcdIN_USE;
+#if gcdDEBUG
+ used->timeStamp = ++Heap->timeStamp;
+#endif
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profile counters. */
+ Heap->allocCount += 1;
+ Heap->allocBytes += bytes;
+ Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
+ Heap->allocBytesTotal += bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Return pointer to memory. */
+ *Memory = used + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+ }
+
+ if (memory != gcvNULL)
+ {
+ /* Free the heap memory. */
+ gckOS_FreeMemory(Heap->os, memory);
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckHEAP_Free
+**
+** Free allocated memory from the heap.
+**
+** INPUT:
+**
+** gckHEAP Heap
+** Pointer to a gckHEAP object.
+**
+** IN gctPOINTER Memory
+** Pointer to memory to free.
+**
+** OUTPUT:
+**
+** NOTHING.
+*/
+gceSTATUS
+gckHEAP_Free(
+ IN gckHEAP Heap,
+ IN gctPOINTER Memory
+ )
+{
+ gcskNODE_PTR node;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
+
+ /* Pointer to structure. */
+ node = (gcskNODE_PTR) Memory - 1;
+
+ /* Mark the node as freed. */
+ node->next = gcvNULL;
+
+#if VIVANTE_PROFILER || gcdDEBUG
+ /* Update profile counters. */
+ Heap->allocBytes -= node->bytes;
+#endif
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Heap->os, Heap->mutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#if VIVANTE_PROFILER
+gceSTATUS
+gckHEAP_ProfileStart(
+ IN gckHEAP Heap
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x", Heap);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+
+ /* Zero the counters. */
+ Heap->allocCount = 0;
+ Heap->allocBytes = 0;
+ Heap->allocBytesMax = 0;
+ Heap->allocBytesTotal = 0;
+ Heap->heapCount = 0;
+ Heap->heapCountMax = 0;
+ Heap->heapMemory = 0;
+ Heap->heapMemoryMax = 0;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckHEAP_ProfileEnd(
+ IN gckHEAP Heap,
+ IN gctCONST_STRING Title
+ )
+{
+ gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
+ gcmkVERIFY_ARGUMENT(Title != gcvNULL);
+
+ gcmkPRINT("");
+ gcmkPRINT("=====[ HEAP - %s ]=====", Title);
+ gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
+ gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
+ gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
+ gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
+ gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
+ gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
+ gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
+ gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
+ gcmkPRINT("==============================================");
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+#endif /* VIVANTE_PROFILER */
+
+/*******************************************************************************
+***** Test Code ****************************************************************
+*******************************************************************************/
+
+#if defined gcdHAL_TEST
+
+#include <stdlib.h>
+#define gcmRANDOM(n) (rand() % n)
+
+typedef struct
+{
+ gctSIZE_T bytes;
+ gctPOINTER memory;
+}
+gcskHEAP_TEST;
+
+gceSTATUS
+gckHEAP_Test(
+ IN gckHEAP Heap,
+ IN gctSIZE_T Vectors,
+ IN gctSIZE_T MaxSize
+ )
+{
+ gctSIZE_T nodeCount = MaxSize / 4;
+ gcskHEAP_TEST * nodes = gcvNULL;
+ gctSIZE_T bytes, index, i;
+ gceSTATUS status, failure = gcvSTATUS_OK;
+ gctUINT8_PTR memory;
+ gcskHEAP_PTR heap, current;
+
+ /* Allocate the node array. */
+ gcmkONERROR(
+ gckOS_AllocateMemory(Heap->os,
+ nodeCount * gcmSIZEOF(gcskHEAP_TEST),
+ (gctPOINTER *) &nodes));
+
+ /* Mark all nodes as free. */
+ gcmkONERROR(
+ gckOS_ZeroMemory(nodes, nodeCount * gcmSIZEOF(gcskHEAP_TEST)));
+
+ gcmkONERROR(gckHEAP_ProfileStart(Heap));
+
+ /* Loop through all vectors. */
+ while (Vectors-- > 0)
+ {
+ /* Get a random index. */
+ index = gcmRANDOM(nodeCount);
+
+ /* Test if we need to allocate pages. */
+ if (nodes[index].bytes == 0)
+ {
+ /* Generate a random byte size. */
+ do
+ {
+ bytes = gcmALIGN(gcmRANDOM(MaxSize), gcmSIZEOF(gctSIZE_T));
+ }
+ while (bytes == 0);
+
+ /* Allocate pages. */
+ status = gckHEAP_Allocate(Heap, bytes, (gctPOINTER *) &memory);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Mark node as allocated. */
+ nodes[index].bytes = bytes;
+ nodes[index].memory = memory;
+
+ /* Put signature in the memory. */
+ for (i = 0; i < bytes; i += gcmSIZEOF(gctSIZE_T))
+ {
+ *(gctSIZE_T_PTR) (memory + i) = index;
+ }
+ }
+ else
+ {
+ gcmkTRACE(gcvLEVEL_WARNING,
+ "%s(%d): Failed to allocate %lu bytes",
+ __FUNCTION__, __LINE__, bytes);
+ }
+ }
+ else
+ {
+ /* Verify the memory. */
+ memory = nodes[index].memory;
+ for (i = 0; i < nodes[index].bytes; i += gcmSIZEOF(gctSIZE_T))
+ {
+ if (*(gctSIZE_T_PTR) (memory + i) != index)
+ {
+ gcmkFATAL("%s(%d): Corruption detected at index %lu",
+ __FUNCTION__, __LINE__, index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the memory. */
+ status = gckHEAP_Free(Heap, memory);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("%s(%d): Cannot free %lu bytes at 0x%x (index=%lu)",
+ __FUNCTION__, __LINE__,
+ nodes[index].bytes, memory, index);
+
+ failure = status;
+ }
+
+ /* Mark the node as free. */
+ nodes[index].bytes = 0;
+ }
+
+ /* Verify the heap chain. */
+ i = 0;
+ for (current = Heap->heap; current != gcvNULL; current = current->next)
+ {
+ gctSIZE_T j;
+ for (heap = Heap->heap, j = 0; j < i; heap = heap->next, ++j)
+ {
+ if (heap == current)
+ {
+ gcmkFATAL("%s(%d): Linked list corrupted for heap 0x%x",
+ __FUNCTION__, __LINE__, current);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ if (heap != current)
+ {
+ gcmkFATAL("%s(%d): Linked list corrupted for heap 0x%x",
+ __FUNCTION__, __LINE__, current);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+ ++i;
+ }
+ }
+
+ /* Walk the entire array of nodes. */
+ for (index = 0; index < nodeCount; ++index)
+ {
+ /* Test if we need to free pages. */
+ if (nodes[index].bytes != 0)
+ {
+ /* Verify the memory. */
+ memory = nodes[index].memory;
+ for (i = 0; i < nodes[index].bytes; i += gcmSIZEOF(gctSIZE_T))
+ {
+ if (*(gctSIZE_T_PTR) (memory + i) != index)
+ {
+ gcmkFATAL("%s(%d): Corruption detected at page %lu",
+ __FUNCTION__, __LINE__, index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the memory. */
+ status = gckHEAP_Free(Heap, memory);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("%s(%d): Cannot free %u bytes at 0x%x (index=%lu)",
+ __FUNCTION__, __LINE__,
+ nodes[index].bytes, memory, index);
+
+ failure = status;
+ }
+ }
+ }
+
+ /* Perform garbage collection. */
+ gcmkONERROR(_CompactKernelHeap(Heap));
+
+ /* Show profiling. */
+ gcmkONERROR(gckHEAP_ProfileEnd(Heap, "Profile"));
+
+ /* Verify we did not loose any nodes. */
+ if (Heap->heap != gcvNULL)
+ {
+ gcmkFATAL("%s(%d): Detected leaking in the heap.",
+ __FUNCTION__, __LINE__);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+OnError:
+ /* Roll back. */
+ if (nodes != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_FreeMemory(Heap->os, nodes));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_MMU
+
+typedef enum _gceMMU_TYPE
+{
+ gcvMMU_USED = 0,
+ gcvMMU_SINGLE,
+ gcvMMU_FREE,
+}
+gceMMU_TYPE;
+
+static gceSTATUS
+_Link(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 Next
+ )
+{
+ if (Index >= Mmu->pageTableEntries)
+ {
+ /* Just move heap pointer. */
+ Mmu->heapList = Next;
+ }
+ else
+ {
+ /* Address page table. */
+ gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+
+ /* Dispatch on node type. */
+ switch (pageTable[Index] & 0xFF)
+ {
+ case gcvMMU_SINGLE:
+ /* Set single index. */
+ pageTable[Index] = (Next << 8) | gcvMMU_SINGLE;
+ break;
+
+ case gcvMMU_FREE:
+ /* Set index. */
+ pageTable[Index + 1] = Next;
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", Index);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+static gceSTATUS
+_AddFree(
+ IN gckMMU Mmu,
+ IN gctUINT32 Index,
+ IN gctUINT32 Node,
+ IN gctUINT32 Count
+ )
+{
+ gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+
+ if (Count == 1)
+ {
+ /* Initialize a single page node. */
+ pageTable[Node] = (~0U << 8) | gcvMMU_SINGLE;
+ }
+ else
+ {
+ /* Initialize the node. */
+ pageTable[Node + 0] = (Count << 8) | gcvMMU_FREE;
+ pageTable[Node + 1] = ~0U;
+ }
+
+ /* Append the node. */
+ return _Link(Mmu, Index, Node);
+}
+
+static gceSTATUS
+_Collect(
+ IN gckMMU Mmu
+ )
+{
+ gctUINT32_PTR pageTable = Mmu->pageTableLogical;
+ gceSTATUS status;
+ gctUINT32 i, previous, start = 0, count = 0;
+
+ /* Flush the MMU cache. */
+ gcmkONERROR(
+ gckHARDWARE_FlushMMU(Mmu->hardware));
+
+ previous = Mmu->heapList = ~0U;
+ Mmu->freeNodes = gcvFALSE;
+
+ /* Walk the entire page table. */
+ for (i = 0; i < Mmu->pageTableEntries; ++i)
+ {
+ /* Dispatch based on type of page. */
+ switch (pageTable[i] & 0xFF)
+ {
+ case gcvMMU_USED:
+ /* Used page, so close any open node. */
+ if (count > 0)
+ {
+ /* Add the node. */
+ gcmkONERROR(_AddFree(Mmu, previous, start, count));
+
+ /* Reset the node. */
+ previous = start;
+ count = 0;
+ }
+ break;
+
+ case gcvMMU_SINGLE:
+ /* Single free node. */
+ if (count++ == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* A free node. */
+ if (count == 0)
+ {
+ /* Start a new node. */
+ start = i;
+ }
+
+ /* Advance the count. */
+ count += pageTable[i] >> 8;
+
+ /* Advance the index into the page table. */
+ i += (pageTable[i] >> 8) - 1;
+ break;
+
+ default:
+ gcmkFATAL("MMU page table correcupted at index %u!", i);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* See if we have an open node left. */
+ if (count > 0)
+ {
+ /* Add the node to the list. */
+ gcmkONERROR(_AddFree(Mmu, previous, start, count));
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
+ "Performed a garbage collection of the MMU heap.");
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the staus. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_Construct
+**
+** Construct a new gckMMU object.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T MmuSize
+** Number of bytes for the page table.
+**
+** OUTPUT:
+**
+** gckMMU * Mmu
+** Pointer to a variable that receives the gckMMU object pointer.
+*/
+gceSTATUS
+gckMMU_Construct(
+ IN gckKERNEL Kernel,
+ IN gctSIZE_T MmuSize,
+ OUT gckMMU * Mmu
+ )
+{
+ gckOS os;
+ gckHARDWARE hardware;
+ gceSTATUS status;
+ gckMMU mmu = gcvNULL;
+ gctUINT32_PTR pageTable;
+
+ gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(MmuSize > 0);
+ gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Extract the gckHARDWARE object pointer. */
+ hardware = Kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Allocate memory for the gckMMU object. */
+ gcmkONERROR(
+ gckOS_Allocate(os, sizeof(struct _gckMMU), (gctPOINTER *) &mmu));
+
+ /* Initialize the gckMMU object. */
+ mmu->object.type = gcvOBJ_MMU;
+ mmu->os = os;
+ mmu->hardware = hardware;
+ mmu->pageTableMutex = gcvNULL;
+ mmu->pageTableLogical = gcvNULL;
+#ifdef __QNXNTO__
+ mmu->nodeList = gcvNULL;
+ mmu->nodeMutex = gcvNULL;
+#endif
+
+ /* Create the page table mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
+
+#ifdef __QNXNTO__
+ /* Create the node list mutex. */
+ gcmkONERROR(gckOS_CreateMutex(os, &mmu->nodeMutex));
+#endif
+
+ /* Allocate the page table (not more than 256 kB). */
+ mmu->pageTableSize = gcmMIN(MmuSize, 256 << 10);
+ gcmkONERROR(
+ gckOS_AllocateContiguous(os,
+ gcvFALSE,
+ &mmu->pageTableSize,
+ &mmu->pageTablePhysical,
+ (gctPOINTER *) &mmu->pageTableLogical));
+
+ /* Compute number of entries in page table. */
+ mmu->pageTableEntries = mmu->pageTableSize / sizeof(gctUINT32);
+
+ /* Mark all pages as free. */
+ pageTable = mmu->pageTableLogical;
+ pageTable[0] = (mmu->pageTableEntries << 8) | gcvMMU_FREE;
+ pageTable[1] = ~0U;
+ mmu->heapList = 0;
+ mmu->freeNodes = gcvFALSE;
+
+ /* Set page table address. */
+ gcmkONERROR(
+ gckHARDWARE_SetMMU(hardware, (gctPOINTER) mmu->pageTableLogical));
+
+ /* Return the gckMMU object pointer. */
+ *Mmu = mmu;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Mmu=0x%x", *Mmu);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (mmu != gcvNULL)
+ {
+ if (mmu->pageTableLogical != gcvNULL)
+ {
+ /* Free the page table. */
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(os,
+ mmu->pageTablePhysical,
+ (gctPOINTER) mmu->pageTableLogical,
+ mmu->pageTableSize));
+ }
+
+ if (mmu->pageTableMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, mmu->pageTableMutex));
+ }
+
+#ifdef __QNXNTO__
+ if (mmu->nodeMutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, mmu->nodeMutex));
+ }
+#endif
+
+ /* Mark the gckMMU object as unknown. */
+ mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the allocates memory. */
+ gcmkVERIFY_OK(gckOS_Free(os, mmu));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_Destroy
+**
+** Destroy a gckMMU object.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckMMU_Destroy(
+ IN gckMMU Mmu
+ )
+{
+#ifdef __QNXNTO__
+ gcuVIDMEM_NODE_PTR node, next;
+#endif
+
+ gcmkHEADER_ARG("Mmu=0x%x", Mmu);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+#ifdef __QNXNTO__
+ /* Free all associated virtual memory. */
+ for (node = Mmu->nodeList; node != gcvNULL; node = next)
+ {
+ next = node->Virtual.next;
+ gcmkVERIFY_OK(gckVIDMEM_Free(node, gcvNULL));
+ }
+#endif
+
+ /* Free the page table. */
+ gcmkVERIFY_OK(
+ gckOS_FreeContiguous(Mmu->os,
+ Mmu->pageTablePhysical,
+ (gctPOINTER) Mmu->pageTableLogical,
+ Mmu->pageTableSize));
+
+#ifdef __QNXNTO__
+ /* Delete the node list mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->nodeMutex));
+#endif
+
+ /* Delete the page table mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->pageTableMutex));
+
+ /* Mark the gckMMU object as unknown. */
+ Mmu->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckMMU object. */
+ gcmkVERIFY_OK(gckOS_Free(Mmu->os, Mmu));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckMMU_AllocatePages
+**
+** Allocate pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctSIZE_T PageCount
+** Number of pages to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * PageTable
+** Pointer to a variable that receives the base address of the page
+** table.
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the hardware specific address.
+*/
+gceSTATUS
+gckMMU_AllocatePages(
+ IN gckMMU Mmu,
+ IN gctSIZE_T PageCount,
+ OUT gctPOINTER * PageTable,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gctUINT32 index = 0, previous = ~0U, left;
+ gctUINT32_PTR pageTable;
+ gctBOOL gotIt;
+ gctUINT32 address;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+
+ if (PageCount > Mmu->pageTableEntries)
+ {
+ /* Not enough pages avaiable. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ /* Cast pointer to page table. */
+ for (pageTable = Mmu->pageTableLogical, gotIt = gcvFALSE; !gotIt;)
+ {
+ /* Walk the heap list. */
+ for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);)
+ {
+ /* Check the node type. */
+ switch (pageTable[index] & 0xFF)
+ {
+ case gcvMMU_SINGLE:
+ /* Single odes are valid if we only need 1 page. */
+ if (PageCount == 1)
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = pageTable[index] >> 8;
+ }
+ break;
+
+ case gcvMMU_FREE:
+ /* Test if the node has enough space. */
+ if (PageCount <= (pageTable[index] >> 8))
+ {
+ gotIt = gcvTRUE;
+ }
+ else
+ {
+ /* Move to next node. */
+ previous = index;
+ index = pageTable[index + 1];
+ }
+ break;
+
+ default:
+ gcmkFATAL("MMU table correcupted at index %u!", index);
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+
+ /* Test if we are out of memory. */
+ if (index >= Mmu->pageTableEntries)
+ {
+ if (Mmu->freeNodes)
+ {
+ /* Time to move out the trash! */
+ gcmkONERROR(_Collect(Mmu));
+ }
+ else
+ {
+ /* Out of resources. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+ }
+ }
+ }
+
+ switch (pageTable[index] & 0xFF)
+ {
+ case gcvMMU_SINGLE:
+ /* Unlink single node from free list. */
+ gcmkONERROR(
+ _Link(Mmu, previous, pageTable[index] >> 8));
+ break;
+
+ case gcvMMU_FREE:
+ /* Check how many pages will be left. */
+ left = (pageTable[index] >> 8) - PageCount;
+ switch (left)
+ {
+ case 0:
+ /* The entire node is consumed, just unlink it. */
+ gcmkONERROR(
+ _Link(Mmu, previous, pageTable[index + 1]));
+ break;
+
+ case 1:
+ /* One page will remain. Convert the node to a single node and
+ ** advance the index. */
+ pageTable[index] = (pageTable[index + 1] << 8) | gcvMMU_SINGLE;
+ index ++;
+ break;
+
+ default:
+ /* Enough pages remain for a new node. However, we will just adjust
+ ** the size of the current node and advance the index. */
+ pageTable[index] = (left << 8) | gcvMMU_FREE;
+ index += left;
+ break;
+ }
+ break;
+ }
+
+ /* Mark node as used. */
+ pageTable[index] = gcvMMU_USED;
+
+ /* Return pointer to page table. */
+ *PageTable = &pageTable[index];
+
+ /* Build virtual address. */
+ gcmkONERROR(
+ gckHARDWARE_BuildVirtualAddress(Mmu->hardware, index, 0, &address));
+
+ if (Address != gcvNULL)
+ {
+ *Address = address;
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+
+ /* Success. */
+ gcmkFOOTER_ARG("*PageTable=0x%x *Address=%08x",
+ *PageTable, gcmOPT_VALUE(Address));
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutex)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckMMU_FreePages
+**
+** Free pages inside the page table.
+**
+** INPUT:
+**
+** gckMMU Mmu
+** Pointer to an gckMMU object.
+**
+** gctPOINTER PageTable
+** Base address of the page table to free.
+**
+** gctSIZE_T PageCount
+** Number of pages to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckMMU_FreePages(
+ IN gckMMU Mmu,
+ IN gctPOINTER PageTable,
+ IN gctSIZE_T PageCount
+ )
+{
+ gctUINT32_PTR pageTable;
+
+ gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
+ Mmu, PageTable, PageCount);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+ gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+
+ /* Convert the pointer. */
+ pageTable = (gctUINT32_PTR) PageTable;
+
+ if (PageCount == 1)
+ {
+ /* Single page node. */
+ pageTable[0] = (~0U << 8) | gcvMMU_SINGLE;
+ }
+ else
+ {
+ /* Mark the node as free. */
+ pageTable[0] = (PageCount << 8) | gcvMMU_FREE;
+ pageTable[1] = ~0U;
+ }
+
+ /* We have free nodes. */
+ Mmu->freeNodes = gcvTRUE;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#ifdef __QNXNTO__
+gceSTATUS
+gckMMU_InsertNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node)
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+
+ gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ Node->Virtual.next = Mmu->nodeList;
+ Mmu->nodeList = Node;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutex)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_RemoveNode(
+ IN gckMMU Mmu,
+ IN gcuVIDMEM_NODE_PTR Node)
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gcuVIDMEM_NODE_PTR *iter;
+
+ gcmkHEADER_ARG("Mmu=0x%x Node=0x%x", Mmu, Node);
+
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ for (iter = &Mmu->nodeList; *iter; iter = &(*iter)->Virtual.next)
+ {
+ if (*iter == Node)
+ {
+ *iter = Node->Virtual.next;
+ break;
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutex)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckMMU_FreeHandleMemory(
+ IN gckMMU Mmu,
+ IN gctHANDLE Handle
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gcuVIDMEM_NODE_PTR curr, next;
+
+ gcmkHEADER_ARG("Mmu=0x%x Handle=0x%x", Mmu, Handle);
+
+ gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
+
+ gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->nodeMutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ for (curr = Mmu->nodeList; curr != gcvNULL; curr = next)
+ {
+ next = curr->Virtual.next;
+
+ if (curr->Virtual.handle == Handle)
+ {
+ while (curr->Virtual.locked > 0 || curr->Virtual.unlockPending)
+ {
+ gcmkONERROR(gckVIDMEM_Unlock(curr, gcvSURF_TYPE_UNKNOWN, gcvNULL, gcvNULL));
+ }
+
+ gcmkVERIFY_OK(gckVIDMEM_Free(curr, gcvNULL));
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->nodeMutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/******************************************************************************
+****************************** T E S T C O D E ******************************
+******************************************************************************/
+
+#if defined gcdHAL_TEST
+
+#include <stdlib.h>
+#define gcmRANDOM(n) (rand() % n)
+
+typedef struct
+{
+ gctSIZE_T pageCount;
+ gctUINT32_PTR pageTable;
+}
+gcsMMU_TEST;
+
+gceSTATUS
+gckMMU_Test(
+ IN gckMMU Mmu,
+ IN gctSIZE_T Vectors,
+ IN gctINT MaxSize
+ )
+{
+ const gctINT nodeCount = MaxSize / 4;
+ gcsMMU_TEST * nodes = gcvNULL;
+ gceSTATUS status, failure = gcvSTATUS_OK;
+ gctSIZE_T i, count;
+ gctUINT32_PTR pageTable;
+ gctINT index;
+
+ /* Allocate the node array. */
+ gcmkONERROR(
+ gckOS_Allocate(Mmu->os,
+ nodeCount * gcmSIZEOF(gcsMMU_TEST),
+ (gctPOINTER *) &nodes));
+
+ /* Mark all nodes as free. */
+ gcmkONERROR(
+ gckOS_ZeroMemory(nodes, nodeCount * gcmSIZEOF(gcsMMU_TEST)));
+
+ /* Loop through all vectors. */
+ while (Vectors-- > 0)
+ {
+ /* Get a random index. */
+ index = gcmRANDOM(nodeCount);
+
+ /* Test if we need to allocate pages. */
+ if (nodes[index].pageCount == 0)
+ {
+ /* Generate a random page count. */
+ do
+ {
+ count = gcmRANDOM(MaxSize);
+ }
+ while (count == 0);
+
+ /* Allocate pages. */
+ status = gckMMU_AllocatePages(Mmu,
+ count,
+ (gctPOINTER *) &pageTable,
+ gcvNULL);
+
+ if (gcmIS_SUCCESS(status))
+ {
+ /* Mark node as allocated. */
+ nodes[index].pageCount = count;
+ nodes[index].pageTable = pageTable;
+
+ /* Put signature in the page table. */
+ for (i = 0; i < count; ++i)
+ {
+ pageTable[i] = (index << 8) | gcvMMU_USED;
+ }
+ }
+ else
+ {
+ gcmkTRACE(gcvLEVEL_WARNING,
+ "gckMMU_Test: Failed to allocate %u pages",
+ count);
+ }
+ }
+ else
+ {
+ /* Verify the page table. */
+ pageTable = nodes[index].pageTable;
+ for (i = 0; i < nodes[index].pageCount; ++i)
+ {
+ if (pageTable[i] != ((index << 8) | gcvMMU_USED))
+ {
+ gcmkFATAL("gckMMU_Test: Corruption detected at page %u",
+ index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the pages. */
+ status = gckMMU_FreePages(Mmu, pageTable, nodes[index].pageCount);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("gckMMU_Test: Cannot free %u pages at 0x%x (index=%u)",
+ nodes[index].pageCount, pageTable, index);
+
+ failure = status;
+ }
+
+ /* Mark the node as free. */
+ nodes[index].pageCount = 0;
+ }
+ }
+
+ /* Walk the entire array of nodes. */
+ for (index = 0; index < nodeCount; ++index)
+ {
+ /* Test if we need to free pages. */
+ if (nodes[index].pageCount != 0)
+ {
+ /* Verify the page table. */
+ pageTable = nodes[index].pageTable;
+ for (i = 0; i < nodes[index].pageCount; ++i)
+ {
+ if (pageTable[i] != ((index << 8) | gcvMMU_USED))
+ {
+ gcmkFATAL("gckMMU_Test: Corruption detected at page %u",
+ index);
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+ }
+
+ /* Free the pages. */
+ status = gckMMU_FreePages(Mmu, pageTable, nodes[index].pageCount);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkFATAL("gckMMU_Test: Cannot free %u pages at 0x%x (index=%u)",
+ nodes[index].pageCount, pageTable, index);
+
+ failure = status;
+ }
+ }
+ }
+
+ /* Perform garbage collection. */
+ gcmkONERROR(_Collect(Mmu));
+
+ /* Verify we did not loose any nodes. */
+ if ((Mmu->heapList != 0)
+ || ((Mmu->pageTableLogical[0] & 0xFF) != gcvMMU_FREE)
+ || (Mmu->pageTableEntries != (Mmu->pageTableLogical[0] >> 8))
+ )
+ {
+ gcmkFATAL("gckMMU_Test: Detected leaking in the page table.");
+
+ failure = gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+OnError:
+ /* Free the array of nodes. */
+ if (nodes != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_Free(Mmu->os, nodes));
+ }
+
+ /* Return test status. */
+ return failure;
+}
+#endif
+
--- /dev/null
+/****************************************************************************
+*
+* 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_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_precomp.h"
+
+#define _GC_OBJ_ZONE gcvZONE_VIDMEM
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** _Split
+**
+** Split a node on the required byte boundary.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the node to split.
+**
+** gctSIZE_T Bytes
+** Number of bytes to keep in the node.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gctBOOL
+** gcvTRUE if the node was split successfully, or gcvFALSE if there is an
+** error.
+**
+*/
+static gctBOOL
+_Split(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+
+ /* Make sure the byte boundary makes sense. */
+ if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
+ {
+ return gcvFALSE;
+ }
+
+ /* Allocate a new gcuVIDMEM_NODE object. */
+ if (gcmIS_ERROR(gckOS_Allocate(Os,
+ gcmSIZEOF(gcuVIDMEM_NODE),
+ (gctPOINTER *) &node)))
+ {
+ /* Error. */
+ return gcvFALSE;
+ }
+
+ /* Initialize gcuVIDMEM_NODE structure. */
+ node->VidMem.offset = Node->VidMem.offset + Bytes;
+ node->VidMem.bytes = Node->VidMem.bytes - Bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.locked = 0;
+ node->VidMem.memory = Node->VidMem.memory;
+ node->VidMem.pool = Node->VidMem.pool;
+ node->VidMem.physical = Node->VidMem.physical;
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ node->VidMem.handle = 0;
+#endif
+
+ /* Insert node behind specified node. */
+ node->VidMem.next = Node->VidMem.next;
+ node->VidMem.prev = Node;
+ Node->VidMem.next = node->VidMem.next->VidMem.prev = node;
+
+ /* Insert free node behind specified node. */
+ node->VidMem.nextFree = Node->VidMem.nextFree;
+ node->VidMem.prevFree = Node;
+ Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
+
+ /* Adjust size of specified node. */
+ Node->VidMem.bytes = Bytes;
+
+ /* Success. */
+ return gcvTRUE;
+}
+
+/*******************************************************************************
+**
+** _Merge
+**
+** Merge two adjacent nodes together.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to the first of the two nodes to merge.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+*/
+static gceSTATUS
+_Merge(
+ IN gckOS Os,
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+
+ /* Save pointer to next node. */
+ node = Node->VidMem.next;
+
+ /* This is a good time to make sure the heap is not corrupted. */
+ if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
+ {
+ /* Corrupted heap. */
+ gcmkASSERT(
+ Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
+ return gcvSTATUS_HEAP_CORRUPTED;
+ }
+
+ /* Adjust byte count. */
+ Node->VidMem.bytes += node->VidMem.bytes;
+
+ /* Unlink next node from linked list. */
+ Node->VidMem.next = node->VidMem.next;
+ Node->VidMem.nextFree = node->VidMem.nextFree;
+
+ Node->VidMem.next->VidMem.prev =
+ Node->VidMem.nextFree->VidMem.prevFree = Node;
+
+ /* Free next node. */
+ return gckOS_Free(Os, node);
+}
+
+/******************************************************************************\
+******************************* gckVIDMEM API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckVIDMEM_ConstructVirtual
+**
+** Construct a new gcuVIDMEM_NODE union for virtual memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctSIZE_T Bytes
+** Number of byte to allocate.
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
+*/
+gceSTATUS
+gckVIDMEM_ConstructVirtual(
+ IN gckKERNEL Kernel,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node = gcvNULL;
+
+ gcmkHEADER_ARG("Kernel=0x%x Bytes=%lu", Kernel, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+#ifdef __QNXNTO__
+ gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+ /* Extract the gckOS object pointer. */
+ os = Kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Allocate an gcuVIDMEM_NODE union. */
+ gcmkONERROR(
+ gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), (gctPOINTER *) &node));
+
+ /* Initialize gcuVIDMEM_NODE union for virtual memory. */
+ node->Virtual.kernel = Kernel;
+ node->Virtual.contiguous = Contiguous;
+ node->Virtual.locked = 0;
+ node->Virtual.logical = gcvNULL;
+ node->Virtual.pageTable = gcvNULL;
+ node->Virtual.mutex = gcvNULL;
+#ifdef __QNXNTO__
+ node->Virtual.next = gcvNULL;
+ node->Virtual.unlockPending = gcvFALSE;
+ node->Virtual.freePending = gcvFALSE;
+ node->Virtual.handle = Handle;
+#else
+ node->Virtual.pending = gcvFALSE;
+#endif
+
+ /* Create the mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &node->Virtual.mutex));
+
+ /* Allocate the virtual memory. */
+ gcmkONERROR(
+ gckOS_AllocatePagedMemoryEx(os,
+ node->Virtual.contiguous,
+ node->Virtual.bytes = Bytes,
+ &node->Virtual.physical));
+
+#ifdef __QNXNTO__
+ /* Register. */
+ gckMMU_InsertNode(Kernel->mmu, node);
+#endif
+
+ /* Return pointer to the gcuVIDMEM_NODE union. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Created virtual node 0x%x for %u bytes @ 0x%x",
+ node, Bytes, node->Virtual.physical);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (node != gcvNULL)
+ {
+ if (node->Virtual.mutex != gcvNULL)
+ {
+ /* Destroy the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->Virtual.mutex));
+ }
+
+ /* Free the structure. */
+ gcmkVERIFY_OK(gckOS_Free(os, node));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_DestroyVirtual
+**
+** Destroy an gcuVIDMEM_NODE union for virtual memory.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_DestroyVirtual(
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gckOS os;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+ /* Extact the gckOS object pointer. */
+ os = Node->Virtual.kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+#ifdef __QNXNTO__
+ /* Unregister. */
+ gcmkVERIFY_OK(
+ gckMMU_RemoveNode(Node->Virtual.kernel->mmu, Node));
+
+ /* Free virtual memory. */
+ gcmkVERIFY_OK(
+ gckOS_FreePagedMemory(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes));
+#endif
+
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(os, Node->Virtual.mutex));
+
+ if (Node->Virtual.pageTable != gcvNULL)
+ {
+ /* Free the pages. */
+ gcmkVERIFY_OK(gckMMU_FreePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageTable,
+ Node->Virtual.pageCount));
+ }
+
+ /* Delete the gcuVIDMEM_NODE union. */
+ gcmkVERIFY_OK(gckOS_Free(os, Node));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Construct
+**
+** Construct a new gckVIDMEM object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 BaseAddress
+** Base address for the video memory heap.
+**
+** gctSIZE_T Bytes
+** Number of bytes in the video memory heap.
+**
+** gctSIZE_T Threshold
+** Minimum number of bytes beyond am allocation before the node is
+** split. Can be used as a minimum alignment requirement.
+**
+** gctSIZE_T BankSize
+** Number of bytes per physical memory bank. Used by bank
+** optimization.
+**
+** OUTPUT:
+**
+** gckVIDMEM * Memory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object.
+*/
+gceSTATUS
+gckVIDMEM_Construct(
+ IN gckOS Os,
+ IN gctUINT32 BaseAddress,
+ IN gctSIZE_T Bytes,
+ IN gctSIZE_T Threshold,
+ IN gctSIZE_T BankSize,
+ OUT gckVIDMEM * Memory
+ )
+{
+ gckVIDMEM memory = gcvNULL;
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctINT i, banks = 0;
+
+ gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
+ "BankSize=%lu",
+ Os, BaseAddress, Bytes, Threshold, BankSize);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+
+ /* Allocate the gckVIDMEM object. */
+ gcmkONERROR(
+ gckOS_Allocate(Os,
+ gcmSIZEOF(struct _gckVIDMEM),
+ (gctPOINTER *) &memory));
+
+ /* Initialize the gckVIDMEM object. */
+ memory->object.type = gcvOBJ_VIDMEM;
+ memory->os = Os;
+
+ /* Set video memory heap information. */
+ memory->baseAddress = BaseAddress;
+ memory->bytes = Bytes;
+ memory->freeBytes = Bytes;
+ memory->threshold = Threshold;
+ memory->mutex = gcvNULL;
+
+ BaseAddress = 0;
+
+ /* Walk all possible banks. */
+ for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
+ {
+ gctSIZE_T bytes;
+
+ if (BankSize == 0)
+ {
+ /* Use all bytes for the first bank. */
+ bytes = Bytes;
+ }
+ else
+ {
+ /* Compute number of bytes for this bank. */
+ bytes = gcmALIGN(BaseAddress + 1, BankSize) - BaseAddress;
+
+ if (bytes > Bytes)
+ {
+ /* Make sure we don't exceed the total number of bytes. */
+ bytes = Bytes;
+ }
+ }
+
+ if (bytes == 0)
+ {
+ /* Mark heap is not used. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = gcvNULL;
+ continue;
+ }
+
+ /* Allocate one gcuVIDMEM_NODE union. */
+ gcmkONERROR(
+ gckOS_Allocate(Os,
+ gcmSIZEOF(gcuVIDMEM_NODE),
+ (gctPOINTER *) &node));
+
+ /* Initialize gcuVIDMEM_NODE union. */
+ node->VidMem.memory = memory;
+
+ node->VidMem.next =
+ node->VidMem.prev =
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = &memory->sentinel[i];
+
+ node->VidMem.offset = BaseAddress;
+ node->VidMem.bytes = bytes;
+ node->VidMem.alignment = 0;
+ node->VidMem.physical = 0;
+ node->VidMem.pool = gcvPOOL_UNKNOWN;
+
+ node->VidMem.locked = 0;
+
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ node->VidMem.handle = 0;
+#endif
+
+ /* Initialize the linked list of nodes. */
+ memory->sentinel[i].VidMem.next =
+ memory->sentinel[i].VidMem.prev =
+ memory->sentinel[i].VidMem.nextFree =
+ memory->sentinel[i].VidMem.prevFree = node;
+
+ /* Mark sentinel. */
+ memory->sentinel[i].VidMem.bytes = 0;
+
+ /* Adjust address for next bank. */
+ BaseAddress += bytes;
+ Bytes -= bytes;
+ banks ++;
+ }
+
+ /* Assign all the bank mappings. */
+ memory->mapping[gcvSURF_RENDER_TARGET] = banks - 1;
+ memory->mapping[gcvSURF_BITMAP] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_DEPTH] = banks - 1;
+ memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TEXTURE] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_VERTEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_INDEX] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TILE_STATUS] = banks - 1;
+ if (banks > 1) --banks;
+ memory->mapping[gcvSURF_TYPE_UNKNOWN] = 0;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] INDEX: bank %d",
+ memory->mapping[gcvSURF_INDEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] VERTEX: bank %d",
+ memory->mapping[gcvSURF_VERTEX]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TEXTURE: bank %d",
+ memory->mapping[gcvSURF_TEXTURE]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] RENDER_TARGET: bank %d",
+ memory->mapping[gcvSURF_RENDER_TARGET]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] DEPTH: bank %d",
+ memory->mapping[gcvSURF_DEPTH]);
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "[GALCORE] TILE_STATUS: bank %d",
+ memory->mapping[gcvSURF_TILE_STATUS]);
+
+ /* Allocate the mutex. */
+ gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));
+
+ /* Return pointer to the gckVIDMEM object. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Roll back. */
+ if (memory != gcvNULL)
+ {
+ if (memory->mutex != gcvNULL)
+ {
+ /* Delete the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
+ }
+
+ for (i = 0; i < banks; ++i)
+ {
+ /* Free the heap. */
+ gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
+ gcmkVERIFY_OK(gckOS_Free(Os, memory->sentinel[i].VidMem.next));
+ }
+
+ /* Free the object. */
+ gcmkVERIFY_OK(gckOS_Free(Os, memory));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Destroy
+**
+** Destroy an gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Destroy(
+ IN gckVIDMEM Memory
+ )
+{
+ gcuVIDMEM_NODE_PTR node, next;
+ gctINT i;
+
+ gcmkHEADER_ARG("Memory=0x%x", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+ /* Walk all sentinels. */
+ for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ /* Bail out of the heap is not used. */
+ if (Memory->sentinel[i].VidMem.next == gcvNULL)
+ {
+ break;
+ }
+
+ /* Walk all the nodes until we reach the sentinel. */
+ for (node = Memory->sentinel[i].VidMem.next;
+ node->VidMem.bytes != 0;
+ node = next)
+ {
+ /* Save pointer to the next node. */
+ next = node->VidMem.next;
+
+ /* Free the node. */
+ gcmkVERIFY_OK(gckOS_Free(Memory->os, node));
+ }
+ }
+
+ /* Free the mutex. */
+ gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex));
+
+ /* Mark the object as unknown. */
+ Memory->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckVIDMEM object. */
+ gcmkVERIFY_OK(gckOS_Free(Memory->os, Memory));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Allocate
+**
+** Allocate rectangular memory from the gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object.
+**
+** gctUINT Width
+** Width of rectangle to allocate. Make sure the width is properly
+** aligned.
+**
+** gctUINT Height
+** Height of rectangle to allocate. Make sure the height is properly
+** aligned.
+**
+** gctUINT Depth
+** Depth of rectangle to allocate. This equals to the number of
+** rectangles to allocate contiguously (i.e., for cubic maps and volume
+** textures).
+**
+** gctUINT BytesPerPixel
+** Number of bytes per pixel.
+**
+** gctUINT32 Alignment
+** Byte alignment for allocation.
+**
+** gceSURF_TYPE Type
+** Type of surface to allocate (use by bank optimization).
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that will hold the allocated memory node.
+*/
+gceSTATUS
+gckVIDMEM_Allocate(
+ IN gckVIDMEM Memory,
+ IN gctUINT Width,
+ IN gctUINT Height,
+ IN gctUINT Depth,
+ IN gctUINT BytesPerPixel,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gctSIZE_T bytes;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Memory=0x%x Width=%u Height=%u Depth=%u BytesPerPixel=%u "
+ "Alignment=%u Type=%d",
+ Memory, Width, Height, Depth, BytesPerPixel, Alignment,
+ Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+ gcmkVERIFY_ARGUMENT(Width > 0);
+ gcmkVERIFY_ARGUMENT(Height > 0);
+ gcmkVERIFY_ARGUMENT(Depth > 0);
+ gcmkVERIFY_ARGUMENT(BytesPerPixel > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+#ifdef __QNXNTO__
+ gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+ /* Compute linear size. */
+ bytes = Width * Height * Depth * BytesPerPixel;
+
+ /* Allocate through linear function. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Handle, Node));
+#else
+ gcmkONERROR(
+ gckVIDMEM_AllocateLinear(Memory, bytes, Alignment, Type, Node));
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+static gcuVIDMEM_NODE_PTR
+_FindNode(
+ IN gckVIDMEM Memory,
+ IN gctINT Bank,
+ IN gctSIZE_T Bytes,
+ IN OUT gctUINT32_PTR Alignment
+ )
+{
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+
+ /* Walk all free nodes until we have one that is big enough or we have
+ reached the sentinel. */
+ for (node = Memory->sentinel[Bank].VidMem.nextFree;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.nextFree)
+ {
+ /* Compute number of bytes to skip for alignment. */
+ alignment = (*Alignment == 0)
+ ? 0
+ : (*Alignment - (node->VidMem.offset % *Alignment));
+
+ if (alignment == *Alignment)
+ {
+ /* Node is already aligned. */
+ alignment = 0;
+ }
+
+ if (node->VidMem.bytes >= Bytes + alignment)
+ {
+ /* This node is big enough. */
+ *Alignment = alignment;
+ return node;
+ }
+ }
+
+ /* Not enough memory. */
+ return gcvNULL;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_AllocateLinear
+**
+** Allocate linear memory from the gckVIDMEM object.
+**
+** INPUT:
+**
+** gckVIDMEM Memory
+** Pointer to an gckVIDMEM object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** gctUINT32 Alignment
+** Byte alignment for allocation.
+**
+** gceSURF_TYPE Type
+** Type of surface to allocate (use by bank optimization).
+**
+** OUTPUT:
+**
+** gcuVIDMEM_NODE_PTR * Node
+** Pointer to a variable that will hold the allocated memory node.
+*/
+gceSTATUS
+gckVIDMEM_AllocateLinear(
+ IN gckVIDMEM Memory,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Alignment,
+ IN gceSURF_TYPE Type,
+#ifdef __QNXNTO__
+ IN gctHANDLE Handle,
+#endif
+ OUT gcuVIDMEM_NODE_PTR * Node
+ )
+{
+ gceSTATUS status;
+ gcuVIDMEM_NODE_PTR node;
+ gctUINT32 alignment;
+ gctINT bank, i;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
+ Memory, Bytes, Alignment, Type);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Node != gcvNULL);
+#ifdef __QNXNTO__
+ gcmkVERIFY_ARGUMENT(Handle != gcvNULL);
+#endif
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ if (Bytes > Memory->freeBytes)
+ {
+ /* Not enough memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Find the default bank for this surface type. */
+ gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
+ bank = Memory->mapping[Type];
+ alignment = Alignment;
+
+ /* Find a free node in the default bank. */
+ node = _FindNode(Memory, bank, Bytes, &alignment);
+
+ /* Out of memory? */
+ if (node == gcvNULL)
+ {
+ /* Walk all lower banks. */
+ for (i = bank - 1; i >= 0; --i)
+ {
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Memory, i, Bytes, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ /* Walk all upper banks. */
+ for (i = bank + 1; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ if (Memory->sentinel[i].VidMem.nextFree == gcvNULL)
+ {
+ /* Abort when we reach unused banks. */
+ break;
+ }
+
+ /* Find a free node inside the current bank. */
+ node = _FindNode(Memory, i, Bytes, &alignment);
+ if (node != gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ if (node == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Do we have an alignment? */
+ if (alignment > 0)
+ {
+ /* Split the node so it is aligned. */
+ if (_Split(Memory->os, node, alignment))
+ {
+ /* Successful split, move to aligned node. */
+ node = node->VidMem.next;
+
+ /* Remove alignment. */
+ alignment = 0;
+ }
+ }
+
+ /* Do we have enough memory after the allocation to split it? */
+ if (node->VidMem.bytes - Bytes > Memory->threshold)
+ {
+ /* Adjust the node size. */
+ _Split(Memory->os, node, Bytes);
+ }
+
+ /* Remove the node from the free list. */
+ node->VidMem.prevFree->VidMem.nextFree = node->VidMem.nextFree;
+ node->VidMem.nextFree->VidMem.prevFree = node->VidMem.prevFree;
+ node->VidMem.nextFree =
+ node->VidMem.prevFree = gcvNULL;
+
+ /* Fill in the information. */
+ node->VidMem.alignment = alignment;
+ node->VidMem.memory = Memory;
+#ifdef __QNXNTO__
+ node->VidMem.logical = gcvNULL;
+ node->VidMem.handle = Handle;
+#endif
+
+ /* Adjust the number of free bytes. */
+ Memory->freeBytes -= node->VidMem.bytes;
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+
+ /* Return the pointer to the node. */
+ *Node = node;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Allocated %u bytes @ 0x%x [0x%08X]",
+ node->VidMem.bytes, node, node->VidMem.offset);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Node=0x%x", *Node);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Free
+**
+** Free an allocated video memory node.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE object.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_Free(
+ IN gcuVIDMEM_NODE_PTR Node
+ )
+{
+ gckVIDMEM memory = gcvNULL;
+ gcuVIDMEM_NODE_PTR node;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ if (Node->VidMem.locked > 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
+ "Node 0x%x is locked (%d)",
+ Node, Node->VidMem.locked);
+
+ /* Node is locked. */
+ gcmkONERROR(gcvSTATUS_MEMORY_LOCKED);
+ }
+
+ /* Extract pointer to gckVIDMEM object owning the node. */
+ memory = Node->VidMem.memory;
+
+ /* Acquire the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+#ifdef __QNXNTO__
+ /* Reset handle to 0. */
+ Node->VidMem.logical = gcvNULL;
+ Node->VidMem.handle = 0;
+
+ /* Don't try to a re-free an already freed node. */
+ if ((Node->VidMem.nextFree == gcvNULL)
+ && (Node->VidMem.prevFree == gcvNULL)
+ )
+#endif
+ {
+ /* Update the number of free bytes. */
+ memory->freeBytes += Node->VidMem.bytes;
+
+ /* Find the next free node. */
+ for (node = Node->VidMem.next;
+ node->VidMem.nextFree == gcvNULL;
+ node = node->VidMem.next) ;
+
+ /* Insert this node in the free list. */
+ Node->VidMem.nextFree = node;
+ Node->VidMem.prevFree = node->VidMem.prevFree;
+
+ Node->VidMem.prevFree->VidMem.nextFree =
+ node->VidMem.prevFree = Node;
+
+ /* Is the next node a free node and not the sentinel? */
+ if ((Node->VidMem.next == Node->VidMem.nextFree)
+ && (Node->VidMem.next->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the next node. */
+ gcmkONERROR(_Merge(memory->os, node = Node));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+
+ /* Is the previous node a free node and not the sentinel? */
+ if ((Node->VidMem.prev == Node->VidMem.prevFree)
+ && (Node->VidMem.prev->VidMem.bytes != 0)
+ )
+ {
+ /* Merge this node with the previous node. */
+ gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev));
+ gcmkASSERT(node->VidMem.nextFree != node);
+ gcmkASSERT(node->VidMem.prevFree != node);
+ }
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ /* Verify the gckKERNEL object pointer. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+#ifdef __QNXNTO__
+ if (!Node->Virtual.unlockPending && (Node->Virtual.locked > 0))
+#else
+ if (!Node->Virtual.pending && (Node->Virtual.locked > 0))
+#endif
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM,
+ "gckVIDMEM_Free: Virtual node 0x%x is locked (%d)",
+ Node, Node->Virtual.locked);
+
+ /* Node is locked. */
+ gcmkONERROR(gcvSTATUS_MEMORY_LOCKED);
+ }
+
+#ifdef __QNXNTO__
+ if (!Node->Virtual.freePending) { if (Node->Virtual.unlockPending)
+#else
+ if (Node->Virtual.pending)
+#endif
+ {
+ gcmkASSERT(Node->Virtual.locked == 1);
+
+ /* Schedule the node to be freed. */
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "gckVIDMEM_Free: Scheduling node 0x%x to be freed later",
+ Node);
+
+ /* Schedule the video memory to be freed again. */
+ gcmkONERROR(gckEVENT_FreeVideoMemory(Node->Virtual.kernel->event,
+ Node,
+ gcvKERNEL_PIXEL));
+
+#ifdef __QNXNTO__
+ Node->Virtual.freePending = gcvTRUE; }
+#endif
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_SKIP;
+ }
+
+ else
+ {
+ /* Free the virtual memory. */
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(Node->Virtual.kernel->os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes));
+
+ /* Destroy the gcuVIDMEM_NODE union. */
+ gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+
+#ifdef __QNXNTO__
+/*******************************************************************************
+**
+** gcoVIDMEM_FreeHandleMemory
+**
+** Free all allocated video memory nodes for a handle.
+**
+** INPUT:
+**
+** gcoVIDMEM Memory
+** Pointer to an gcoVIDMEM object..
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckVIDMEM_FreeHandleMemory(
+ IN gckVIDMEM Memory,
+ IN gctHANDLE Handle
+ )
+{
+ gceSTATUS status;
+ gctBOOL mutex = gcvFALSE;
+ gcuVIDMEM_NODE_PTR node;
+ gctINT i;
+ gctUINT32 nodeCount = 0, byteCount = 0;
+ gctBOOL again;
+
+ gcmkHEADER_ARG("Memory=0x%x Handle=0x%x", Memory, Handle);
+
+ gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
+
+ gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
+ mutex = gcvTRUE;
+
+ /* Walk all sentinels. */
+ for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
+ {
+ /* Bail out of the heap if it is not used. */
+ if (Memory->sentinel[i].VidMem.next == gcvNULL)
+ {
+ break;
+ }
+
+ do
+ {
+ again = gcvFALSE;
+
+ /* Walk all the nodes until we reach the sentinel. */
+ for (node = Memory->sentinel[i].VidMem.next;
+ node->VidMem.bytes != 0;
+ node = node->VidMem.next)
+ {
+ /* Free the node if it was allocated by Handle. */
+ if (node->VidMem.handle == Handle)
+ {
+ /* Unlock video memory. */
+ while (gckVIDMEM_Unlock(node, gcvSURF_TYPE_UNKNOWN, gcvNULL, gcvNULL)
+ != gcvSTATUS_MEMORY_UNLOCKED)
+ ;
+
+ nodeCount++;
+ byteCount += node->VidMem.bytes;
+
+ /* Free video memory. */
+ gcmkVERIFY_OK(gckVIDMEM_Free(node, gcvNULL));
+
+ /*
+ * Freeing may cause a merge which will invalidate our iteration.
+ * Don't be clever, just restart.
+ */
+ again = gcvTRUE;
+
+ break;
+ }
+ }
+ }
+ while (again);
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ gcmkFOOTER();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (mutex)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
+ }
+
+ gcmkFOOTER();
+ return status;
+}
+#endif
+
+/*******************************************************************************
+**
+** gckVIDMEM_Lock
+**
+** Lock a video memory node and return it's hardware specific address.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a gcuVIDMEM_NODE union.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable that will hold the hardware specific address.
+*/
+gceSTATUS
+gckVIDMEM_Lock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ OUT gctUINT32 * Address
+ )
+{
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL locked = gcvFALSE;
+ gckOS os = gcvNULL;
+
+ gcmkHEADER_ARG("Node=0x%x", Node);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ /* Increment the lock count. */
+ Node->VidMem.locked ++;
+
+ /* Return the address of the node. */
+ *Address = Node->VidMem.memory->baseAddress
+ + Node->VidMem.offset
+ + Node->VidMem.alignment;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Locked node 0x%x (%d) @ 0x%08X",
+ Node,
+ Node->VidMem.locked,
+ *Address);
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+ /* Verify the gckKERNEL object pointer. */
+ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
+
+ /* Extract the gckOS object pointer. */
+ os = Node->Virtual.kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Grab the mutex. */
+ gcmkONERROR(gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ /* Increment the lock count. */
+ if (Node->Virtual.locked ++ == 0)
+ {
+ /* Is this node pending for a final unlock? */
+#ifdef __QNXNTO__
+ if (!Node->Virtual.contiguous && Node->Virtual.unlockPending)
+#else
+ if (!Node->Virtual.contiguous && Node->Virtual.pending)
+#endif
+ {
+ /* Make sure we have a page table. */
+ gcmkASSERT(Node->Virtual.pageTable != gcvNULL);
+
+ /* Remove pending unlock. */
+#ifdef __QNXNTO__
+ Node->Virtual.unlockPending = gcvFALSE;
+#else
+ Node->Virtual.pending = gcvFALSE;
+#endif
+ }
+
+ /* First lock - create a page table. */
+ gcmkASSERT(Node->Virtual.pageTable == gcvNULL);
+
+ /* Make sure we mark our node as not flushed. */
+#ifdef __QNXNTO__
+ Node->Virtual.unlockPending = gcvFALSE;
+#else
+ Node->Virtual.pending = gcvFALSE;
+#endif
+
+ /* Lock the allocated pages. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckOS_LockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ Node->Virtual.userPID,
+ &Node->Virtual.logical,
+ &Node->Virtual.pageCount));
+#else
+ gcmkONERROR(
+ gckOS_LockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ &Node->Virtual.logical,
+ &Node->Virtual.pageCount));
+#endif
+
+ locked = gcvTRUE;
+
+ if (Node->Virtual.contiguous)
+ {
+ /* Get physical address directly */
+ gcmkONERROR(gckOS_GetPhysicalAddress(os,
+ Node->Virtual.logical,
+ &Node->Virtual.address));
+ }
+ else
+ {
+ /* Allocate pages inside the MMU. */
+ gcmkONERROR(
+ gckMMU_AllocatePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageCount,
+ &Node->Virtual.pageTable,
+ &Node->Virtual.address));
+
+ /* Map the pages. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckOS_MapPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.logical,
+ Node->Virtual.pageCount,
+ Node->Virtual.pageTable));
+#else
+ gcmkONERROR(
+ gckOS_MapPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.pageCount,
+ Node->Virtual.pageTable));
+#endif
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Mapped virtual node 0x%x to 0x%08X",
+ Node,
+ Node->Virtual.address);
+ }
+ }
+
+ /* Return hardware address. */
+ *Address = Node->Virtual.address;
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Address=%08x", *Address);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (locked)
+ {
+ if (Node->Virtual.pageTable != gcvNULL)
+ {
+ /* Free the pages from the MMU. */
+ gcmkVERIFY_OK(
+ gckMMU_FreePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageTable,
+ Node->Virtual.pageCount));
+
+ Node->Virtual.pageTable = gcvNULL;
+ }
+
+ /* Unlock the pages. */
+#ifdef __QNXNTO__
+ gcmkVERIFY_OK(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.userPID,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+#else
+ gcmkVERIFY_OK(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+#endif
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckVIDMEM_Unlock
+**
+** Unlock a video memory node.
+**
+** INPUT:
+**
+** gcuVIDMEM_NODE_PTR Node
+** Pointer to a locked gcuVIDMEM_NODE union.
+**
+** gceSURF_TYPE Type
+** Type of surface to unlock.
+**
+** gctSIZE_T * CommandSize
+** Pointer to a variable specifying the number of bytes in the command
+** buffer specified by 'Commands'. If gcvNULL, there is no command
+** buffer and the video memory shoud be unlocked synchronously.
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable specifying whether the surface should be
+** unlocked asynchroneously or not.
+**
+** OUTPUT:
+**
+** gctBOOL * Asynchroneous
+** Pointer to a variable receiving the number of bytes used in the
+** command buffer specified by 'Commands'. If gcvNULL, there is no
+** command buffer.
+*/
+gceSTATUS
+gckVIDMEM_Unlock(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gceSURF_TYPE Type,
+ IN OUT gctBOOL * Asynchroneous
+ )
+{
+ gceSTATUS status;
+ gckKERNEL kernel;
+ gckHARDWARE hardware;
+ gctPOINTER buffer;
+ gctSIZE_T requested, bufferSize;
+ gckCOMMAND command = gcvNULL;
+ gceKERNEL_FLUSH flush;
+ gckOS os = gcvNULL;
+ gctBOOL acquired = gcvFALSE;
+ gctBOOL needRelease = gcvFALSE;
+ gctBOOL pendingUnlock = gcvFALSE;
+
+ gcmkHEADER_ARG("Node=0x%x Type=%d *Asynchroneous=%d",
+ Node, Type, gcmOPT_VALUE(Asynchroneous));
+
+ /* Verify the arguments. */
+ if ((Node == gcvNULL)
+ || (Node->VidMem.memory == gcvNULL)
+ )
+ {
+ /* Invalid object. */
+ gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
+ }
+
+ /**************************** Video Memory ********************************/
+
+ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ if (Node->VidMem.locked <= 0)
+ {
+ /* The surface was not locked. */
+ gcmkONERROR(gcvSTATUS_MEMORY_UNLOCKED);
+ }
+
+ /* Decrement the lock count. */
+ Node->VidMem.locked --;
+
+ if (Asynchroneous != gcvNULL)
+ {
+ /* No need for any events. */
+ *Asynchroneous = gcvFALSE;
+ }
+ }
+
+ /*************************** Virtual Memory *******************************/
+
+ else
+ {
+ /* Verify the gckKERNEL object pointer. */
+ kernel = Node->Virtual.kernel;
+ gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
+
+ /* Verify the gckHARDWARE object pointer. */
+ hardware = Node->Virtual.kernel->hardware;
+ gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+
+ /* Verify the gckCOMMAND object pointer. */
+ command = Node->Virtual.kernel->command;
+ gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
+
+ if (Asynchroneous == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "gckVIDMEM_Unlock: Unlocking virtual node 0x%x (%d)",
+ Node,
+ Node->Virtual.locked);
+
+ /* Get the gckOS object pointer. */
+ os = kernel->os;
+ gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
+
+ /* Grab the mutex. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(os, Node->Virtual.mutex, gcvINFINITE));
+
+ /* If we need to unlock a node from virtual memory we have to be
+ ** very carefull. If the node is still inside the caches we
+ ** might get a bus error later if the cache line needs to be
+ ** replaced. So - we have to flush the caches before we do
+ ** anything. We also need to stall to make sure the flush has
+ ** happened. However - when we get to this point we are inside
+ ** the interrupt handler and we cannot just gckCOMMAND_Wait
+ ** because it will wait forever. So - what we do here is we
+ ** verify the type of the surface, flush the appropriate cache,
+ ** mark the node as flushed, and issue another unlock to unmap
+ ** the MMU. */
+ if (!Node->Virtual.contiguous
+ && (Node->Virtual.locked == 1)
+#ifdef __QNXTO__
+ && !Node->Virtual.unlockPending
+#else
+ && !Node->Virtual.pending
+#endif
+ )
+ {
+ if (Type == gcvSURF_BITMAP)
+ {
+ /* Flush 2D cache. */
+ flush = gcvFLUSH_2D;
+ }
+ else if (Type == gcvSURF_RENDER_TARGET)
+ {
+ /* Flush color cache. */
+ flush = gcvFLUSH_COLOR;
+ }
+ else if (Type == gcvSURF_DEPTH)
+ {
+ /* Flush depth cache. */
+ flush = gcvFLUSH_DEPTH;
+ }
+ else
+ {
+ /* No flush required. */
+ flush = (gceKERNEL_FLUSH) 0;
+ }
+
+ gcmkONERROR(
+ gckHARDWARE_Flush(hardware, flush, gcvNULL, &requested));
+
+ if (requested != 0)
+ {
+ gcmkONERROR(
+ gckCOMMAND_Reserve(command,
+ requested,
+ &buffer,
+ &bufferSize));
+
+ needRelease = gcvTRUE;
+
+ gcmkONERROR(gckHARDWARE_Flush(hardware,
+ flush,
+ buffer,
+ &bufferSize));
+
+ gcmkONERROR(
+ gckEVENT_Unlock(Node->Virtual.kernel->event,
+ gcvKERNEL_PIXEL,
+ Node,
+ Type));
+
+ /* Mark node as pending. */
+#ifdef __QNXNTO__
+ Node->Virtual.unlockPending = gcvTRUE;
+#else
+ Node->Virtual.pending = gcvTRUE;
+#endif
+
+ needRelease = gcvFALSE;
+
+ gcmkONERROR(gckCOMMAND_Execute(command, requested));
+
+ pendingUnlock = gcvTRUE;
+ }
+ }
+
+ if (!pendingUnlock)
+ {
+ if (Node->Virtual.locked == 0)
+ {
+ status = gcvSTATUS_MEMORY_UNLOCKED;
+ goto OnError;
+ }
+
+ /* Decrement lock count. */
+ -- Node->Virtual.locked;
+
+ /* See if we can unlock the resources. */
+ if (Node->Virtual.locked == 0)
+ {
+ /* Unlock the pages. */
+#ifdef __QNXNTO__
+ gcmkONERROR(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.userPID,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+#else
+ gcmkONERROR(
+ gckOS_UnlockPages(os,
+ Node->Virtual.physical,
+ Node->Virtual.bytes,
+ Node->Virtual.logical));
+#endif
+
+ /* Free the page table. */
+ if (Node->Virtual.pageTable != gcvNULL)
+ {
+ gcmkONERROR(
+ gckMMU_FreePages(Node->Virtual.kernel->mmu,
+ Node->Virtual.pageTable,
+ Node->Virtual.pageCount));
+
+ /* Mark page table as freed. */
+ Node->Virtual.pageTable = gcvNULL;
+ }
+
+ /* Mark node as unlocked. */
+#ifdef __QNXTO
+ Node->Virtual.unlockPending = gcvFALSE;
+#else
+ Node->Virtual.pending = gcvFALSE;
+#endif
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Unmapped virtual node 0x%x from 0x%08X",
+ Node, Node->Virtual.address);
+ }
+
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
+ "Scheduled unlock for virtual node 0x%x",
+ Node);
+
+ /* Schedule the surface to be unlocked. */
+ *Asynchroneous = gcvTRUE;
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
+ return gcvSTATUS_OK;
+
+OnError:
+ if (needRelease)
+ {
+ gcmkVERIFY_OK(gckCOMMAND_Release(command));
+ }
+
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->Virtual.mutex));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+#ifdef __QNXNTO__
+/* Set the allocating process' PID for this node. */
+gceSTATUS
+gckVIDMEM_SetPID(
+ IN gcuVIDMEM_NODE_PTR Node,
+ IN gctUINT32 Pid
+ )
+{
+ if (Node != gcvNULL)
+ {
+ if (Node->VidMem.memory->object.type != gcvOBJ_VIDMEM)
+ {
+ Node->Virtual.userPID = Pid;
+ }
+
+ }
+ else
+ {
+ return gcvSTATUS_INVALID_OBJECT;
+ }
+
+ return gcvSTATUS_OK;
+}
+#endif
+
--- /dev/null
+##############################################################################
+#
+# Copyright (C) 2005 - 2010 by Vivante Corp.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the license, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+##############################################################################
+
+
+
+#
+# Linux build file for architecture dependent kernel HAL layer.
+#
+#
+
+
+################################################################################
+# Include common definitions.
+
+include $(AQROOT)/makefile.linux.def
+
+################################################################################
+# Define a shortcut for the main target.
+
+STATIC = 1
+TARGET_NAME = libhalkernel.a
+
+################################################################################
+# Supply additional include directories.
+
+INCLUDE += -I$(AQROOT)/hal/inc
+INCLUDE += -I$(AQROOT)/hal/user
+INCLUDE += -I$(AQARCH)/hal/kernel
+
+CFLAGS += $(INCLUDE) -Werror -ansi
+
+################################################################################
+# Describe object files.
+
+OBJECTS = $(OBJ_DIR)/gc_hal_kernel_command.o \
+ $(OBJ_DIR)/gc_hal_kernel_event.o \
+ $(OBJ_DIR)/gc_hal_kernel_heap.o \
+ $(OBJ_DIR)/gc_hal_kernel.o \
+ $(OBJ_DIR)/gc_hal_kernel_mmu.o \
+ $(OBJ_DIR)/gc_hal_kernel_video_memory.o
+
+include $(AQROOT)/common.target
--- /dev/null
+##############################################################################
+#
+# Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+#
+# The material in this file is confidential and contains trade secrets
+# of Vivante Corporation. This is proprietary information owned by
+# Vivante Corporation. No part of this work may be disclosed,
+# reproduced, copied, transmitted, or used in any way for any purpose,
+# without the express written permission of Vivante Corporation.
+#
+##############################################################################
+#
+# Auto-generated file on 10/12/2010. Do not edit!!!
+#
+##############################################################################
+
+
+
+#
+# Linux build file for the user level HAL libraries.
+#
+
+
+
+################################################################################
+# Define make command.
+
+MAKE = make --makefile=makefile.linux
+
+
+################################################################################
+# Define build directories.
+
+HAL_USER_DRV_ARCH := $(AQARCH)/hal/user
+ifeq ($(QNX), 1)
+HAL_USER_DRV_OS := $(AQROOT)/hal/os/qnx/user
+else
+HAL_USER_DRV_OS := $(AQROOT)/hal/os/linux/user
+endif
+HAL_USER_DRV_MAIN := $(AQROOT)/hal/user
+
+$(HAL_USER_DRV_MAIN): $(HAL_USER_DRV_ARCH) $(HAL_USER_DRV_OS)
+
+MODULES := $(HAL_USER_DRV_ARCH) $(HAL_USER_DRV_OS) $(HAL_USER_DRV_MAIN)
+MAIN_MODULE = $(HAL_USER_DRV_MAIN)
+
+include $(AQROOT)/common.node
--- /dev/null
+##############################################################################
+#
+# Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+#
+# The material in this file is confidential and contains trade secrets
+# of Vivante Corporation. This is proprietary information owned by
+# Vivante Corporation. No part of this work may be disclosed,
+# reproduced, copied, transmitted, or used in any way for any purpose,
+# without the express written permission of Vivante Corporation.
+#
+##############################################################################
+#
+# Auto-generated file on 10/12/2010. Do not edit!!!
+#
+##############################################################################
+
+
+"$(DEFFILE)" : $(AQROOT)\hal\os\libGAL.def.mak
+ @copy << "$(DEFFILE)"
+;
+; !! Do not edit this file - it is automatically generated !!
+;
+
+LIBRARY libGAL
+
+EXPORTS
+ ;gcoOS
+ gcoOS_SetDebugLevel
+ gcoOS_SetDebugZone
+ gcoOS_SetDebugFile
+ gcoOS_SetDebugZones
+ gcoOS_SetDebugLevelZone
+ gcoOS_SetDebugShaderFiles
+ gcoOS_DebugFatal
+ gcoOS_DebugTrace
+ gcoOS_DebugTraceZone
+ gcoOS_Print
+ gcoOS_DebugBreak
+ gcoOS_Verify
+ gcoOS_Construct
+ gcoOS_Destroy
+ gcoOS_QueryVideoMemory
+ gcoOS_Allocate
+ gcoOS_Free
+ gcoOS_AllocateNonPagedMemory
+ gcoOS_FreeNonPagedMemory
+ gcoOS_AllocateContiguous
+ gcoOS_FreeContiguous
+ gcoOS_CreateMutex
+ gcoOS_DeleteMutex
+ gcoOS_AcquireMutex
+ gcoOS_ReleaseMutex
+ gcoOS_CreateSignal
+ gcoOS_DestroySignal
+ gcoOS_Signal
+ gcoOS_WaitSignal
+ gcoOS_DeviceControl
+ gcoOS_Open
+ gcoOS_Close
+ gcoOS_Read
+ gcoOS_Write
+ gcoOS_Seek
+ gcoOS_SetPos
+ gcoOS_GetPos
+ gcoOS_MemCopy
+ gcoOS_ZeroMemory
+ gcoOS_MemFill
+ gcoOS_StrLen
+ gcoOS_StrFindReverse
+ gcoOS_StrCopySafe
+ gcoOS_StrCatSafe
+ gcoOS_StrCmp
+ gcoOS_StrNCmp
+ gcoOS_StrToFloat
+ gcoOS_StrToInt
+ gcoOS_MemCmp
+ gcoOS_PrintStrSafe
+ gcoOS_PrintStrVSafe
+ gcoOS_MapUserMemory
+ gcoOS_UnmapUserMemory
+ gcoOS_StrDup
+ gcoOS_LoadLibrary
+ gcoOS_FreeLibrary
+ gcoOS_GetProcAddress
+ gcoOS_Delay
+ gcoOS_GetCurrentProcessID
+ gcoOS_AtomConstruct
+ gcoOS_AtomDestroy
+ gcoOS_AtomIncrement
+ gcoOS_AtomDecrement
+ gcoOS_GetTicks
+ gcoOS_GetTime
+ gcoOS_GetCPUTime
+ gcoOS_GetMemoryUsage
+ gcoOS_GetBaseAddress
+ gcoOS_ReadRegister
+ gcoOS_WriteRegister
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcsMEM
+ gcfMEM_InitFSMemPool
+ gcfMEM_FreeFSMemPool
+ gcfMEM_FSMemPoolGetANode
+ gcfMEM_FSMemPoolFreeANode
+ gcfMEM_FSMemPoolFreeAList
+ gcfMEM_InitAFSMemPool
+ gcfMEM_FreeAFSMemPool
+ gcfMEM_AFSMemPoolGetANode
+ gcfMEM_AFSMemPoolFreeANode
+!ENDIF
+
+ ; gcoHAL
+ gcoHAL_Construct
+ gcoHAL_Destroy
+ gcoHAL_IsFeatureAvailable
+ gcoHAL_QueryChipIdentity
+ gcoHAL_Call
+ gcoHAL_QueryVideoMemory
+ gcoHAL_MapMemory
+ gcoHAL_UnmapMemory
+ gcoHAL_ScheduleUnmapMemory
+ gcoHAL_ScheduleUnmapUserMemory
+ gcoHAL_Commit
+ gcoHAL_QueryTiled
+ gcoHAL_Get2DEngine
+ gcoHAL_Get3DEngine
+ gcoHAL_GetVGEngine
+ gcoHAL_GetDump
+ gcoHAL_ScheduleEvent
+!IFNDEF VIVANTE_NO_3D
+ gcoHAL_QueryTargetCaps
+ gcoHAL_SetDepthOnly
+ gcoHAL_QueryShaderCaps
+ gcoHAL_QueryTextureCaps
+ gcoHAL_QueryStreamCaps
+!ENDIF
+ gcoHAL_ProfileStart
+ gcoHAL_ProfileEnd
+ gcoHAL_Compact
+ gcoHAL_SetPowerManagementState
+ gcoHAL_QueryPowerManagementState
+ gcoHAL_DestroySurface
+
+ ; gcoDUMP
+ gcoDUMP_Construct
+ gcoDUMP_Destroy
+ gcoDUMP_Control
+ gcoDUMP_IsEnabled
+ gcoDUMP_AddSurface
+ gcoDUMP_FrameBegin
+ gcoDUMP_FrameEnd
+ gcoDUMP_DumpData
+ gcoDUMP_Delete
+ gcfDump
+
+ ; gcoSURF
+ gcoSURF_Construct
+ gcoSURF_Destroy
+ gcoSURF_MapUserSurface
+ gcoSURF_GetSize
+ gcoSURF_GetAlignedSize
+ gcoSURF_GetFormat
+ gcoSURF_Lock
+ gcoSURF_Unlock
+ gcoSURF_Fill
+ gcoSURF_Blend
+ gcoSURF_SetClipping
+ gcoSURF_Clear2D
+ gcoSURF_Line
+ gcoSURF_Blit
+ gcoSURF_MonoBlit
+ gcoSURF_FilterBlit
+ gcoSURF_EnableAlphaBlend
+ gcoSURF_DisableAlphaBlend
+ gcoSURF_CopyPixels
+ gcoSURF_ReadPixel
+ gcoSURF_WritePixel
+ gcoSURF_QueryFormat
+ gcoSURF_Flush
+ gcoSURF_SetColorType
+ gcoSURF_GetColorType
+ gcoSURF_SetRotation
+ gcoSURF_ConstructWrapper
+ gcoSURF_SetBuffer
+ gcoSURF_SetWindow
+ gcoSURF_ReferenceSurface
+ gcoSURF_SetOrientation
+ gcoSURF_QueryOrientation
+ gcoSURF_QueryReferenceCount
+
+!IFNDEF VIVANTE_NO_3D
+ gcoSURF_IsTileStatusSupported
+ gcoSURF_EnableTileStatus
+ gcoSURF_DisableTileStatus
+ gcoSURF_SetSamples
+ gcoSURF_GetSamples
+ gcoSURF_Copy
+ gcoSURF_Clear
+ gcoSURF_ClearRect
+ gcoSURF_Resample
+ gcoSURF_Resolve
+ gcoSURF_ResolveRect
+ depr_gcoSURF_Resolve
+ depr_gcoSURF_ResolveRect
+ gcoSURF_SetResolvability
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcoINDEX
+ gcoINDEX_Construct
+ gcoINDEX_Destroy
+ gcoINDEX_Lock
+ gcoINDEX_Unlock
+ gcoINDEX_Load
+ gcoINDEX_Bind
+ gcoINDEX_BindOffset
+ gcoINDEX_Free
+ gcoINDEX_Upload
+ gcoINDEX_UploadOffset
+ gcoINDEX_QueryCaps
+ gcoINDEX_GetIndexRange
+ gcoINDEX_SetDynamic
+ gcoINDEX_UploadDynamic
+!ENDIF
+
+ ; gco2D
+ gco2D_Construct
+ gco2D_Destroy
+ gco2D_SetBrushLimit
+ gco2D_FlushBrush
+ gco2D_LoadSolidBrush
+ gco2D_SetMonochromeSource
+ gco2D_SetColorSource
+ gco2D_SetColorSourceEx
+ gco2D_SetColorSourceAdvanced
+ gco2D_SetMaskedSource
+ gco2D_SetMaskedSourceEx
+ gco2D_SetSource
+ gco2D_SetClipping
+ gco2D_SetTarget
+ gco2D_SetTargetEx
+ gco2D_SetStretchFactors
+ gco2D_SetStretchRectFactors
+ gco2D_ConstructSingleColorBrush
+ gco2D_ConstructMonochromeBrush
+ gco2D_ConstructColorBrush
+ gco2D_Clear
+ gco2D_Line
+ gco2D_ColorLine
+ gco2D_Blit
+ gco2D_BatchBlit
+ gco2D_StretchBlit
+ gco2D_MonoBlit
+ gco2D_SetKernelSize
+ gco2D_SetFilterType
+ gco2D_SetUserFilterKernel
+ gco2D_EnableUserFilterPasses
+ gco2D_FreeFilterBuffer
+ gco2D_FilterBlit
+ gco2D_FilterBlitEx
+ gco2D_EnableAlphaBlend
+ gco2D_EnableAlphaBlendAdvanced
+ gco2D_SetPorterDuffBlending
+ gco2D_DisableAlphaBlend
+ gco2D_GetPackSize
+ gco2D_Flush
+ gco2D_LoadPalette
+ gco2D_SetBitBlitMirror
+ gco2D_SetTransparencyAdvanced
+ gco2D_SetSourceColorKeyAdvanced
+ gco2D_SetSourceColorKeyRangeAdvanced
+ gco2D_SetTargetColorKeyAdvanced
+ gco2D_SetTargetColorKeyRangeAdvanced
+ gco2D_SetYUVColorMode
+ gco2D_SetSourceGlobalColorAdvanced
+ gco2D_SetTargetGlobalColorAdvanced
+ gco2D_SetPixelMultiplyModeAdvanced
+ gco2D_SetAutoFlushCycles
+ gco2D_ProfileEngine
+ gco2D_GetMaximumDataCount
+
+
+!IFNDEF VIVANTE_NO_3D
+ gco3D_Construct
+ gco3D_Destroy
+ gco3D_SetAPI
+ gco3D_SetTarget
+ gco3D_SetDepth
+ gco3D_SetViewport
+ gco3D_SetScissors
+ gco3D_SetClearColor
+ gco3D_SetClearColorX
+ gco3D_SetClearColorF
+ gco3D_SetClearDepthX
+ gco3D_SetClearDepthF
+ gco3D_SetClearStencil
+ gco3D_Clear
+ gco3D_ClearRect
+ gco3D_ClearTileStatus
+ gco3D_ClearHzTileStatus
+ gco3D_SetShading
+ gco3D_EnableBlending
+ gco3D_SetBlendFunction
+ gco3D_SetBlendMode
+ gco3D_SetBlendColor
+ gco3D_SetBlendColorX
+ gco3D_SetBlendColorF
+ gco3D_SetCulling
+ gco3D_SetPointSizeEnable
+ gco3D_SetPointSprite
+ gco3D_SetFill
+ gco3D_SetDepthCompare
+ gco3D_EnableDepthWrite
+ gco3D_SetDepthRangeX
+ gco3D_SetDepthMode
+ gco3D_SetDepthRangeF
+ gco3D_SetLastPixelEnable
+ gco3D_SetDepthScaleBiasX
+ gco3D_SetDepthScaleBiasF
+ gco3D_EnableDither
+ gco3D_SetColorWrite
+ gco3D_SetEarlyDepth
+ gco3D_SetDepthOnly
+ gco3D_SetStencilMode
+ gco3D_SetStencilMask
+ gco3D_SetStencilWriteMask
+ gco3D_SetStencilReference
+ gco3D_SetStencilCompare
+ gco3D_SetStencilPass
+ gco3D_SetStencilFail
+ gco3D_SetStencilDepthFail
+ gco3D_SetAlphaTest
+ gco3D_SetAlphaCompare
+ gco3D_SetAlphaReference
+ gco3D_SetAlphaReferenceX
+ gco3D_SetAlphaReferenceF
+ gco3D_SetAntiAliasLine
+ gco3D_SetAALineTexSlot
+ gco3D_SetAALineWidth
+ gco3D_DrawPrimitives
+ gco3D_DrawPrimitivesOffset
+ gco3D_DrawIndexedPrimitives
+ gco3D_DrawIndexedPrimitivesOffset
+ gco3D_SetAntiAlias
+ gco3D_WriteBuffer
+ gco3D_SetFragmentConfiguration
+ gco3D_EnableTextureStage
+ gco3D_SetTextureColorMask
+ gco3D_SetTextureAlphaMask
+ gco3D_SetFragmentColorX
+ gco3D_SetFragmentColorF
+ gco3D_SetFogColorX
+ gco3D_SetFogColorF
+ gco3D_SetTetxureColorX
+ gco3D_SetTetxureColorF
+ gco3D_SetColorTextureFunction
+ gco3D_SetAlphaTextureFunction
+ gco3D_Semaphore
+ gco3D_SetCentroids
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcoTEXTURE
+ gcoTEXTURE_Construct
+ gcoTEXTURE_ConstructSized
+ gcoTEXTURE_Destroy
+ gcoTEXTURE_Upload
+ gcoTEXTURE_UploadSub
+ gcoTEXTURE_UploadCompressed
+ gcoTEXTURE_GetMipMap
+ gcoTEXTURE_GetMipMapFace
+ gcoTEXTURE_AddMipMap
+ gcoTEXTURE_AddMipMapFromClient
+ gcoTEXTURE_AddMipMapFromSurface
+ gcoTEXTURE_SetEndianHint
+ gcoTEXTURE_SetAddressingMode
+ gcoTEXTURE_SetBorderColor
+ gcoTEXTURE_SetBorderColorX
+ gcoTEXTURE_SetBorderColorF
+ gcoTEXTURE_SetMinFilter
+ gcoTEXTURE_SetMagFilter
+ gcoTEXTURE_SetMipFilter
+ gcoTEXTURE_SetLODBiasX
+ gcoTEXTURE_SetLODBiasF
+ gcoTEXTURE_SetLODMinX
+ gcoTEXTURE_SetLODMinF
+ gcoTEXTURE_SetLODMaxX
+ gcoTEXTURE_SetLODMaxF
+ gcoTEXTURE_Bind
+ gcoTEXTURE_Flush
+ gcoTEXTURE_QueryCaps
+ gcoTEXTURE_GetClosestFormat
+ gcoTEXTURE_Disable
+ gcoTEXTURE_RenderIntoMipMap
+ gcoTEXTURE_IsRenderable
+ gcoTEXTURE_IsComplete
+!ENDIF
+
+ ; gcsRECT
+ gcsRECT_Height
+ gcsRECT_Width
+ gcsRECT_Set
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcoHARDWARE
+ gcoHARDWARE_QueryTextureCaps
+ gcoHARDWARE_QueryShaderCaps
+ gcoHARDWARE_QueryIndexCaps
+ gcoHARDWARE_QueryStreamCaps
+!ENDIF
+
+ ; gcoBRUSH
+ gcoBRUSH_Destroy
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcSHADER
+ gcOptimizeShader
+ gcLinkShaders
+ gcLoadShaders
+ gcSaveProgram
+ gcSHADER_Construct
+ gcSHADER_Destroy
+ gcSHADER_AddUniform
+ gcSHADER_AddSource
+ gcSHADER_AddSourceAttributeIndexed
+ gcSHADER_AddSourceUniformIndexed
+ gcSHADER_AddSourceSamplerIndexed
+ gcSHADER_AddOpcodeIndexed
+ gcSHADER_AddSourceIndexed
+ gcSHADER_AddAttribute
+ gcSHADER_AddOutput
+ gcSHADER_AddOutputIndexed
+ gcSHADER_AddSourceAttribute
+ gcSHADER_AddSourceConstant
+ gcSHADER_AddSourceUniform
+ gcSHADER_AddLabel
+ gcSHADER_AddOpcode
+ gcSHADER_AddOpcode2
+ gcSHADER_AddOpcodeConditional
+ gcSHADER_AddVariable
+ gcSHADER_Pack
+ gcSHADER_Load
+ gcSHADER_Save
+ gcSHADER_GetUniform
+ gcSHADER_GetUniformCount
+ gcSHADER_GetAttribute
+ gcSHADER_GetAttributeCount
+ gcSHADER_GetPositionAttribute
+ gcSHADER_GetVariable
+ gcSHADER_GetVariableCount
+ gcSHADER_AddFunction
+ gcSHADER_BeginFunction
+ gcSHADER_EndFunction
+ gcSHADER_SetOptimizationOption
+ gcSHADER_GetPositionAttribute
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcATTRIBUTE
+ gcATTRIBUTE_GetName
+ gcATTRIBUTE_GetType
+ gcATTRIBUTE_IsEnabled
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcFUNCTION
+ gcFUNCTION_AddArgument
+ gcFUNCTION_GetArgument
+ gcFUNCTION_GetLabel
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcUNIFORM
+ gcUNIFORM_GetName
+ gcUNIFORM_GetType
+ gcUNIFORM_GetSampler
+ gcUNIFORM_SetValue
+ gcUNIFORM_SetValueX
+ gcUNIFORM_SetValueF
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcoSTREAM
+ gcoSTREAM_Construct
+ gcoSTREAM_Destroy
+ gcoSTREAM_Upload
+ gcoSTREAM_SetStride
+ gcoSTREAM_Lock
+ gcoSTREAM_Unlock
+ gcoSTREAM_Reserve
+ gcoSTREAM_Flush
+ gcoSTREAM_SetDynamic
+ gcoSTREAM_UploadDynamic
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcoVERTEX
+ gcoVERTEX_Construct
+ gcoVERTEX_Destroy
+ gcoVERTEX_Reset
+ gcoVERTEX_EnableAttribute
+ gcoVERTEX_DisableAttribute
+ gcoVERTEX_Bind
+!ENDIF
+
+!IFNDEF VIVANTE_NO_3D
+ ; gcoBUFFER
+ gcoBUFFER_Construct
+ gcoBUFFER_Destroy
+ gcoBUFFER_Reserve
+ gcoBUFFER_Write
+ gcoBUFFER_Commit
+!ENDIF
+
+!IFNDEF VIVANTE_NO_PROFILER
+ ; gcoPROFILER
+ ;gcoPROFILER_Initialize
+ ;gcoPROFILER_Destroy
+ ;gcoPROFILER_EndFrame
+ ;gcoPROFILER_ShaderFS
+ ;gcoPROFILER_ShaderVS
+!ENDIF
+
+ ; gcoMATH
+ gcoMATH_Log2in5dot5
+ gcoMATH_Sine
+ gcoMATH_Cosine
+ gcoMATH_Floor
+ gcoMATH_Ceiling
+ gcoMATH_SquareRoot
+ gcoMATH_Log2
+ gcoMATH_Power
+ gcoMATH_Modulo
+ gcoMATH_ArcCosine
+ gcoMATH_Absolute
+ gcoMATH_Exp
+ gcoMATH_UInt2Float
+ gcoMATH_Float2UInt
+ gcoMATH_Multiply
+<<
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+#include "linux/spinlock.h"
+#include <stdarg.h>
+
+/*
+ gcdBUFFERED_OUTPUT
+
+ When set to non-zero, all output is collected into a buffer with the
+ specified size. Once the buffer gets full, or the token "$$FLUSH$$" has
+ been received, the debug buffer will be printed to the console.
+*/
+#define gcdBUFFERED_OUTPUT 0
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_WARNING;
+static gctUINT32 _debugZones = gcvZONE_ALL;
+static gctINT _indent = 0;
+static spinlock_t _lock = SPIN_LOCK_UNLOCKED;
+
+static void
+OutputDebugString(
+ IN gctCONST_STRING String
+ )
+{
+#if gcdBUFFERED_OUTPUT
+ static gctCHAR outputBuffer[gcdBUFFERED_OUTPUT];
+ static gctINT outputBufferIndex = 0;
+ gctINT n, i;
+
+ n = (String != gcvNULL) ? strlen(String) + 1 : 0;
+
+ if ((n == 0) || (outputBufferIndex + n > gcmSIZEOF(outputBuffer)))
+ {
+ for (i = 0; i < outputBufferIndex; i += strlen(outputBuffer + i) + 1)
+ {
+ printk(outputBuffer + i);
+ }
+
+ outputBufferIndex = 0;
+ }
+
+ if (n > 0)
+ {
+ memcpy(outputBuffer + outputBufferIndex, String, n);
+ outputBufferIndex += n;
+ }
+#else
+ if (String != gcvNULL)
+ {
+ printk(String);
+ }
+#endif
+}
+
+static void
+_Print(
+ IN gctCONST_STRING Message,
+ IN va_list Arguments
+ )
+{
+ char buffer[1024];
+ int i, n;
+
+ if (strcmp(Message, "$$FLUSH$$") == 0)
+ {
+ spin_lock(&_lock);
+ {
+ OutputDebugString(gcvNULL);
+ }
+ spin_unlock(&_lock);
+ return;
+ }
+
+ if (strncmp(Message, "--", 2) == 0)
+ {
+ if (_indent == 0)
+ {
+ printk("ERROR: _indent=0\n");
+ }
+
+ _indent -= 2;
+ }
+
+ for (i = 0; i < _indent; ++i)
+ {
+ buffer[i] = ' ';
+ }
+
+ /* Print message to buffer. */
+ n = vsnprintf(buffer + i, sizeof(buffer) - i, Message, Arguments);
+ if ((n <= 0) || (buffer[i + n - 1] != '\n'))
+ {
+ /* Append new-line. */
+ strncat(buffer, "\n", sizeof(buffer));
+ }
+
+ /* Output to debugger. */
+ spin_lock(&_lock);
+ {
+ OutputDebugString(buffer);
+ }
+ spin_unlock(&_lock);
+
+ if (strncmp(Message, "++", 2) == 0)
+ {
+ _indent += 2;
+ }
+}
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#define _DEBUGPRINT(Message) \
+{ \
+ va_list arguments; \
+ \
+ va_start(arguments, Message); \
+ _Print(Message, arguments); \
+ va_end(arguments); \
+}
+
+/******************************************************************************\
+********************************** Debug Code **********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Print
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTrace
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZone
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugBreak
+**
+** Break into the debugger.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugBreak(
+ void
+ )
+{
+ gckOS_DebugTrace(gcvLEVEL_ERROR, "gckOS_DebugBreak");
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFatal
+**
+** Send a message to the debugger and break into the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ _DEBUGPRINT(Message);
+
+ /* Break into the debugger. */
+ gckOS_DebugBreak();
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevel
+**
+** Set the debug level.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ )
+{
+ _debugLevel = Level;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZone
+**
+** Set the debug zone.
+**
+** INPUT:
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ )
+{
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevelZone
+**
+** Set the debug level and zone.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ )
+{
+ _debugLevel = Level;
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZones
+**
+** Enable or disable debug zones.
+**
+** INPUT:
+**
+** gctUINT32 Zones
+** Debug zones to enable or disable.
+**
+** gctBOOL Enable
+** Set to gcvTRUE to enable the zones (or the Zones with the current
+** zones) or gcvFALSE to disable the specified Zones.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ )
+{
+ if (Enable)
+ {
+ /* Enable the zones. */
+ _debugZones |= Zones;
+ }
+ else
+ {
+ /* Disable the zones. */
+ _debugZones &= ~Zones;
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_Verify
+**
+** Called to verify the result of a function call.
+**
+** INPUT:
+**
+** gceSTATUS Status
+** Function call result.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Verify(
+ IN gceSTATUS Status
+ )
+{
+ _lastError = Status;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+
+#define _GC_OBJ_ZONE gcvZONE_DEVICE
+
+#ifdef FLAREON
+static struct dove_gpio_irq_handler gc500_handle;
+#endif
+
+/******************************************************************************\
+******************************** gckGALDEVICE Code *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckGALDEVICE_AllocateMemory(
+ IN gckGALDEVICE Device,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPHYS_ADDR *Physical,
+ OUT gctUINT32 *PhysAddr
+ )
+{
+ gceSTATUS status;
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
+
+ status = gckOS_AllocateContiguous(Device->os,
+ gcvFALSE,
+ &Bytes,
+ Physical,
+ Logical);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "gckGALDEVICE_AllocateMemory: error status->0x%x",
+ status);
+
+ return status;
+ }
+
+ *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle - Device->baseAddress;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "gckGALDEVICE_AllocateMemory: phys_addr->0x%x phsical->0x%x Logical->0x%x",
+ (gctUINT32)*Physical,
+ (gctUINT32)*PhysAddr,
+ (gctUINT32)*Logical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_FreeMemory(
+ IN gckGALDEVICE Device,
+ IN gctPOINTER Logical,
+ IN gctPHYS_ADDR Physical)
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ return gckOS_FreeContiguous(Device->os,
+ Physical,
+ Logical,
+ ((PLINUX_MDL)Physical)->numPages*PAGE_SIZE);
+}
+
+irqreturn_t isrRoutine(int irq, void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+ int handled = 0;
+
+ /* Call kernel interrupt notification. */
+ if (gckKERNEL_Notify(device->kernel,
+ gcvNOTIFY_INTERRUPT,
+ gcvTRUE) == gcvSTATUS_OK)
+ {
+ device->dataReady = gcvTRUE;
+
+ up(&device->sema);
+
+ handled = 1;
+ }
+
+ return IRQ_RETVAL(handled);
+}
+
+int threadRoutine(void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Starting isr Thread with extension->%p",
+ device);
+
+ for (;;)
+ {
+ static int down;
+
+ down = down_interruptible(&device->sema);
+ device->dataReady = gcvFALSE;
+
+ if (device->killThread == gcvTRUE)
+ {
+ /* The daemon exits. */
+ while (!kthread_should_stop())
+ {
+ gckOS_Delay(device->os, 1);
+ }
+
+ return 0;
+ }
+ else
+ {
+ gckKERNEL_Notify(device->kernel, gcvNOTIFY_INTERRUPT, gcvFALSE);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Setup_ISR
+**
+** Start the ISR routine.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Setup successfully.
+** gcvSTATUS_GENERIC_IO
+** Setup failed.
+*/
+gceSTATUS
+gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ gctINT ret;
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->irqLine == 0)
+ {
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* Hook up the isr based on the irq line. */
+#ifdef FLAREON
+ gc500_handle.dev_name = "galcore interrupt service";
+ gc500_handle.dev_id = Device;
+ gc500_handle.handler = isrRoutine;
+ gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
+ gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
+ ret = dove_gpio_request (DOVE_GPIO0_7, &gc500_handle);
+#else
+ ret = request_irq(Device->irqLine,
+ isrRoutine,
+ IRQF_DISABLED,
+ "galcore interrupt service",
+ Device);
+#endif
+
+
+ if (ret != 0) {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Setup_ISR: "
+ "Could not register irq line->%d",
+ Device->irqLine);
+
+ Device->isrInitialized = gcvFALSE;
+
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ Device->isrInitialized = gcvTRUE;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Setup_ISR: "
+ "Setup the irq line->%d",
+ Device->irqLine);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Release_ISR
+**
+** Release the irq line.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* release the irq */
+ if (Device->isrInitialized)
+ {
+#ifdef FLAREON
+ dove_gpio_free (DOVE_GPIO0_7, "galcore interrupt service");
+#else
+ free_irq(Device->irqLine, Device);
+#endif
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start_Thread
+**
+** Start the daemon thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+** gcvSTATUS_GENERIC_IO
+** Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Thread(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* start the kernel thread */
+ Device->threadCtxt = kthread_run(threadRoutine,
+ Device,
+ "galcore daemon thread");
+
+ Device->threadInitialized = gcvTRUE;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Start_Thread: "
+ "Start the daemon thread.");
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop_Thread
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop_Thread(
+ gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* stop the thread */
+ if (Device->threadInitialized)
+ {
+ Device->killThread = gcvTRUE;
+ up(&Device->sema);
+
+ kthread_stop(Device->threadCtxt);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start
+**
+** Start the gal device, including the following actions: setup the isr routine
+** and start the daemoni thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+*/
+gceSTATUS
+gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ )
+{
+ /* start the daemon thread */
+ gcmkVERIFY_OK(gckGALDEVICE_Start_Thread(Device));
+
+ /* setup the isr routine */
+ gcmkVERIFY_OK(gckGALDEVICE_Setup_ISR(Device));
+
+ /* Switch to SUSPEND power state. */
+ gcmkVERIFY_OK(
+ gckHARDWARE_SetPowerManagementState(Device->kernel->hardware,
+ gcvPOWER_SUSPEND_ATPOWERON));
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* Switch to ON power state. */
+ gcmkVERIFY_OK(
+ gckHARDWARE_SetPowerManagementState(Device->kernel->hardware,
+ gcvPOWER_ON));
+
+ if (Device->isrInitialized)
+ {
+ gckGALDEVICE_Release_ISR(Device);
+ }
+
+ if (Device->threadInitialized)
+ {
+ gckGALDEVICE_Stop_Thread(Device);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Construct
+**
+** Constructor.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gckGALDEVICE * Device
+** Pointer to a variable receiving the gckGALDEVICE object pointer on
+** success.
+*/
+gceSTATUS
+gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 BaseAddress,
+ IN gctINT Signal,
+ OUT gckGALDEVICE *Device
+ )
+{
+ gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
+ gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
+ gctUINT32 horizontalTileSize, verticalTileSize;
+ gctUINT32 physAddr;
+ gctUINT32 physical;
+ gckGALDEVICE device;
+ gceSTATUS status;
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Enter gckGALDEVICE_Construct");
+
+ /* Allocate device structure. */
+ device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL);
+ if (!device)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Can't allocate memory.");
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ memset(device, 0, sizeof(struct _gckGALDEVICE));
+
+ physical = RegisterMemBase;
+
+ /* Set up register memory region */
+ if (physical != 0)
+ {
+ /* Request a region. */
+ request_mem_region(RegisterMemBase, RegisterMemSize, "galcore register region");
+ device->registerBase = (gctPOINTER) ioremap_nocache(RegisterMemBase,
+ RegisterMemSize);
+ if (!device->registerBase)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Unable to map location->0x%lX for size->%ld",
+ RegisterMemBase,
+ RegisterMemSize);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ physical += RegisterMemSize;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: "
+ "RegisterBase after mapping Address->0x%x is 0x%x",
+ (gctUINT32)RegisterMemBase,
+ (gctUINT32)device->registerBase);
+ }
+
+ /* construct the gckOS object */
+ device->baseAddress = BaseAddress;
+ gcmkVERIFY_OK(gckOS_Construct(device, &device->os));
+
+ /* construct the gckKERNEL object. */
+ gcmkVERIFY_OK(gckKERNEL_Construct(device->os, device, &device->kernel));
+
+ gcmkVERIFY_OK(gckHARDWARE_SetFastClear(device->kernel->hardware,
+ FastClear,
+ Compression));
+
+ /* query the ceiling of the system memory */
+ gcmkVERIFY_OK(gckHARDWARE_QuerySystemMemory(device->kernel->hardware,
+ &device->systemMemorySize,
+ &device->systemMemoryBaseAddress));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: "
+ "Will be trying to allocate contiguous memory of 0x%x bytes",
+ (gctUINT32)device->systemMemoryBaseAddress);
+
+#if COMMAND_PROCESSOR_VERSION == 1
+ /* start the command queue */
+ gcmkVERIFY_OK(gckCOMMAND_Start(device->kernel->command));
+#endif
+
+ /* initialize the thread daemon */
+ sema_init(&device->sema, 0);
+
+ device->threadInitialized = gcvFALSE;
+ device->killThread = gcvFALSE;
+
+ /* initialize the isr */
+ device->isrInitialized = gcvFALSE;
+ device->dataReady = gcvFALSE;
+ device->irqLine = IrqLine;
+
+ device->signal = Signal;
+
+ /* query the amount of video memory */
+ gcmkVERIFY_OK(gckHARDWARE_QueryMemory(device->kernel->hardware,
+ &device->internalSize,
+ &internalBaseAddress,
+ &internalAlignment,
+ &device->externalSize,
+ &externalBaseAddress,
+ &externalAlignment,
+ &horizontalTileSize,
+ &verticalTileSize));
+
+ /* set up the internal memory region */
+ if (device->internalSize > 0)
+ {
+ gceSTATUS status = gckVIDMEM_Construct(device->os,
+ internalBaseAddress,
+ device->internalSize,
+ internalAlignment,
+ 0,
+ &device->internalVidMem);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* error, remove internal heap */
+ device->internalSize = 0;
+ }
+ else
+ {
+ /* map internal memory */
+ device->internalPhysical = (gctPHYS_ADDR)physical;
+ device->internalLogical = (gctPOINTER)ioremap_nocache(
+ physical, device->internalSize);
+
+ gcmkASSERT(device->internalLogical != NULL);
+
+ physical += device->internalSize;
+ }
+ }
+
+ if (device->externalSize > 0)
+ {
+ /* create the external memory heap */
+ gceSTATUS status = gckVIDMEM_Construct(device->os,
+ externalBaseAddress,
+ device->externalSize,
+ externalAlignment,
+ 0,
+ &device->externalVidMem);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* error, remove internal heap */
+ device->externalSize = 0;
+ }
+ else
+ {
+ /* map internal memory */
+ device->externalPhysical = (gctPHYS_ADDR)physical;
+ device->externalLogical = (gctPOINTER)ioremap_nocache(
+ physical, device->externalSize);
+
+ gcmkASSERT(device->externalLogical != NULL);
+
+ physical += device->externalSize;
+ }
+ }
+
+ /* set up the contiguous memory */
+ device->contiguousSize = ContiguousSize;
+
+ if (ContiguousBase == 0)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+
+ while (device->contiguousSize > 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Will be trying to allocate contiguous memory of %ld bytes",
+ device->contiguousSize
+ );
+
+ /* allocate contiguous memory */
+ status = gckGALDEVICE_AllocateMemory(
+ device,
+ device->contiguousSize,
+ &device->contiguousBase,
+ &device->contiguousPhysical,
+ &physAddr
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Contiguous allocated size->0x%08X Virt->0x%08lX physAddr->0x%08X",
+ device->contiguousSize,
+ device->contiguousBase,
+ physAddr
+ );
+
+ status = gckVIDMEM_Construct(
+ device->os,
+ physAddr | device->systemMemoryBaseAddress,
+ device->contiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ device->contiguousMapped = gcvFALSE;
+
+ /* success, abort loop */
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Using %u bytes of contiguous memory.",
+ device->contiguousSize
+ );
+
+ break;
+ }
+
+ gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(
+ device,
+ device->contiguousBase,
+ device->contiguousPhysical
+ ));
+
+ device->contiguousBase = NULL;
+ }
+
+ if (device->contiguousSize <= (4 << 20))
+ {
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ device->contiguousSize -= (4 << 20);
+ }
+ }
+ }
+ else
+ {
+ /* Create the contiguous memory heap. */
+ status = gckVIDMEM_Construct(
+ device->os,
+ (ContiguousBase - device->baseAddress) | device->systemMemoryBaseAddress,
+ ContiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, roll back. */
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ /* Map the contiguous memory. */
+ request_mem_region(
+ ContiguousBase,
+ ContiguousSize,
+ "galcore managed memory"
+ );
+
+ device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
+ device->contiguousSize = ContiguousSize;
+ device->contiguousBase = (gctPOINTER) ioremap_nocache(ContiguousBase, ContiguousSize);
+ device->contiguousMapped = gcvTRUE;
+
+ if (device->contiguousBase == gcvNULL)
+ {
+ /* Error, roll back. */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(device->contiguousVidMem));
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ }
+ }
+ }
+
+ *Device = device;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Initialized device->%p contiguous->%lu @ %p (0x%08X)",
+ device,
+ device->contiguousSize,
+ device->contiguousBase,
+ device->contiguousPhysical);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Destroy
+**
+** Class destructor.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+ gckGALDEVICE Device)
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[ENTER] gckGALDEVICE_Destroy");
+
+ /* Destroy the gckKERNEL object. */
+ gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernel));
+
+ if (Device->internalVidMem != gcvNULL)
+ {
+ /* destroy the internal heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+
+ /* unmap the internal memory */
+ iounmap(Device->internalLogical);
+ }
+
+ if (Device->externalVidMem != gcvNULL)
+ {
+ /* destroy the internal heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+
+ /* unmap the external memory */
+ iounmap(Device->externalLogical);
+ }
+
+ if (Device->contiguousVidMem != gcvNULL)
+ {
+ /* Destroy the contiguous heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+
+ if (Device->contiguousMapped)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Destroy: "
+ "Unmapping contiguous memory->0x%08lX",
+ Device->contiguousBase);
+
+ iounmap(Device->contiguousBase);
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Destroy: "
+ "Freeing contiguous memory->0x%08lX",
+ Device->contiguousBase);
+
+ gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(Device,
+ Device->contiguousBase,
+ Device->contiguousPhysical));
+ }
+ }
+
+ if (Device->registerBase)
+ {
+ iounmap(Device->registerBase);
+ }
+
+ /* Destroy the gckOS object. */
+ gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+
+ kfree(Device);
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Leave gckGALDEVICE_Destroy");
+
+ return gcvSTATUS_OK;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_device_h_
+#define __gc_hal_kernel_device_h_
+
+#define gcdkUSE_MEMORY_RECORD 1
+
+#ifdef ANDROID
+#define gcdkREPORT_VIDMEM_LEAK 0
+#else
+#define gcdkREPORT_VIDMEM_LEAK 1
+#endif
+
+/******************************************************************************\
+******************************* gckGALDEVICE Structure *******************************
+\******************************************************************************/
+
+typedef struct _gckGALDEVICE
+{
+ /* Objects. */
+ gckOS os;
+ gckKERNEL kernel;
+
+ /* Attributes. */
+ gctSIZE_T internalSize;
+ gctPHYS_ADDR internalPhysical;
+ gctPOINTER internalLogical;
+ gckVIDMEM internalVidMem;
+ gctSIZE_T externalSize;
+ gctPHYS_ADDR externalPhysical;
+ gctPOINTER externalLogical;
+ gckVIDMEM externalVidMem;
+ gckVIDMEM contiguousVidMem;
+ gctPOINTER contiguousBase;
+ gctPHYS_ADDR contiguousPhysical;
+ gctSIZE_T contiguousSize;
+ gctBOOL contiguousMapped;
+ gctPOINTER contiguousMappedUser;
+ gctSIZE_T systemMemorySize;
+ gctUINT32 systemMemoryBaseAddress;
+ gctPOINTER registerBase;
+ gctSIZE_T registerSize;
+ gctUINT32 baseAddress;
+
+ /* IRQ management. */
+ gctINT irqLine;
+ gctBOOL isrInitialized;
+ gctBOOL dataReady;
+
+ /* Thread management. */
+ struct task_struct *threadCtxt;
+ struct semaphore sema;
+ gctBOOL threadInitialized;
+ gctBOOL killThread;
+
+ /* Signal management. */
+ gctINT signal;
+}
+* gckGALDEVICE;
+
+#if gcdkUSE_MEMORY_RECORD
+typedef struct MEMORY_RECORD
+{
+ gcuVIDMEM_NODE_PTR node;
+
+ struct MEMORY_RECORD * prev;
+ struct MEMORY_RECORD * next;
+}
+MEMORY_RECORD, * MEMORY_RECORD_PTR;
+#endif
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+ gckGALDEVICE device;
+ gctPOINTER mappedMemory;
+ gctPOINTER contiguousLogical;
+
+#if gcdkUSE_MEMORY_RECORD
+ MEMORY_RECORD memoryRecordList;
+#endif
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start_Thread(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop_Thread(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 BaseAddress,
+ IN gctINT Signal,
+ OUT gckGALDEVICE *Device
+ );
+
+gceSTATUS gckGALDEVICE_Destroy(
+ IN gckGALDEVICE Device
+ );
+
+#endif /* __gc_hal_kernel_device_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+
+
+#include "gc_hal_kernel_linux.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_user_context.h"
+
+#if USE_PLATFORM_DRIVER
+#include <linux/platform_device.h>
+#endif
+
+MODULE_DESCRIPTION("Vivante Graphics Driver");
+MODULE_LICENSE("GPL");
+
+struct class *gpuClass;
+
+static gckGALDEVICE galDevice;
+
+static int major = 199;
+module_param(major, int, 0644);
+
+int irqLine = 0;
+module_param(irqLine, int, 0644);
+
+long registerMemBase = 0x80000000;
+module_param(registerMemBase, long, 0644);
+
+ulong registerMemSize = 256 << 10;
+module_param(registerMemSize, ulong, 0644);
+
+long contiguousSize = 4 << 20;
+module_param(contiguousSize, long, 0644);
+
+ulong contiguousBase = 0;
+module_param(contiguousBase, ulong, 0644);
+
+long bankSize = 32 << 20;
+module_param(bankSize, long, 0644);
+
+int fastClear = -1;
+module_param(fastClear, int, 0644);
+
+int compression = -1;
+module_param(compression, int, 0644);
+
+int signal = 48;
+module_param(signal, int, 0644);
+
+ulong baseAddress = 0;
+module_param(baseAddress, ulong, 0644);
+
+int showArgs = 0;
+module_param(showArgs, int, 0644);
+
+static int drv_open(struct inode *inode, struct file *filp);
+static int drv_release(struct inode *inode, struct file *filp);
+static int drv_ioctl(struct inode *inode, struct file *filp,
+ unsigned int ioctlCode, unsigned long arg);
+static int drv_mmap(struct file * filp, struct vm_area_struct * vma);
+
+struct file_operations driver_fops =
+{
+ .open = drv_open,
+ .release = drv_release,
+ .ioctl = drv_ioctl,
+ .mmap = drv_mmap,
+};
+
+int drv_open(struct inode *inode, struct file* filp)
+{
+ gcsHAL_PRIVATE_DATA_PTR private;
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "Entering drv_open\n");
+
+ private = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL);
+
+ if (private == gcvNULL)
+ {
+ return -ENOTTY;
+ }
+
+ private->device = galDevice;
+ private->mappedMemory = gcvNULL;
+ private->contiguousLogical = gcvNULL;
+
+#if gcdkUSE_MEMORY_RECORD
+ private->memoryRecordList.prev = &private->memoryRecordList;
+ private->memoryRecordList.next = &private->memoryRecordList;
+#endif
+
+ /* A process gets attached. */
+ gcmkVERIFY_OK(
+ gckKERNEL_AttachProcess(galDevice->kernel, gcvTRUE));
+
+ if (!galDevice->contiguousMapped)
+ {
+ gcmkVERIFY_OK(gckOS_MapMemory(galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ &private->contiguousLogical));
+ }
+
+ filp->private_data = private;
+
+ return 0;
+}
+
+extern void
+OnProcessExit(
+ IN gckOS Os,
+ IN gckKERNEL Kernel
+ );
+
+int drv_release(struct inode* inode, struct file* filp)
+{
+ gcsHAL_PRIVATE_DATA_PTR private;
+ gckGALDEVICE device;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Entering drv_close\n");
+
+ private = filp->private_data;
+ gcmkASSERT(private != gcvNULL);
+
+ device = private->device;
+
+#if gcdkUSE_MEMORY_RECORD
+ FreeAllMemoryRecord(galDevice->os, &private->memoryRecordList);
+
+#ifdef ANDROID
+ gcmkVERIFY_OK(gckOS_Delay(galDevice->os, 1000));
+#else
+ gcmkVERIFY_OK(gckCOMMAND_Stall(device->kernel->command));
+#endif
+#endif
+
+ if (!device->contiguousMapped)
+ {
+ if (private->contiguousLogical != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckOS_UnmapMemory(galDevice->os,
+ galDevice->contiguousPhysical,
+ galDevice->contiguousSize,
+ private->contiguousLogical));
+ }
+ }
+
+ /* A process gets detached. */
+ gcmkVERIFY_OK(
+ gckKERNEL_AttachProcess(galDevice->kernel, gcvFALSE));
+
+ kfree(private);
+ filp->private_data = NULL;
+
+ return 0;
+}
+
+int drv_ioctl(struct inode *inode,
+ struct file *filp,
+ unsigned int ioctlCode,
+ unsigned long arg)
+{
+ gcsHAL_INTERFACE iface;
+ gctUINT32 copyLen;
+ DRIVER_ARGS drvArgs;
+ gckGALDEVICE device;
+ gceSTATUS status;
+ gcsHAL_PRIVATE_DATA_PTR private;
+
+ private = filp->private_data;
+
+ if (private == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] drv_ioctl: private_data is NULL\n");
+
+ return -ENOTTY;
+ }
+
+ device = private->device;
+
+ if (device == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] drv_ioctl: device is NULL\n");
+
+ return -ENOTTY;
+ }
+
+ if (ioctlCode != IOCTL_GCHAL_INTERFACE
+ && ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
+ {
+ /* Unknown command. Fail the I/O. */
+ return -ENOTTY;
+ }
+
+ /* Get the drvArgs to begin with. */
+ copyLen = copy_from_user(&drvArgs,
+ (void *) arg,
+ sizeof(DRIVER_ARGS));
+
+ if (copyLen != 0)
+ {
+ /* The input buffer is not big enough. So fail the I/O. */
+ return -ENOTTY;
+ }
+
+ /* Now bring in the gcsHAL_INTERFACE structure. */
+ if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
+ || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
+ )
+ {
+ return -ENOTTY;
+ }
+
+ copyLen = copy_from_user(&iface,
+ drvArgs.InputBuffer,
+ sizeof(gcsHAL_INTERFACE));
+
+ if (copyLen != 0)
+ {
+ /* The input buffer is not big enough. So fail the I/O. */
+ return -ENOTTY;
+ }
+
+#if gcdkUSE_MEMORY_RECORD
+ if (iface.command == gcvHAL_EVENT_COMMIT)
+ {
+ MEMORY_RECORD_PTR mr;
+ gcsQUEUE_PTR queue = iface.u.Event.queue;
+
+ while (queue != gcvNULL)
+ {
+ gcsQUEUE_PTR record, next;
+
+ /* Map record into kernel memory. */
+ gcmkERR_BREAK(gckOS_MapUserPointer(device->os,
+ queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) &record));
+
+ switch (record->iface.command)
+ {
+ case gcvHAL_FREE_VIDEO_MEMORY:
+ mr = FindMemoryRecord(device->os,
+ &private->memoryRecordList,
+ record->iface.u.FreeVideoMemory.node);
+
+ if (mr != gcvNULL)
+ {
+ DestoryMemoryRecord(device->os, mr);
+ }
+ else
+ {
+ printk("*ERROR* Invalid video memory (%p) for free\n",
+ record->iface.u.FreeVideoMemory.node);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* Next record in the queue. */
+ next = record->next;
+
+ /* Unmap record from kernel memory. */
+ gcmkERR_BREAK(gckOS_UnmapUserPointer(device->os,
+ queue,
+ gcmSIZEOF(gcsQUEUE),
+ (gctPOINTER *) record));
+ queue = next;
+ }
+ }
+#endif
+
+ status = gckKERNEL_Dispatch(device->kernel,
+ (ioctlCode == IOCTL_GCHAL_INTERFACE) , &iface);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+ "[galcore] gckKERNEL_Dispatch returned %d.\n",
+ status);
+ }
+
+ else if (gcmIS_ERROR(iface.status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+ "[galcore] IOCTL %d returned %d.\n",
+ iface.command,
+ iface.status);
+ }
+
+ /* See if this was a LOCK_VIDEO_MEMORY command. */
+ else if (iface.command == gcvHAL_LOCK_VIDEO_MEMORY)
+ {
+ /* Special case for mapped memory. */
+ if (private->mappedMemory != gcvNULL
+ && iface.u.LockVideoMemory.node->VidMem.memory->object.type
+ == gcvOBJ_VIDMEM)
+ {
+ /* Compute offset into mapped memory. */
+ gctUINT32 offset = (gctUINT8 *) iface.u.LockVideoMemory.memory
+ - (gctUINT8 *) device->contiguousBase;
+
+ /* Compute offset into user-mapped region. */
+ iface.u.LockVideoMemory.memory =
+ (gctUINT8 *) private->mappedMemory + offset;
+ }
+ }
+#if gcdkUSE_MEMORY_RECORD
+ else if (iface.command == gcvHAL_ALLOCATE_VIDEO_MEMORY)
+ {
+ CreateMemoryRecord(device->os,
+ &private->memoryRecordList,
+ iface.u.AllocateVideoMemory.node);
+ }
+ else if (iface.command == gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY)
+ {
+ CreateMemoryRecord(device->os,
+ &private->memoryRecordList,
+ iface.u.AllocateLinearVideoMemory.node);
+ }
+ else if (iface.command == gcvHAL_FREE_VIDEO_MEMORY)
+ {
+ MEMORY_RECORD_PTR mr;
+
+ mr = FindMemoryRecord(device->os,
+ &private->memoryRecordList,
+ iface.u.FreeVideoMemory.node);
+
+ if (mr != gcvNULL)
+ {
+ DestoryMemoryRecord(device->os, mr);
+ }
+ else
+ {
+ printk("*ERROR* Invalid video memory for free\n");
+ }
+ }
+#endif
+
+ /* Copy data back to the user. */
+ copyLen = copy_to_user(drvArgs.OutputBuffer,
+ &iface,
+ sizeof(gcsHAL_INTERFACE));
+
+ if (copyLen != 0)
+ {
+ /* The output buffer is not big enough. So fail the I/O. */
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int drv_mmap(struct file * filp, struct vm_area_struct * vma)
+{
+ gcsHAL_PRIVATE_DATA_PTR private = filp->private_data;
+ gckGALDEVICE device;
+ int ret;
+ unsigned long size = vma->vm_end - vma->vm_start;
+
+ if (private == gcvNULL)
+ {
+ return -ENOTTY;
+ }
+
+ device = private->device;
+
+ if (device == gcvNULL)
+ {
+ return -ENOTTY;
+ }
+
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND;
+ vma->vm_pgoff = 0;
+
+ if (device->contiguousMapped)
+ {
+ ret = io_remap_pfn_range(vma,
+ vma->vm_start,
+ (gctUINT32) device->contiguousPhysical >> PAGE_SHIFT,
+ size,
+ vma->vm_page_prot);
+
+ private->mappedMemory = (ret == 0) ? (gctPOINTER) vma->vm_start : gcvNULL;
+
+ return ret;
+ }
+ else
+ {
+ return -ENOTTY;
+ }
+}
+
+
+static struct miscdevice miscdev = {
+ .name = "galcore",
+ .fops = &driver_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
+
+
+
+#if !USE_PLATFORM_DRIVER
+static int __init drv_init(void)
+#else
+static int drv_init(void)
+#endif
+{
+ int ret;
+ gckGALDEVICE device;
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ struct clk * clk = NULL;
+#endif
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "Entering drv_init\n");
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ clk = clk_get(NULL, "GCCLK");
+ if (IS_ERR(clk))
+ {
+ int retval = PTR_ERR(clk);
+ printk("clk get error: %d\n", retval);
+ return -ENODEV;
+ }
+
+ /* APMU_GC_156M, APMU_GC_624M, APMU_GC_PLL2, APMU_GC_PLL2_DIV2 currently */
+ if (clk_set_rate(clk, 624000000))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Can't set core clock.");
+ return -EAGAIN;
+ }
+ clk_enable(clk);
+#endif
+
+ if (showArgs)
+ {
+ printk("galcore options:\n");
+ printk(" irqLine = %d\n", irqLine);
+ printk(" registerMemBase = 0x%08lX\n", registerMemBase);
+ printk(" contiguousSize = %ld\n", contiguousSize);
+ printk(" contiguousBase = 0x%08lX\n", contiguousBase);
+ printk(" bankSize = 0x%08lX\n", bankSize);
+ printk(" fastClear = %d\n", fastClear);
+ printk(" compression = %d\n", compression);
+ printk(" signal = %d\n", signal);
+ printk(" baseAddress = 0x%08lX\n", baseAddress);
+ }
+
+ /* Create the GAL device. */
+ gcmkVERIFY_OK(gckGALDEVICE_Construct(irqLine,
+ registerMemBase,
+ registerMemSize,
+ contiguousBase,
+ contiguousSize,
+ bankSize,
+ fastClear,
+ compression,
+ baseAddress,
+ signal,
+ &device));
+
+ /* Start the GAL device. */
+ if (gcmIS_ERROR(gckGALDEVICE_Start(device)))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Can't start the gal device.\n");
+
+ /* Roll back. */
+ gckGALDEVICE_Stop(device);
+ gckGALDEVICE_Destroy(device);
+
+ return -1;
+ }
+
+
+#if 1
+ ret = misc_register(&miscdev);
+ if (ret < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Could not register misc.\n");
+
+ /* Roll back. */
+ gckGALDEVICE_Stop(device);
+ gckGALDEVICE_Destroy(device);
+
+ return -1;
+ }
+ galDevice = device;
+#else
+
+ /* Register the character device. */
+ ret = register_chrdev(major, DRV_NAME, &driver_fops);
+ if (ret < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Could not allocate major number for mmap.\n");
+
+ /* Roll back. */
+ gckGALDEVICE_Stop(device);
+ gckGALDEVICE_Destroy(device);
+
+ return -1;
+ }
+ else
+ {
+ if (major == 0)
+ {
+ major = ret;
+ }
+ }
+
+ galDevice = device;
+
+ gpuClass = class_create(THIS_MODULE, "graphics_class");
+ if (IS_ERR(gpuClass)) {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "Failed to create the class.\n");
+ return -1;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+ device_create(gpuClass, NULL, MKDEV(major, 0), NULL, "galcore");
+#else
+ device_create(gpuClass, NULL, MKDEV(major, 0), "galcore");
+#endif
+#endif
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] irqLine->%ld, contiguousSize->%lu, memBase->0x%lX\n",
+ irqLine,
+ contiguousSize,
+ registerMemBase);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "[galcore] driver registered successfully.\n");
+
+ return 0;
+}
+
+#if !USE_PLATFORM_DRIVER
+static void __exit drv_exit(void)
+#else
+static void drv_exit(void)
+#endif
+{
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ struct clk * clk = NULL;
+#endif
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "[galcore] Entering drv_exit\n");
+
+#if 1
+ misc_deregister(&miscdev);
+#else
+
+ device_destroy(gpuClass, MKDEV(major, 0));
+ class_destroy(gpuClass);
+
+ unregister_chrdev(major, DRV_NAME);
+#endif
+
+ gckGALDEVICE_Stop(galDevice);
+ gckGALDEVICE_Destroy(galDevice);
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+ clk = clk_get(NULL, "GCCLK");
+ clk_disable(clk);
+#endif
+}
+
+#if !USE_PLATFORM_DRIVER
+module_init(drv_init);
+module_exit(drv_exit);
+#else
+
+#ifdef CONFIG_DOVE_GPU
+#define DEVICE_NAME "dove_gpu"
+#else
+#define DEVICE_NAME "galcore"
+#endif
+
+
+static int __devinit gpu_probe(struct platform_device *pdev)
+{
+ int ret = -ENODEV;
+ struct resource *res;
+ res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,"gpu_irq");
+ if (!res) {
+ printk(KERN_ERR "%s: No irq line supplied.\n",__FUNCTION__);
+ goto gpu_probe_fail;
+ }
+ irqLine = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gpu_base");
+ if (!res) {
+ printk(KERN_ERR "%s: No register base supplied.\n",__FUNCTION__);
+ goto gpu_probe_fail;
+ }
+ registerMemBase = res->start;
+ registerMemSize = res->end - res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,"gpu_mem");
+ if (!res) {
+ printk(KERN_ERR "%s: No memory base supplied.\n",__FUNCTION__);
+ goto gpu_probe_fail;
+ }
+ contiguousBase = res->start;
+ contiguousSize = res->end-res->start;
+
+ ret = drv_init();
+ if(!ret) {
+ platform_set_drvdata(pdev,galDevice);
+ return ret;
+ }
+
+gpu_probe_fail:
+ printk(KERN_INFO "Failed to register gpu driver.\n");
+ return ret;
+}
+
+static int __devinit gpu_remove(struct platform_device *pdev)
+{
+ drv_exit();
+
+ return 0;
+}
+
+static int __devinit gpu_suspend(struct platform_device *dev, pm_message_t state)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+
+ device = platform_get_drvdata(dev);
+
+ status = gckHARDWARE_SetPowerManagementState(device->kernel->hardware, gcvPOWER_OFF);
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __devinit gpu_resume(struct platform_device *dev)
+{
+ gceSTATUS status;
+ gckGALDEVICE device;
+
+ device = platform_get_drvdata(dev);
+
+ status = gckHARDWARE_SetPowerManagementState(device->kernel->hardware, gcvPOWER_ON);
+
+ if (gcmIS_ERROR(status))
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct platform_driver gpu_driver = {
+ .probe = gpu_probe,
+ .remove = gpu_remove,
+
+ .suspend = gpu_suspend,
+ .resume = gpu_resume,
+
+ .driver = {
+ .name = DEVICE_NAME,
+ }
+};
+
+#if 0
+#ifndef CONFIG_DOVE_GPU
+static struct resource gpu_resources[] = {
+ {
+ .name = "gpu_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "gpu_base",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "gpu_mem",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device * gpu_device;
+#endif
+#endif
+
+static int __init gpu_init(void)
+{
+ int ret = 0;
+
+#if 0 //add by dkm
+#ifndef CONFIG_DOVE_GPU
+ gpu_resources[0].start = gpu_resources[0].end = irqLine;
+
+ gpu_resources[1].start = registerMemBase;
+ gpu_resources[1].end = registerMemBase + registerMemSize;
+
+ gpu_resources[2].start = contiguousBase;
+ gpu_resources[2].end = contiguousBase + contiguousSize;
+
+ /* Allocate device */
+ gpu_device = platform_device_alloc(DEVICE_NAME, -1);
+ if (!gpu_device)
+ {
+ printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Insert resource */
+ ret = platform_device_add_resources(gpu_device, gpu_resources, 3);
+ if (ret)
+ {
+ printk(KERN_ERR "galcore: platform_device_add_resources failed.\n");
+ goto put_dev;
+ }
+
+ /* Add device */
+ ret = platform_device_add(gpu_device);
+ if (ret)
+ {
+ printk(KERN_ERR "galcore: platform_device_add failed.\n");
+ goto del_dev;
+ }
+#endif
+#endif
+ ret = platform_driver_register(&gpu_driver);
+ if (!ret)
+ {
+ goto out;
+ }
+
+#if 0 //add by dkm
+#ifndef CONFIG_DOVE_GPU
+del_dev:
+ platform_device_del(gpu_device);
+put_dev:
+ platform_device_put(gpu_device);
+#endif
+#endif
+
+out:
+ return ret;
+
+}
+
+static void __exit gpu_exit(void)
+{
+ platform_driver_unregister(&gpu_driver);
+#if 0 //add by dkm
+#ifndef CONFIG_DOVE_GPU
+ platform_device_unregister(gpu_device);
+#endif
+#endif
+}
+
+module_init(gpu_init);
+module_exit(gpu_exit);
+
+#endif
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_QueryVideoMemory
+**
+** Query the amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
+** the memory information.
+*/
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Get internal memory size and physical address. */
+ Interface->u.QueryVideoMemory.internalSize = device->internalSize;
+ Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysical;
+
+ /* Get external memory size and physical address. */
+ Interface->u.QueryVideoMemory.externalSize = device->externalSize;
+ Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysical;
+
+ /* Get contiguous memory size and physical address. */
+ Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
+ Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysical;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_GetVideoMemoryPool
+**
+** Get the gckVIDMEM object belonging to the specified pool.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcePOOL Pool
+** Pool to query gckVIDMEM object for.
+**
+** OUTPUT:
+**
+** gckVIDMEM * VideoMemory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object belonging to the requested pool.
+*/
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ )
+{
+ gckGALDEVICE device;
+ gckVIDMEM videoMemory;
+
+ gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Dispatch on pool. */
+ switch (Pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ videoMemory = device->internalVidMem;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ videoMemory = device->externalVidMem;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ videoMemory = device->contiguousVidMem;
+ break;
+
+ default:
+ /* Unknown pool. */
+ videoMemory = NULL;
+ }
+
+ /* Return pointer to the gckVIDMEM object. */
+ *VideoMemory = videoMemory;
+
+ /* Return status. */
+ gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
+ return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapMemory
+**
+** Map video memory into the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the base address of the mapped
+** memory region.
+*/
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ return gckOS_MapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_UnmapMemory
+**
+** Unmap video memory from the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** gctPOINTER Logical
+** Base address of the mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ return gckOS_UnmapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapVideoMemory
+**
+** Get the logical address for a hardware specific memory address for the
+** current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE to map the memory into the user space.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * Logical
+ )
+{
+ gckGALDEVICE device;
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ gcePOOL pool;
+ gctUINT32 offset, base;
+ gceSTATUS status;
+ gctPOINTER logical;
+
+ gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
+ Kernel, InUserSpace, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Split the memory address into a pool type and offset. */
+ gcmkONERROR(
+ gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset));
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ if (device->contiguousMapped)
+ {
+ logical = device->contiguousBase;
+ }
+ else
+ {
+ mdl = (PLINUX_MDL) device->contiguousPhysical;
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+ gcmkASSERT(mdlMap);
+
+ logical = (gctPOINTER) mdlMap->vmaAddr;
+ }
+
+ gcmkVERIFY_OK(
+ gckHARDWARE_SplitMemory(Kernel->hardware,
+ device->contiguousVidMem->baseAddress,
+ &pool,
+ &base));
+
+ offset -= base;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Build logical address of specified address. */
+ *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Logical=%p", *Logical);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Retunn the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Notify
+**
+** This function iscalled by clients to notify the gckKERNRL object of an event.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gceNOTIFY Notification
+** Notification event.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+ IN gceNOTIFY Notification,
+ IN gctBOOL Data
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=%p Notification=%d Data=%d",
+ Kernel, Notification, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Dispatch on notifcation. */
+ switch (Notification)
+ {
+ case gcvNOTIFY_INTERRUPT:
+ /* Process the interrupt. */
+#if COMMAND_PROCESSOR_VERSION > 1
+ status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
+#else
+ status = gckHARDWARE_Interrupt(Kernel->hardware, Data);
+#endif
+ break;
+
+ default:
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=%p", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Fill in signal. */
+ Settings->signal = device->signal;
+
+ /* Success. */
+ gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
+ return gcvSTATUS_OK;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_linux_h_
+#define __gc_hal_kernel_linux_h_
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#ifdef FLAREON
+# include <asm/arch-realview/dove_gpio_irq.h>
+#endif
+#include <linux/interrupt.h>
+#include <linux/vmalloc.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+
+#ifdef MODVERSIONS
+# include <linux/modversions.h>
+#endif
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
+#include <linux/clk.h>
+#endif
+
+#define NTSTRSAFE_NO_CCH_FUNCTIONS
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_kernel_os.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
+#else
+#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
+#endif
+
+#define _WIDE(string) L##string
+#define WIDE(string) _WIDE(string)
+
+#define countof(a) (sizeof(a) / sizeof(a[0]))
+
+#define DRV_NAME "galcore"
+
+#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+
+static inline gctINT
+GetOrder(
+ IN gctINT numPages
+ )
+{
+ gctINT order = 0;
+
+ while ((1 << order) < numPages) order++;
+
+ return order;
+}
+
+#endif /* __gc_hal_kernel_linux_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_linux.h"
+
+#include <linux/pagemap.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+#ifdef NO_DMA_COHERENT
+#include <linux/dma-mapping.h>
+#endif /* NO_DMA_COHERENT */
+
+#if !USE_NEW_LINUX_SIGNAL
+#define USER_SIGNAL_TABLE_LEN_INIT 64
+#endif
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#define MEMORY_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryLock, \
+ gcvINFINITE))
+
+#define MEMORY_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
+
+#define MEMORY_MAP_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryMapLock, \
+ gcvINFINITE))
+
+#define MEMORY_MAP_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+struct _gckOS
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Heap. */
+ gckHEAP heap;
+
+ /* Pointer to device */
+ gckGALDEVICE device;
+
+ /* Memory management */
+ gctPOINTER memoryLock;
+ gctPOINTER memoryMapLock;
+
+ struct _LINUX_MDL *mdlHead;
+ struct _LINUX_MDL *mdlTail;
+
+ gctUINT32 baseAddress;
+
+ /* Kernel process ID. */
+ gctUINT32 kernelProcessID;
+
+#if !USE_NEW_LINUX_SIGNAL
+ /* Signal management. */
+ struct _signal {
+ /* Unused signal ID number. */
+ gctINT unused;
+
+ /* The pointer to the table. */
+ gctPOINTER * table;
+
+ /* Signal table length. */
+ gctINT tableLen;
+
+ /* The current unused signal ID. */
+ gctINT currentID;
+
+ /* Lock. */
+ gctPOINTER lock;
+ } signal;
+#endif
+};
+
+#if !USE_NEW_LINUX_SIGNAL
+typedef struct _gcsSIGNAL
+{
+ /* Kernel sync primitive. */
+ struct completion event;
+
+ /* Manual reset flag. */
+ gctBOOL manualReset;
+
+ /* The reference counter. */
+ atomic_t ref;
+
+ /* The owner of the signal. */
+ gctHANDLE process;
+}
+gcsSIGNAL;
+
+typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
+#endif
+
+typedef struct _gcsPageInfo * gcsPageInfo_PTR;
+
+typedef struct _gcsPageInfo
+{
+ struct page **pages;
+ gctUINT32_PTR pageTable;
+}
+gcsPageInfo;
+
+static PLINUX_MDL
+_CreateMdl(
+ IN gctINT PID
+ )
+{
+ PLINUX_MDL mdl;
+
+ mdl = (PLINUX_MDL)kmalloc(sizeof(struct _LINUX_MDL), GFP_ATOMIC);
+ if (mdl == gcvNULL) return gcvNULL;
+
+ mdl->pid = PID;
+ mdl->maps = gcvNULL;
+ mdl->prev = gcvNULL;
+ mdl->next = gcvNULL;
+
+ return mdl;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap
+ );
+
+static gceSTATUS
+_DestroyMdl(
+ IN PLINUX_MDL Mdl
+ )
+{
+ PLINUX_MDL_MAP mdlMap, next;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
+
+ mdlMap = Mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ next = mdlMap->next;
+
+ gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
+
+ mdlMap = next;
+ }
+
+ kfree(Mdl);
+
+ return gcvSTATUS_OK;
+}
+
+static PLINUX_MDL_MAP
+_CreateMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_ATOMIC);
+ if (mdlMap == gcvNULL) return gcvNULL;
+
+ mdlMap->pid = PID;
+ mdlMap->vmaAddr = gcvNULL;
+ mdlMap->vma = gcvNULL;
+
+ mdlMap->next = Mdl->maps;
+ Mdl->maps = mdlMap;
+
+ return mdlMap;
+}
+
+static gceSTATUS
+_DestroyMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN PLINUX_MDL_MAP MdlMap
+ )
+{
+ PLINUX_MDL_MAP prevMdlMap;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
+ gcmkASSERT(Mdl->maps != gcvNULL);
+
+ if (Mdl->maps == MdlMap)
+ {
+ Mdl->maps = MdlMap->next;
+ }
+ else
+ {
+ prevMdlMap = Mdl->maps;
+
+ while (prevMdlMap->next != MdlMap)
+ {
+ prevMdlMap = prevMdlMap->next;
+
+ gcmkASSERT(prevMdlMap != gcvNULL);
+ }
+
+ prevMdlMap->next = MdlMap->next;
+ }
+
+ kfree(MdlMap);
+
+ return gcvSTATUS_OK;
+}
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+
+ mdlMap = Mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if (mdlMap->pid == PID) return mdlMap;
+
+ mdlMap = mdlMap->next;
+ }
+
+ return gcvNULL;
+}
+
+void
+FreeProcessMemoryOnExit(
+ IN gckOS Os,
+ IN gckKERNEL Kernel
+ )
+{
+ PLINUX_MDL mdl, nextMdl;
+ PLINUX_MDL_MAP mdlMap;
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl != Os->mdlTail)
+ {
+ nextMdl = mdl->next;
+ }
+ else
+ {
+ nextMdl = gcvNULL;
+ }
+
+ if (mdl->pagedMem)
+ {
+ mdlMap = mdl->maps;
+
+ if (mdlMap != gcvNULL
+ && mdlMap->pid == current->tgid
+ && mdlMap->next == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ gcmkVERIFY_OK(gckOS_FreePagedMemory(Os, mdl, mdl->numPages * PAGE_SIZE));
+
+ MEMORY_LOCK(Os);
+
+ nextMdl = Os->mdlHead;
+ }
+ }
+
+ mdl = nextMdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+}
+
+void
+PrintInfoOnExit(
+ IN gckOS Os,
+ IN gckKERNEL Kernel
+ )
+{
+ PLINUX_MDL mdl, nextMdl;
+ PLINUX_MDL_MAP mdlMap;
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl != Os->mdlTail)
+ {
+ nextMdl = mdl->next;
+ }
+ else
+ {
+ nextMdl = gcvNULL;
+ }
+
+ printk("Unfreed mdl: %p, pid: %d -> pagedMem: %s, addr: %p, dmaHandle: 0x%x, pages: %d",
+ mdl,
+ mdl->pid,
+ mdl->pagedMem? "true" : "false",
+ mdl->addr,
+ mdl->dmaHandle,
+ mdl->numPages);
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ printk("\tmap: %p, pid: %d -> vmaAddr: %p, vma: %p",
+ mdlMap,
+ mdlMap->pid,
+ mdlMap->vmaAddr,
+ mdlMap->vma);
+
+ mdlMap = mdlMap->next;
+ }
+
+ mdl = nextMdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+}
+
+void
+OnProcessExit(
+ IN gckOS Os,
+ IN gckKERNEL Kernel
+ )
+{
+ /* PrintInfoOnExit(Os, Kernel); */
+
+#ifdef ANDROID
+ FreeProcessMemoryOnExit(Os, Kernel);
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_Construct
+**
+** Construct a new gckOS object.
+**
+** INPUT:
+**
+** gctPOINTER Context
+** Pointer to the gckGALDEVICE class.
+**
+** OUTPUT:
+**
+** gckOS * Os
+** Pointer to a variable that will hold the pointer to the gckOS object.
+*/
+gceSTATUS
+gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+ /* Allocate the gckOS object. */
+ os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_ATOMIC);
+
+ if (os == gcvNULL)
+ {
+ /* Out of memory. */
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Zero the memory. */
+ gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
+
+ /* Initialize the gckOS object. */
+ os->object.type = gcvOBJ_OS;
+
+ /* Set device device. */
+ os->device = Context;
+
+ /* IMPORTANT! No heap yet. */
+ os->heap = gcvNULL;
+
+ /* Initialize the memory lock. */
+ gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
+
+ gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
+
+ /* Create the gckHEAP object. */
+ gcmkONERROR(gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
+
+ os->mdlHead = os->mdlTail = gcvNULL;
+
+ /* Find the base address of the physical memory. */
+ os->baseAddress = os->device->baseAddress;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "Physical base address set to 0x%08X.",
+ os->baseAddress);
+
+ /* Get the kernel process ID. */
+ gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
+
+#if !USE_NEW_LINUX_SIGNAL
+ /*
+ * Initialize the signal manager.
+ * It creates the signals to be used in
+ * the user space.
+ */
+
+ /* Initialize mutex. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &os->signal.lock));
+
+ /* Initialize the signal table. */
+ os->signal.table =
+ kmalloc(gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT, GFP_KERNEL);
+
+ if (os->signal.table == gcvNULL)
+ {
+ /* Out of memory. */
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ goto OnError;
+ }
+
+ gckOS_ZeroMemory(os->signal.table,
+ gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
+
+ /* Set the signal table length. */
+ os->signal.tableLen = USER_SIGNAL_TABLE_LEN_INIT;
+
+ /* The table is empty. */
+ os->signal.unused = os->signal.tableLen;
+
+ /* Initial signal ID. */
+ os->signal.currentID = 0;
+#endif
+
+ /* Return pointer to the gckOS object. */
+ *Os = os;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+#if !USE_NEW_LINUX_SIGNAL
+ /* Roll back any allocation. */
+ if (os->signal.table != gcvNULL)
+ {
+ kfree(os->signal.table);
+ }
+
+ if (os->signal.lock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->signal.lock));
+ }
+#endif
+
+ if (os->heap != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckHEAP_Destroy(os->heap));
+ }
+
+ if (os->memoryMapLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryMapLock));
+ }
+
+ if (os->memoryLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryLock));
+ }
+
+ kfree(os);
+
+ /* Return the error. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Destroy
+**
+** Destroy an gckOS object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ )
+{
+ gckHEAP heap;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+#if !USE_NEW_LINUX_SIGNAL
+ /*
+ * Destroy the signal manager.
+ */
+
+ /* Destroy the mutex. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->signal.lock));
+
+ /* Free the signal table. */
+ kfree(Os->signal.table);
+#endif
+
+ if (Os->heap != NULL)
+ {
+ /* Mark gckHEAP as gone. */
+ heap = Os->heap;
+ Os->heap = NULL;
+
+ /* Destroy the gckHEAP object. */
+ gcmkVERIFY_OK(
+ gckHEAP_Destroy(heap));
+ }
+
+ /* Destroy the memory lock. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->memoryMapLock));
+
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->memoryLock));
+
+ gcmkPRINT("$$FLUSH$$");
+
+ /* Mark the gckOS object as unknown. */
+ Os->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckOS object. */
+ kfree(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_Allocate
+**
+** Allocate memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gceSTATUS status;
+
+ //gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ /* Do we have a heap? */
+ if (Os->heap != NULL)
+ {
+ /* Allocate from the heap. */
+ gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
+ }
+
+ /* Success. */
+ //gcmkFOOTER_ARG("*memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Free
+**
+** Free allocated memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gceSTATUS status;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ //gcmkHEADER_ARG("Os=0x%x Memory=0x%x", Os, memory);
+
+ /* Do we have a heap? */
+ if (Os->heap != NULL)
+ {
+ /* Free from the heap. */
+ gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_FreeMemory(Os, Memory));
+ }
+
+ /* Success. */
+ //gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateMemory
+**
+** Allocate memory wrapper.
+**
+** INPUT:
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctPOINTER memory;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ memory = (gctPOINTER) kmalloc(Bytes, GFP_ATOMIC);
+
+ if (memory == NULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Return pointer to the memory allocation. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=%p", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeMemory
+**
+** Free allocated memory wrapper.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gcmkHEADER_ARG("Memory=%p", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ /* Free the memory from the OS pool. */
+ kfree(Memory);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapMemory
+**
+** Map physical memory into the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the logical address of the
+** mapped memory.
+*/
+gceSTATUS
+gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ down_write(¤t->mm->mmap_sem);
+
+ mdlMap->vmaAddr = (char *)do_mmap_pgoff(NULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: do_mmap_pgoff error");
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapMemory] mdl->numPages: %d",
+ "[gckOS_MapMemory] mdl->vmaAddr: 0x%x",
+ mdl->numPages,
+ mdlMap->vmaAddr
+ );
+
+ up_write(¤t->mm->mmap_sem);
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ if (!mdlMap->vma)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: find_vma error.");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ up_write(¤t->mm->mmap_sem);
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+#ifndef NO_DMA_COHERENT
+ if (dma_mmap_coherent(NULL,
+ mdlMap->vma,
+ mdl->addr,
+ mdl->dmaHandle,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ up_write(¤t->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: dma_mmap_coherent error.");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#else
+ mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+ mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
+ mdlMap->vma->vm_pgoff = 0;
+
+ if (remap_pfn_range(mdlMap->vma,
+ mdlMap->vma->vm_start,
+ mdl->dmaHandle >> PAGE_SHIFT,
+ mdl->numPages*PAGE_SIZE,
+ mdlMap->vma->vm_page_prot) < 0)
+ {
+ up_write(¤t->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(¤t->mm->mmap_sem);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ *Logical = mdlMap->vmaAddr;
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
+ "gckOS_MapMemory: User Mapped address for 0x%x is 0x%x pid->%d",
+ (gctUINT32)mdl->addr,
+ (gctUINT32)*Logical,
+ mdlMap->pid);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapMemory
+**
+** Unmap physical memory out of the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ struct task_struct * task;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_UnmapMemory");
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_UnmapMemory Will be unmapping 0x%x mdl->0x%x",
+ (gctUINT32)Logical,
+ (gctUINT32)mdl);
+
+ MEMORY_LOCK(Os);
+
+ if (Logical)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_UnmapMemory] Logical: 0x%x",
+ Logical
+ );
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Get the current pointer for the task with stored pid. */
+ task = FIND_TASK_BY_PID(mdlMap->pid);
+
+ if (task != gcvNULL && task->mm != gcvNULL)
+ {
+ down_write(&task->mm->mmap_sem);
+ do_munmap(task->mm, (unsigned long)Logical, mdl->numPages*PAGE_SIZE);
+ up_write(&task->mm->mmap_sem);
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "Can't find the task with pid->%d. No unmapping",
+ mdlMap->pid);
+ }
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateNonPagedMemory
+**
+** Allocate a number of pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that holds the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** allocation.
+*/
+gceSTATUS
+gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctSIZE_T bytes;
+ gctINT numPages;
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap = 0;
+ gctSTRING addr;
+
+#ifdef NO_DMA_COHERENT
+ struct page * page;
+ long size, order;
+ gctPOINTER vaddr;
+#endif
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT((Bytes != NULL) && (*Bytes > 0));
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_AllocateNonPagedMemory");
+
+ /* Align number of bytes to page size. */
+ bytes = gcmALIGN(*Bytes, PAGE_SIZE);
+
+ /* Get total number of pages.. */
+ numPages = GetPageCount(bytes, 0);
+
+ /* Allocate mdl+vector structure */
+ mdl = _CreateMdl(current->tgid);
+
+ if (mdl == gcvNULL)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdl->pagedMem = 0;
+ mdl->numPages = numPages;
+
+ MEMORY_LOCK(Os);
+
+#ifndef NO_DMA_COHERENT
+ addr = dma_alloc_coherent(NULL,
+ mdl->numPages * PAGE_SIZE,
+ &mdl->dmaHandle,
+ GFP_ATOMIC);
+#else
+ size = mdl->numPages * PAGE_SIZE;
+ order = get_order(size);
+ page = alloc_pages(GFP_KERNEL | GFP_DMA, order);
+
+ if (page == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ vaddr = (gctPOINTER)page_address(page);
+ addr = ioremap_nocache(virt_to_phys(vaddr), size);
+ mdl->dmaHandle = virt_to_phys(vaddr);
+ mdl->kaddr = vaddr;
+
+#if ENABLE_ARM_L2_CACHE
+ dma_cache_maint(vaddr, size, DMA_FROM_DEVICE);
+#endif
+
+ while (size > 0)
+ {
+ SetPageReserved(virt_to_page(vaddr));
+
+ vaddr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+#endif
+
+ if (addr == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "galcore: Can't allocate memorry for size->0x%x",
+ (gctUINT32)bytes);
+
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ if ((Os->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
+ {
+ mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
+ | (Os->baseAddress & 0x80000000);
+ }
+
+ mdl->addr = addr;
+
+ /*
+ * We will not do any mapping from here.
+ * Mapping will happen from mmap method.
+ * mdl structure will be used.
+ */
+
+ /* Return allocated memory. */
+ *Bytes = bytes;
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ if (InUserSpace)
+ {
+ mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Only after mmap this will be valid. */
+
+ /* We need to map this to user space. */
+ down_write(¤t->mm->mmap_sem);
+
+ mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "galcore: do_mmap_pgoff error");
+
+ up_write(¤t->mm->mmap_sem);
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ if (mdlMap->vma == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "find_vma error");
+
+ up_write(¤t->mm->mmap_sem);
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+#ifndef NO_DMA_COHERENT
+ if (dma_mmap_coherent(NULL,
+ mdlMap->vma,
+ mdl->addr,
+ mdl->dmaHandle,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ up_write(¤t->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "dma_mmap_coherent error");
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#else
+ mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+ mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
+ mdlMap->vma->vm_pgoff = 0;
+
+ if (remap_pfn_range(mdlMap->vma,
+ mdlMap->vma->vm_start,
+ mdl->dmaHandle >> PAGE_SHIFT,
+ mdl->numPages * PAGE_SIZE,
+ mdlMap->vma->vm_page_prot))
+ {
+ up_write(¤t->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "remap_pfn_range error");
+
+ gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+#endif /* NO_DMA_COHERENT */
+
+ up_write(¤t->mm->mmap_sem);
+
+ *Logical = mdlMap->vmaAddr;
+ }
+ else
+ {
+ *Logical = (gctPOINTER)mdl->addr;
+ }
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+
+ if (!Os->mdlHead)
+ {
+ /* Initialize the queue. */
+ Os->mdlHead = Os->mdlTail = mdl;
+ }
+ else
+ {
+ /* Add to the tail. */
+ mdl->prev = Os->mdlTail;
+ Os->mdlTail->next = mdl;
+ Os->mdlTail = mdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocateNonPagedMemory: "
+ "Bytes->0x%x, Mdl->%p, Logical->0x%x dmaHandle->0x%x",
+ (gctUINT32)bytes,
+ mdl,
+ (gctUINT32)mdl->addr,
+ mdl->dmaHandle);
+
+ if (InUserSpace)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "vmaAddr->0x%x pid->%d",
+ (gctUINT32)mdlMap->vmaAddr,
+ mdlMap->pid);
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeNonPagedMemory
+**
+** Free previously allocated and mapped pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes allocated.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocated memory.
+**
+** gctPOINTER Logical
+** Logical address of the allocated memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ struct task_struct * task;
+
+#ifdef NO_DMA_COHERENT
+ unsigned size;
+ gctPOINTER vaddr;
+#endif /* NO_DMA_COHERENT */
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_FreeNonPagedMemory");
+
+ /* Convert physical address into a pointer to a MDL. */
+ mdl = (PLINUX_MDL) Physical;
+
+ MEMORY_LOCK(Os);
+
+#ifndef NO_DMA_COHERENT
+ dma_free_coherent(gcvNULL,
+ mdl->numPages * PAGE_SIZE,
+ mdl->addr,
+ mdl->dmaHandle);
+#else
+ size = mdl->numPages * PAGE_SIZE;
+ vaddr = mdl->kaddr;
+
+ while (size > 0)
+ {
+ ClearPageReserved(virt_to_page(vaddr));
+
+ vaddr += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
+
+ iounmap(mdl->addr);
+#endif /* NO_DMA_COHERENT */
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if (mdlMap->vmaAddr != gcvNULL)
+ {
+ /* Get the current pointer for the task with stored pid. */
+ task = FIND_TASK_BY_PID(mdlMap->pid);
+
+ if (task != gcvNULL && task->mm != gcvNULL)
+ {
+ down_write(&task->mm->mmap_sem);
+
+ if (do_munmap(task->mm,
+ (unsigned long)mdlMap->vmaAddr,
+ mdl->numPages * PAGE_SIZE) < 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreeNonPagedMemory: "
+ "Unmap Failed ->Mdl->0x%x Logical->0x%x vmaAddr->0x%x",
+ (gctUINT32)mdl,
+ (gctUINT32)mdl->addr,
+ (gctUINT32)mdlMap->vmaAddr);
+ }
+
+ up_write(&task->mm->mmap_sem);
+ }
+
+ mdlMap->vmaAddr = gcvNULL;
+ }
+
+ mdlMap = mdlMap->next;
+ }
+
+ /* Remove the node from global list.. */
+ if (mdl == Os->mdlHead)
+ {
+ if ((Os->mdlHead = mdl->next) == gcvNULL)
+ {
+ Os->mdlTail = gcvNULL;
+ }
+ }
+ else
+ {
+ mdl->prev->next = mdl->next;
+ if (mdl == Os->mdlTail)
+ {
+ Os->mdlTail = mdl->prev;
+ }
+ else
+ {
+ mdl->next->prev = mdl->prev;
+ }
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreeNonPagedMemory: "
+ "Mdl->0x%x Logical->0x%x",
+ (gctUINT32)mdl,
+ (gctUINT32)mdl->addr);
+
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReadRegister
+**
+** Read data from a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** OUTPUT:
+**
+** gctUINT32 * Data
+** Pointer to a variable that receives the data read from the register.
+*/
+gceSTATUS gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Data != NULL);
+
+ *Data = readl((gctUINT8 *)Os->device->registerBase + Address);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteRegister
+**
+** Write data to a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ writel(Data, (gctUINT8 *)Os->device->registerBase + Address);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPageSize
+**
+** Get the system's page size.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * PageSize
+** Pointer to a variable that will receive the system's page size.
+*/
+gceSTATUS gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(PageSize != NULL);
+
+ /* Return the page size. */
+ *PageSize = (gctSIZE_T) PAGE_SIZE;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddressProcess
+**
+** Get the physical system address of a corresponding virtual address for a
+** given process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** gctUINT ProcessID
+** Procedd ID.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+gckOS_GetPhysicalAddressProcess(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT ProcessID,
+ OUT gctUINT32 * Address
+ )
+{
+ return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddress
+**
+** Get the physical system address of a corresponding virtual address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ )
+{
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ /*
+ * Try to search the address in our list.
+ * This could be an mmaped memory.
+ * Search in our list.
+ */
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ /* Check for the logical address match. */
+ if (mdl->addr
+ && (gctUINT32)Logical >= (gctUINT32)mdl->addr
+ && (gctUINT32)Logical < ((gctUINT32)mdl->addr + mdl->numPages*PAGE_SIZE))
+ {
+ if (mdl->dmaHandle)
+ {
+ /* The memory was from coherent area. */
+ *Address = (gctUINT32)mdl->dmaHandle
+ + (gctUINT32)((gctUINT32)Logical - (gctUINT32)mdl->addr);
+ }
+ else if (mdl->pagedMem)
+ {
+ if (mdl->contiguous)
+ {
+ *Address = (gctUINT32)virt_to_phys(mdl->addr)
+ + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
+ }
+ else
+ {
+ *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
+ + ((gctUINT32)Logical - (gctUINT32)mdl->addr)));
+ }
+ }
+ else
+ {
+ *Address = (gctUINT32)virt_to_phys(mdl->addr)
+ + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
+ }
+ break;
+ }
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ /* Is the given address within that range. */
+ if (mdlMap != gcvNULL
+ && mdlMap->vmaAddr != gcvNULL
+ && Logical >= mdlMap->vmaAddr
+ && Logical < (mdlMap->vmaAddr + mdl->numPages * PAGE_SIZE))
+ {
+ if (mdl->dmaHandle)
+ {
+ /* The memory was from coherent area. */
+ *Address = (gctUINT32)mdl->dmaHandle
+ + (gctUINT32)((gctUINT32)Logical
+ - (gctUINT32)mdlMap->vmaAddr);
+ }
+ else if (mdl->pagedMem)
+ {
+ if (mdl->contiguous)
+ {
+ *Address = (gctUINT32)virt_to_phys(mdl->addr)
+ + (gctUINT32)(Logical - mdlMap->vmaAddr);
+ }
+ else
+ {
+ *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
+ + ((gctUINT32)Logical - (gctUINT32)mdlMap->vmaAddr)));
+ }
+ }
+ else
+ {
+ /* Return the kernel virtual pointer based on this. */
+ *Address = (gctUINT32)virt_to_phys(mdl->addr)
+ + (gctUINT32)(Logical - mdlMap->vmaAddr);
+ }
+ break;
+ }
+
+ mdl = mdl->next;
+ }
+
+ /* Subtract base address to get a GPU physical address. */
+ gcmkASSERT(*Address >= Os->baseAddress);
+ *Address -= Os->baseAddress;
+
+ MEMORY_UNLOCK(Os);
+
+ if (mdl == gcvNULL)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPhysical
+**
+** Map a physical address into kernel space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Physical
+** Physical address of the memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the base address of the mapped
+** memory.
+*/
+gceSTATUS gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctPOINTER logical;
+ PLINUX_MDL mdl;
+ gctUINT32 physical;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ MEMORY_LOCK(Os);
+
+ /* Compute true physical address (before subtraction of the baseAddress). */
+ physical = Physical + Os->baseAddress;
+
+ /* Go through our mapping to see if we know this physical address already. */
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl->dmaHandle != 0)
+ {
+ if ((physical >= mdl->dmaHandle)
+ && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
+ )
+ {
+ *Logical = mdl->addr + (physical - mdl->dmaHandle);
+ break;
+ }
+ }
+
+ mdl = mdl->next;
+ }
+
+ if (mdl == gcvNULL)
+ {
+ /* Map memory as cached memory. */
+ request_mem_region(physical, Bytes, "MapRegion");
+ logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
+
+ if (logical == NULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "gckOS_MapMemory: Failed to ioremap");
+
+ MEMORY_UNLOCK(Os);
+
+ /* Out of resources. */
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Return pointer to mapped memory. */
+ *Logical = logical;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "gckOS_MapPhysical: "
+ "Physical->0x%X Bytes->0x%X Logical->0x%X MappingFound->%d",
+ (gctUINT32) Physical,
+ (gctUINT32) Bytes,
+ (gctUINT32) *Logical,
+ mdl ? 1 : 0);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapPhysical
+**
+** Unmap a previously mapped memory region from kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Pointer to the base address of the memory to unmap.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ MEMORY_LOCK(Os);
+
+ mdl = Os->mdlHead;
+
+ while (mdl != gcvNULL)
+ {
+ if (mdl->addr != gcvNULL)
+ {
+ if (Logical >= (gctPOINTER)mdl->addr
+ && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
+ {
+ break;
+ }
+ }
+
+ mdl = mdl->next;
+ }
+
+ if (mdl == gcvNULL)
+ {
+ /* Unmap the memory. */
+ iounmap(Logical);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_UnmapPhysical: "
+ "Logical->0x%x Bytes->0x%x MappingFound(?)->%d",
+ (gctUINT32)Logical,
+ (gctUINT32)Bytes,
+ mdl ? 1 : 0);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateMutex
+**
+** Create a new mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Mutex
+** Pointer to a variable that will hold a pointer to the mutex.
+*/
+gceSTATUS gckOS_CreateMutex(
+ IN gckOS Os,
+ OUT gctPOINTER * Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+ /* Allocate a FAST_MUTEX structure. */
+ *Mutex = (gctPOINTER)kmalloc(sizeof(struct semaphore), GFP_KERNEL);
+
+ if (*Mutex == gcvNULL)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Initialize the semaphore.. Come up in unlocked state. */
+ init_MUTEX(*Mutex);
+
+ /* Return status. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DeleteMutex
+**
+** Delete a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mute to be deleted.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+ /* Delete the fast mutex. */
+ kfree(Mutex);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireMutex
+**
+** Acquire a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be acquired.
+**
+** gctUINT32 Timeout
+** Timeout value specified in milliseconds.
+** Specify the value of gcvINFINITE to keep the thread suspended
+** until the mutex has been acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+ if (Timeout == gcvINFINITE)
+ {
+ down((struct semaphore *) Mutex);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ while (gcvTRUE)
+ {
+ /* Try to acquire the fast mutex. */
+ if (!down_trylock((struct semaphore *) Mutex))
+ {
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ if (Timeout-- == 0) break;
+
+ /* Wait for 1 millisecond. */
+ gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+ }
+
+ /* Timeout. */
+ return gcvSTATUS_TIMEOUT;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseMutex
+**
+** Release an acquired mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+ /* Release the fast mutex. */
+ up((struct semaphore *) Mutex);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchange
+**
+** Atomically exchange a pair of 32-bit values.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctINT32_PTR Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctINT32 NewValue
+** Specifies a new value for the 32-bit value pointed to by Target.
+**
+** OUT gctINT32_PTR OldValue
+** The old value of the 32-bit value pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Exchange the pair of 32-bit values. */
+ *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchangePtr
+**
+** Atomically exchange a pair of pointers.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctPOINTER * Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctPOINTER NewValue
+** Specifies a new value for the pointer pointed to by Target.
+**
+** OUT gctPOINTER * OldValue
+** The old value of the pointer pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Exchange the pair of pointers. */
+ *OldValue = (gctPOINTER) atomic_xchg((atomic_t *) Target, (int) NewValue);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomConstruct
+**
+** Create an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Atom
+** Pointer to a variable receiving the constructed atom.
+*/
+gceSTATUS
+gckOS_AtomConstruct(
+ IN gckOS Os,
+ OUT gctPOINTER * Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Allocate the atom. */
+ gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
+
+ /* Initialize the atom. */
+ atomic_set((atomic_t *) *Atom, 0);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Atom=0x%x", *Atom);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDestroy
+**
+** Destroy an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom to destroy.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomDestroy(
+ IN gckOS Os,
+ OUT gctPOINTER Atom
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Free the atom. */
+ gcmkONERROR(gckOS_Free(Os, Atom));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomGet
+**
+** Get the 32-bit value protected by an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the value of the atom.
+*/
+gceSTATUS
+gckOS_AtomGet(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Return the current value of atom. */
+ *Value = atomic_read((atomic_t *) Atom);
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomIncrement
+**
+** Atomically increment the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomIncrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Increment the atom. */
+ *Value = atomic_inc_return((atomic_t *) Atom) - 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomDecrement
+**
+** Atomically decrement the 32-bit integer value inside an atom.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctPOINTER Atom
+** Pointer to the atom.
+**
+** OUTPUT:
+**
+** gctINT32_PTR Value
+** Pointer to a variable the receives the original value of the atom.
+*/
+gceSTATUS
+gckOS_AtomDecrement(
+ IN gckOS Os,
+ IN gctPOINTER Atom,
+ OUT gctINT32_PTR Value
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
+
+ /* Decrement the atom. */
+ *Value = atomic_dec_return((atomic_t *) Atom) + 1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Value=%d", *Value);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_Delay
+**
+** Delay execution of the current thread for a number of milliseconds.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Delay
+** Delay to sleep, specified in milliseconds.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ )
+{
+ struct timeval now;
+ unsigned long jiffies;
+
+ if (Delay > 0)
+ {
+ /* Convert milliseconds into seconds and microseconds. */
+ now.tv_sec = Delay / 1000;
+ now.tv_usec = (Delay % 1000) * 1000;
+
+ /* Convert timeval to jiffies. */
+ jiffies = timeval_to_jiffies(&now);
+
+ /* Schedule timeout. */
+ schedule_timeout_interruptible(jiffies);
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MemoryBarrier
+**
+** Make sure the CPU has executed everything up to this point and the data got
+** written to the specified pointer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of memory that needs to be barriered.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ )
+{
+ /* Verify thearguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ mb();
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemory
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ return gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical);
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemoryEx
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL Contiguous
+** Need contiguous memory or not.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ gctINT numPages;
+ gctINT i;
+ PLINUX_MDL mdl;
+ gctSTRING addr;
+ gctSIZE_T bytes;
+
+ gcmkHEADER_ARG("Os=0x%0x Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+ bytes = gcmALIGN(Bytes, PAGE_SIZE);
+
+ numPages = GetPageCount(bytes, 0);
+
+ MEMORY_LOCK(Os);
+
+ if (Contiguous)
+ {
+ addr = (char *)__get_free_pages(GFP_ATOMIC | GFP_DMA, GetOrder(numPages));
+ }
+ else
+ {
+ addr = vmalloc(bytes);
+ }
+
+ if (!addr)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocatePagedMemoryEx: "
+ "Can't allocate memorry for size->0x%x",
+ (gctUINT32)bytes);
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdl = _CreateMdl(current->tgid);
+
+ if (mdl == gcvNULL)
+ {
+ if (Contiguous)
+ {
+ free_pages((unsigned int) addr, GetOrder(mdl->numPages));
+ }
+ else
+ {
+ vfree(addr);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdl->dmaHandle = 0;
+ mdl->addr = addr;
+ mdl->numPages = numPages;
+ mdl->pagedMem = 1;
+ mdl->contiguous = Contiguous;
+
+ for (i = 0; i < mdl->numPages; i++)
+ {
+ struct page *page;
+
+ if (mdl->contiguous)
+ {
+ page = virt_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
+ }
+ else
+ {
+ page = vmalloc_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
+ }
+
+ SetPageReserved(page);
+ flush_dcache_page(page);
+ }
+
+ /* Return physical address. */
+ *Physical = (gctPHYS_ADDR) mdl;
+
+ /*
+ * Add this to a global list.
+ * Will be used by get physical address
+ * and mapuser pointer functions.
+ */
+ if (!Os->mdlHead)
+ {
+ /* Initialize the queue. */
+ Os->mdlHead = Os->mdlTail = mdl;
+ }
+ else
+ {
+ /* Add to tail. */
+ mdl->prev = Os->mdlTail;
+ Os->mdlTail->next = mdl;
+ Os->mdlTail = mdl;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "%s: Bytes=%lu Mdl=0x%08x Logical=0x%08x",
+ __FUNCTION__, bytes, mdl, mdl->addr);
+
+ /* Success. */
+ gcmkHEADER_ARG("*Physical=0x%08x", *Physical);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreePagedMemory
+**
+** Free memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ )
+{
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ gctSTRING addr;
+ gctINT i;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_FreePagedMemory");
+
+ addr = mdl->addr;
+
+ MEMORY_LOCK(Os);
+
+ for (i = 0; i < mdl->numPages; i++)
+ {
+ if (mdl->contiguous)
+ {
+ ClearPageReserved(virt_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
+ }
+ else
+ {
+ ClearPageReserved(vmalloc_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
+ }
+ }
+
+ if (mdl->contiguous)
+ {
+ free_pages((unsigned long)mdl->addr, GetOrder(mdl->numPages));
+ }
+ else
+ {
+ vfree(mdl->addr);
+ }
+
+ /* Remove the node from global list. */
+ if (mdl == Os->mdlHead)
+ {
+ if ((Os->mdlHead = mdl->next) == gcvNULL)
+ {
+ Os->mdlTail = gcvNULL;
+ }
+ }
+ else
+ {
+ mdl->prev->next = mdl->next;
+
+ if (mdl == Os->mdlTail)
+ {
+ Os->mdlTail = mdl->prev;
+ }
+ else
+ {
+ mdl->next->prev = mdl->prev;
+ }
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Free the structure... */
+ gcmkVERIFY_OK(_DestroyMdl(mdl));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreePagedMemory: Bytes->0x%x, Mdl->0x%x",
+ (gctUINT32)Bytes,
+ (gctUINT32)mdl);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_LockPages
+**
+** Lock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the address of the mapped
+** memory.
+**
+** gctSIZE_T * PageCount
+** Pointer to a variable that receives the number of pages required for
+** the page table according to the GPU page size.
+*/
+gceSTATUS gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ PLINUX_MDL mdl;
+ PLINUX_MDL_MAP mdlMap;
+ gctSTRING addr;
+ unsigned long start;
+ unsigned long pfn;
+ gctINT i;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(PageCount != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_LockPages");
+
+ mdl = (PLINUX_MDL) Physical;
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = FindMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ mdlMap = _CreateMdlMap(mdl, current->tgid);
+
+ if (mdlMap == gcvNULL)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ down_write(¤t->mm->mmap_sem);
+
+ mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(NULL,
+ 0L,
+ mdl->numPages * PAGE_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ 0);
+
+ up_write(¤t->mm->mmap_sem);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: "
+ "vmaAddr->0x%x for phys_addr->0x%x",
+ (gctUINT32)mdlMap->vmaAddr,
+ (gctUINT32)mdl);
+
+ if (mdlMap->vmaAddr == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: do_mmap_pgoff error");
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
+
+ if (mdlMap->vma == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "find_vma error");
+
+ mdlMap->vmaAddr = gcvNULL;
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ mdlMap->vma->vm_flags |= VM_RESERVED;
+ /* Make this mapping non-cached. */
+ mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
+
+ addr = mdl->addr;
+
+ /* Now map all the vmalloc pages to this user address. */
+ down_write(¤t->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(¤t->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(¤t->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(¤t->mm->mmap_sem);
+ }
+
+ /* Convert pointer to MDL. */
+ *Logical = mdlMap->vmaAddr;
+
+ /* Return the page number according to the GPU page size. */
+ gcmkASSERT((PAGE_SIZE % 4096) == 0);
+ gcmkASSERT((PAGE_SIZE / 4096) >= 1);
+
+ *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: "
+ "gctPHYS_ADDR->0x%x Bytes->0x%x Logical->0x%x pid->%d",
+ (gctUINT32)Physical,
+ (gctUINT32)Bytes,
+ (gctUINT32)*Logical,
+ mdlMap->pid);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPages
+**
+** Map paged memory into a page table.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T PageCount
+** Number of pages required for the physical address.
+**
+** gctPOINTER PageTable
+** Pointer to the page table to fill in.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ )
+{
+ PLINUX_MDL mdl;
+ gctUINT32* table;
+ gctSTRING addr;
+ gctINT i = 0;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_MapPages");
+
+ /* Convert pointer to MDL. */
+ mdl = (PLINUX_MDL)Physical;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_MapPages: "
+ "Physical->0x%x PageCount->0x%x PagedMemory->?%d",
+ (gctUINT32)Physical,
+ (gctUINT32)PageCount,
+ mdl->pagedMem);
+
+ MEMORY_LOCK(Os);
+
+ table = (gctUINT32 *)PageTable;
+
+ /* Get all the physical addresses and store them in the page table. */
+
+ addr = mdl->addr;
+
+ if (mdl->pagedMem)
+ {
+ /* Try to get the user pages so DMA can happen. */
+ while (PageCount-- > 0)
+ {
+ if (mdl->contiguous)
+ {
+ *table++ = virt_to_phys(addr);
+ }
+ else
+ {
+ *table++ = page_to_phys(vmalloc_to_page(addr));
+ }
+
+ addr += 4096;
+ i++;
+ }
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "We should not get this call for Non Paged Memory!");
+
+ while (PageCount-- > 0)
+ {
+ *table++ = (gctUINT32)virt_to_phys(addr);
+ addr += 4096;
+ }
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnlockPages
+**
+** Unlock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** gctPOINTER Logical
+** Address of the mapped memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ PLINUX_MDL_MAP mdlMap;
+ PLINUX_MDL mdl = (PLINUX_MDL)Physical;
+ struct task_struct * task;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ /* Make sure there is already a mapping...*/
+ gcmkVERIFY_ARGUMENT(mdl->addr != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_UnlockPages");
+
+ MEMORY_LOCK(Os);
+
+ mdlMap = mdl->maps;
+
+ while (mdlMap != gcvNULL)
+ {
+ if (mdlMap->vmaAddr != gcvNULL)
+ {
+ /* Get the current pointer for the task with stored pid. */
+ task = FIND_TASK_BY_PID(mdlMap->pid);
+
+ if (task != gcvNULL && task->mm != gcvNULL)
+ {
+ down_write(&task->mm->mmap_sem);
+ do_munmap(task->mm, (unsigned long)Logical, mdl->numPages * PAGE_SIZE);
+ up_write(&task->mm->mmap_sem);
+ }
+
+ mdlMap->vmaAddr = gcvNULL;
+ }
+
+ mdlMap = mdlMap->next;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_AllocateContiguous
+**
+** Allocate memory from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that receives the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the logical address of the
+** memory allocation.
+*/
+gceSTATUS gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ /* Same as non-paged memory for now. */
+ return gckOS_AllocateNonPagedMemory(Os,
+ InUserSpace,
+ Bytes,
+ Physical,
+ Logical
+ );
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeContiguous
+**
+** Free memory allocated from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctPOINTER Logical
+** Logicval address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ /* Same of non-paged memory for now. */
+ return gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical);
+}
+
+/******************************************************************************
+**
+** gckOS_GetKernelLogical
+**
+** Return the kernel logical pointer that corresponods to the specified
+** hardware address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Hardware physical address.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the pointer in kernel address space.
+*/
+gceSTATUS
+gckOS_GetKernelLogical(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gckGALDEVICE device;
+ gckKERNEL kernel;
+ gcePOOL pool;
+ gctUINT32 offset;
+ gctPOINTER logical;
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Os->device;
+
+ /* Kernel shortcut. */
+ kernel = device->kernel;
+
+ /* Split the memory address into a pool type and offset. */
+ gcmkERR_BREAK(gckHARDWARE_SplitMemory(
+ kernel->hardware, Address, &pool, &offset
+ ));
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ logical = device->contiguousBase;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Build logical address of specified address. */
+ * KernelPointer = ((gctUINT8_PTR) logical) + offset;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapUserPointer
+**
+** Map a pointer from the user process into the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be mapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be mapped.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the mapped pointer in kernel address
+** space.
+*/
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+#if NO_USER_DIRECT_ACCESS_FROM_KERNEL
+ gctPOINTER buf = gcvNULL;
+ gctUINT32 len;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+ buf = kmalloc(Size, GFP_KERNEL);
+ if (buf == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Failed to allocate memory at line %d in %s.",
+ __LINE__, __FILE__
+ );
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ len = copy_from_user(buf, Pointer, Size);
+ if (len != 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Failed to copy data from user at line %d in %s.",
+ __LINE__, __FILE__
+ );
+
+ if (buf != gcvNULL)
+ {
+ kfree(buf);
+ }
+
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ *KernelPointer = buf;
+#else
+ *KernelPointer = Pointer;
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserPointer
+**
+** Unmap a user process pointer from the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be unmapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be unmapped.
+**
+** gctPOINTER KernelPointer
+** Pointer in kernel address space that needs to be unmapped.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ )
+{
+#if NO_USER_DIRECT_ACCESS_FROM_KERNEL
+ gctUINT32 len;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
+
+ len = copy_to_user(Pointer, KernelPointer, Size);
+
+ kfree(KernelPointer);
+
+ if (len != 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Failed to copy data to user at line %d in %s.",
+ __LINE__, __FILE__
+ );
+ return gcvSTATUS_GENERIC_IO;
+ }
+#endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteMemory
+**
+** Write data to a memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of the memory to write to.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != NULL);
+
+ /* Write memory. */
+ writel(Data, (gctUINT8 *)Address);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateSignal
+**
+** Create a new signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctSIGNAL * Signal
+** Pointer to a variable receiving the created gctSIGNAL.
+*/
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ )
+{
+#if USE_NEW_LINUX_SIGNAL
+ return gcvSTATUS_NOT_SUPPORTED;
+#else
+ gcsSIGNAL_PTR signal;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+ /* Create an event structure. */
+ signal = (gcsSIGNAL_PTR)kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL);
+
+ if (signal == gcvNULL)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ signal->manualReset = ManualReset;
+
+ init_completion(&signal->event);
+
+ atomic_set(&signal->ref, 1);
+
+ *Signal = (gctSIGNAL) signal;
+
+ return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySignal
+**
+** Destroy a signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+#if USE_NEW_LINUX_SIGNAL
+ return gcvSTATUS_NOT_SUPPORTED;
+#else
+ gcsSIGNAL_PTR signal;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+ signal = (gcsSIGNAL_PTR) Signal;
+
+ if (atomic_dec_and_test(&signal->ref))
+ {
+ /* Free the sgianl. */
+ kfree(Signal);
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+#endif
+}
+
+/*******************************************************************************
+**
+** gckOS_Signal
+**
+** Set a state of the specified signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ )
+{
+#if USE_NEW_LINUX_SIGNAL
+ return gcvSTATUS_NOT_SUPPORTED;
+#else
+ gcsSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x State=%d", Os, Signal, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcsSIGNAL_PTR) Signal;
+
+ /* Set the new state of the event. */
+ if (signal->manualReset)
+ {
+ if (State)
+ {
+ /* Set the event to a signaled state. */
+ complete_all(&signal->event);
+ }
+ else
+ {
+ /* Set the event to an unsignaled state. */
+ INIT_COMPLETION(signal->event);
+ }
+ }
+ else
+ {
+ if (State)
+ {
+ /* Set the event to a signaled state. */
+ complete(&signal->event);
+
+ }
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+#endif
+}
+
+#if USE_NEW_LINUX_SIGNAL
+/*******************************************************************************
+**
+** gckOS_UserSignal
+**
+** Set the specified signal which is owned by a process to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ )
+{
+ gceSTATUS status;
+ gctINT result;
+ struct task_struct * task;
+ struct siginfo info;
+
+ task = FIND_TASK_BY_PID((pid_t) Process);
+
+ if (task != gcvNULL)
+ {
+ /* Fill in the siginfo structure. */
+ info.si_signo = Os->device->signal;
+ info.si_errno = 0;
+ info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
+ info.si_ptr = Signal;
+
+ /* Send the signal. */
+ if ((result = send_sig_info(Os->device->signal, &info, task)) < 0)
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "%s(%d): send_sig_info failed.",
+ __FUNCTION__, __LINE__);
+ }
+ else
+ {
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ }
+ else
+ {
+ status = gcvSTATUS_GENERIC_IO;
+
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "%s(%d): find_task_by_pid failed.",
+ __FUNCTION__, __LINE__);
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignal
+**
+** Wait for a signal to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapSignal
+**
+** Map a signal in to the current process space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to tha gctSIGNAL to map.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** gctSIGNAL * MappedSignal
+** Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ )
+{
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+#else
+
+/*******************************************************************************
+**
+** gckOS_UserSignal
+**
+** Set the specified signal which is owned by a process to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process
+ )
+{
+ gceSTATUS status;
+ gctSIGNAL signal;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=%d Process=0x%x",
+ Os, (gctINT) Signal, Process);
+
+ /* Map the signal into kernel space. */
+ gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
+
+ /* Signal. */
+ status = gckOS_Signal(Os, signal, gcvTRUE);
+ gcmkFOOTER();
+ return status;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignal
+**
+** Wait for a signal to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctUINT timeout;
+ gctUINT rc;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x Wait=%u", Os, Signal, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcsSIGNAL_PTR) Signal;
+
+ /* Convert wait to milliseconds. */
+ timeout = (Wait == gcvINFINITE) ? MAX_SCHEDULE_TIMEOUT : Wait*HZ/1000;
+
+ /* Linux bug ? */
+ if (!signal->manualReset && timeout == 0) timeout = 1;
+
+ rc = wait_for_completion_interruptible_timeout(&signal->event, timeout);
+ status = ((rc == 0) && !signal->event.done) ? gcvSTATUS_TIMEOUT
+ : gcvSTATUS_OK;
+
+ /* Return status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapSignal
+**
+** Map a signal in to the current process space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to tha gctSIGNAL to map.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** gctSIGNAL * MappedSignal
+** Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ )
+{
+ gctINT signalID;
+ gcsSIGNAL_PTR signal;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x Process=0x%x", Os, Signal, Process);
+
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+ gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
+
+ signalID = (gctINT) Signal - 1;
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (signalID >= 0 && signalID < Os->signal.tableLen)
+ {
+ /* It is a user space signal. */
+ signal = Os->signal.table[signalID];
+
+ if (signal == gcvNULL)
+ {
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+ }
+ else
+ {
+ /* It is a kernel space signal structure. */
+ signal = (gcsSIGNAL_PTR) Signal;
+ }
+
+ if (atomic_inc_return(&signal->ref) <= 1)
+ {
+ /* The previous value is 0, it has been deleted. */
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Release the mutex. */
+ gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+ *MappedSignal = (gctSIGNAL) signal;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*MappedSignal=0x%x", *MappedSignal);
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateUserSignal
+**
+** Create a new signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+**
+** OUTPUT:
+**
+** gctINT * SignalID
+** Pointer to a variable receiving the created signal's ID.
+*/
+gceSTATUS
+gckOS_CreateUserSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctINT * SignalID
+ )
+{
+ gcsSIGNAL_PTR signal;
+ gctINT unused, currentID, tableLen;
+ gctPOINTER * table;
+ gctINT i;
+ gceSTATUS status;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%0x ManualReset=%d", Os, ManualReset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(SignalID != gcvNULL);
+
+ /* Lock the table. */
+ gcmkONERROR(
+ gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ if (Os->signal.unused < 1)
+ {
+ /* Enlarge the table. */
+ table = (gctPOINTER *) kmalloc(
+ sizeof(gctPOINTER) * (Os->signal.tableLen + USER_SIGNAL_TABLE_LEN_INIT),
+ GFP_KERNEL);
+
+ if (table == gcvNULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ memset(table + Os->signal.tableLen, 0, sizeof(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
+ memcpy(table, Os->signal.table, sizeof(gctPOINTER) * Os->signal.tableLen);
+
+ /* Release the old table. */
+ kfree(Os->signal.table);
+
+ /* Update the table. */
+ Os->signal.table = table;
+ Os->signal.currentID = Os->signal.tableLen;
+ Os->signal.tableLen += USER_SIGNAL_TABLE_LEN_INIT;
+ Os->signal.unused += USER_SIGNAL_TABLE_LEN_INIT;
+ }
+
+ table = Os->signal.table;
+ currentID = Os->signal.currentID;
+ tableLen = Os->signal.tableLen;
+ unused = Os->signal.unused;
+
+ /* Create a new signal. */
+ gcmkONERROR(
+ gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
+
+ /* Save the process ID. */
+ signal->process = (gctHANDLE) current->tgid;
+
+ table[currentID] = signal;
+
+ /* Plus 1 to avoid NULL claims. */
+ *SignalID = currentID + 1;
+
+ /* Update the currentID. */
+ if (--unused > 0)
+ {
+ for (i = 0; i < tableLen; i++)
+ {
+ if (++currentID >= tableLen)
+ {
+ /* Wrap to the begin. */
+ currentID = 0;
+ }
+
+ if (table[currentID] == gcvNULL)
+ {
+ break;
+ }
+ }
+ }
+
+ Os->signal.table = table;
+ Os->signal.currentID = currentID;
+ Os->signal.tableLen = tableLen;
+ Os->signal.unused = unused;
+
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+ gcmkFOOTER_ARG("*SignalID=%d", gcmOPT_VALUE(SignalID));
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroyUserSignal
+**
+** Destroy a signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** The signal's ID.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroyUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x SignalID=%d", Os, SignalID);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkONERROR(
+ gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+
+ acquired = gcvTRUE;
+
+ if (SignalID < 1 || SignalID > Os->signal.tableLen)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: invalid signal->%d.",
+ (gctINT) SignalID
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ SignalID -= 1;
+
+ signal = Os->signal.table[SignalID];
+
+ if (signal == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: signal is NULL."
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ /* Check to see if the process is the owner of the signal. */
+ if (signal->process != (gctHANDLE) current->tgid)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: process id doesn't match. ",
+ "signal->process: %d, current->tgid: %d",
+ signal->process,
+ current->tgid);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ gcmkONERROR(
+ gckOS_DestroySignal(Os, signal));
+
+ /* Update the table. */
+ Os->signal.table[SignalID] = gcvNULL;
+ if (Os->signal.unused++ == 0)
+ {
+ Os->signal.currentID = SignalID;
+ }
+
+ gcmkVERIFY_OK(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitUserSignal
+**
+** Wait for a signal used in the user mode to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** Signal ID.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x SignalID=%d Wait=%u", Os, SignalID, Wait);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if (SignalID < 1 || SignalID > Os->signal.tableLen)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitSignal: invalid signal.",
+ SignalID
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ SignalID -= 1;
+
+ signal = Os->signal.table[SignalID];
+
+ gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+ acquired = gcvFALSE;
+
+ if (signal == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitSignal: signal is NULL."
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ if (signal->process != (gctHANDLE) current->tgid)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitUserSignal: process id doesn't match. "
+ "signal->process: %d, current->tgid: %d",
+ signal->process,
+ current->tgid);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+
+do{
+ status = gckOS_WaitSignal(Os, signal, Wait==gcvINFINITE?5000:Wait);
+if(Wait==gcvINFINITE&&status==gcvSTATUS_TIMEOUT){gcmkPRINT("$$FLUSH$$");}
+}while(status==gcvSTATUS_TIMEOUT&&Wait==gcvINFINITE);
+
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_SignalUserSignal
+**
+** Set a state of the specified signal to be used in the user space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctINT SignalID
+** SignalID.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SignalUserSignal(
+ IN gckOS Os,
+ IN gctINT SignalID,
+ IN gctBOOL State
+ )
+{
+ gceSTATUS status;
+ gcsSIGNAL_PTR signal;
+ gctBOOL acquired = gcvFALSE;
+
+ gcmkHEADER_ARG("Os=0x%x SignalID=%d State=%d", Os, SignalID, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
+ acquired = gcvTRUE;
+
+ if ((SignalID < 1)
+ || (SignalID > Os->signal.tableLen)
+ )
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
+ "gckOS_WaitSignal: invalid signal->%d.", SignalID);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ SignalID -= 1;
+
+ signal = Os->signal.table[SignalID];
+
+ gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
+ acquired = gcvFALSE;
+
+ if (signal == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_WaitSignal: signal is NULL."
+ );
+
+ gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
+ }
+
+ if (signal->process != (gctHANDLE) current->tgid)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_DestroyUserSignal: process id doesn't match. ",
+ "signal->process: %d, current->tgid: %d",
+ signal->process,
+ current->tgid);
+
+ gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
+ }
+
+ status = gckOS_Signal(Os, signal, State);
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+
+OnError:
+ if (acquired)
+ {
+ /* Release the mutex. */
+ gcmkONERROR(
+ gckOS_ReleaseMutex(Os, Os->signal.lock));
+ }
+
+ /* Return the staus. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckOS_CleanProcessSignal(
+ gckOS Os,
+ gctHANDLE Process
+ )
+{
+ gctINT signal;
+
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
+ Os->signal.lock,
+ gcvINFINITE
+ ));
+
+ if (Os->signal.unused == Os->signal.tableLen)
+ {
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
+ Os->signal.lock
+ ));
+
+ return gcvSTATUS_OK;
+ }
+
+ for (signal = 0; signal < Os->signal.tableLen; signal++)
+ {
+ if (Os->signal.table[signal] != gcvNULL &&
+ ((gcsSIGNAL_PTR)Os->signal.table[signal])->process == Process)
+ {
+ gckOS_DestroySignal(Os, Os->signal.table[signal]);
+
+ /* Update the signal table. */
+ Os->signal.table[signal] = gcvNULL;
+ if (Os->signal.unused++ == 0)
+ {
+ Os->signal.currentID = signal;
+ }
+ }
+ }
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
+ Os->signal.lock
+ ));
+
+ return gcvSTATUS_OK;
+}
+
+#endif /* USE_NEW_LINUX_SIGNAL */
+
+/*******************************************************************************
+**
+** gckOS_MapUserMemory
+**
+** Lock down a user buffer and return an DMA'able address to be used by the
+** hardware to access it.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to lock down.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to lock down.
+**
+** OUTPUT:
+**
+** gctPOINTER * Info
+** Pointer to variable receiving the information record required by
+** gckOS_UnmapUserMemory.
+**
+** gctUINT32_PTR Address
+** Pointer to a variable that will receive the address DMA'able by the
+** hardware.
+*/
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ )
+{
+ gceSTATUS status;
+ gctSIZE_T pageCount, i, j;
+ gctUINT32_PTR pageTable;
+ gctUINT32 address;
+ gctUINT32 start, end, memory;
+ gctINT result = 0;
+
+ gcsPageInfo_PTR info = gcvNULL;
+ struct page **pages = gcvNULL;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] enter."
+ );
+
+ do
+ {
+ memory = (gctUINT32) Memory;
+
+ /* Get the number of required pages. */
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = memory >> PAGE_SHIFT;
+ pageCount = end - start;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] pageCount: %d.",
+ pageCount
+ );
+
+ /* Invalid argument. */
+ if (pageCount == 0)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Overflow. */
+ if ((memory + Size) < memory)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ MEMORY_MAP_LOCK(Os);
+
+ /* Allocate the Info struct. */
+ info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL);
+
+ if (info == gcvNULL)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ break;
+ }
+
+ /* Allocate the array of page addresses. */
+ pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL);
+
+ if (pages == gcvNULL)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+ break;
+ }
+
+ /* Get the user pages. */
+ down_read(¤t->mm->mmap_sem);
+ result = get_user_pages(current,
+ current->mm,
+ memory & PAGE_MASK,
+ pageCount,
+ 1,
+ 0,
+ pages,
+ NULL
+ );
+ up_read(¤t->mm->mmap_sem);
+
+ if (result <=0 || result < pageCount)
+ {
+ struct vm_area_struct *vma;
+
+ vma = find_vma(current->mm, memory);
+
+ if (vma && (vma->vm_flags & VM_PFNMAP) )
+ {
+ do
+ {
+ pte_t * pte;
+ spinlock_t * ptl;
+ unsigned long pfn;
+
+ pgd_t * pgd = pgd_offset(current->mm, memory);
+ pud_t * pud = pud_alloc(current->mm, pgd, memory);
+ if (pud)
+ {
+ pmd_t * pmd = pmd_alloc(current->mm, pud, memory);
+ if (pmd)
+ {
+ pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
+ if (!pte)
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ pfn = pte_pfn(*pte);
+ *Address = ((pfn << PAGE_SHIFT) | (((unsigned long)Memory) & ~PAGE_MASK))
+ - Os->baseAddress;
+ *Info = gcvNULL;
+
+ pte_unmap_unlock(pte, ptl);
+
+ /* Release page info struct. */
+ if (info != gcvNULL)
+ {
+ /* Free the page info struct. */
+ kfree(info);
+ }
+
+ if (pages != gcvNULL)
+ {
+ /* Free the page table. */
+ kfree(pages);
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ *Address = ~0;
+ *Info = gcvNULL;
+
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+ else
+ {
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ break;
+ }
+ }
+
+ for (i = 0; i < pageCount; i++)
+ {
+ /* Flush the data cache. */
+#ifdef ANDROID
+ dma_sync_single_for_device(
+ gcvNULL,
+ page_to_phys(pages[i]),
+ PAGE_SIZE,
+ DMA_TO_DEVICE);
+#else
+ flush_dcache_page(pages[i]);
+#endif
+ }
+
+ /* Allocate pages inside the page table. */
+ gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernel->mmu,
+ pageCount * (PAGE_SIZE/4096),
+ (gctPOINTER *) &pageTable,
+ &address));
+
+ /* Fill the page table. */
+ for (i = 0; i < pageCount; i++)
+ {
+ /* Get the physical address from page struct. */
+ pageTable[i * (PAGE_SIZE/4096)] = page_to_phys(pages[i]);
+
+ for (j = 1; j < (PAGE_SIZE/4096); j++)
+ {
+ pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] pages[%d]: 0x%x, pageTable[%d]: 0x%x.",
+ i, pages[i],
+ i, pageTable[i]);
+ }
+
+ /* Save pointer to page table. */
+ info->pageTable = pageTable;
+ info->pages = pages;
+
+ *Info = (gctPOINTER) info;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] info->pages: 0x%x, info->pageTable: 0x%x, info: 0x%x.",
+ info->pages,
+ info->pageTable,
+ info
+ );
+
+ /* Return address. */
+ *Address = address + (memory & ~PAGE_MASK);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] Address: 0x%x.",
+ *Address
+ );
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error occured: %d.",
+ status
+ );
+
+ /* Release page array. */
+ if (result > 0 && pages != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error: page table is freed."
+ );
+
+ for (i = 0; i < result; i++)
+ {
+ if (pages[i] == gcvNULL)
+ {
+ break;
+ }
+#ifdef ANDROID
+ dma_sync_single_for_device(
+ gcvNULL,
+ page_to_phys(pages[i]),
+ PAGE_SIZE,
+ DMA_FROM_DEVICE);
+#endif
+ page_cache_release(pages[i]);
+ }
+ }
+
+ if (pages != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error: pages is freed."
+ );
+
+ /* Free the page table. */
+ kfree(pages);
+ info->pages = gcvNULL;
+ }
+
+ /* Release page info struct. */
+ if (info != gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] error: info is freed."
+ );
+
+ /* Free the page info struct. */
+ kfree(info);
+ *Info = gcvNULL;
+ }
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] leave."
+ );
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserMemory
+**
+** Unlock a user buffer and that was previously locked down by
+** gckOS_MapUserMemory.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to unlock.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to unlock.
+**
+** gctPOINTER Info
+** Information record returned by gckOS_MapUserMemory.
+**
+** gctUINT32_PTR Address
+** The address returned by gckOS_MapUserMemory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ )
+{
+ gceSTATUS status;
+ gctUINT32 memory, start, end;
+ gcsPageInfo_PTR info;
+ gctSIZE_T pageCount, i;
+ struct page **pages;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] enter."
+ );
+
+ do
+ {
+ info = (gcsPageInfo_PTR) Info;
+
+ if (info == gcvNULL)
+ {
+ return gcvSTATUS_OK;
+ }
+
+ pages = info->pages;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] info: 0x%x, pages: 0x%x.",
+ info,
+ pages
+ );
+
+ /* Invalid page array. */
+ if (pages == gcvNULL)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ memory = (gctUINT32) Memory;
+ end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = memory >> PAGE_SHIFT;
+ pageCount = end - start;
+
+ /* Overflow. */
+ if ((memory + Size) < memory)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Invalid argument. */
+ if (pageCount == 0)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] memory: 0x%x, pageCount: %d, pageTable: 0x%x.",
+ memory,
+ pageCount,
+ info->pageTable
+ );
+
+ MEMORY_MAP_LOCK(Os);
+
+ /* Free the pages from the MMU. */
+ gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernel->mmu,
+ info->pageTable,
+ pageCount * (PAGE_SIZE/4096)
+ ));
+
+ /* Release the page cache. */
+ for (i = 0; i < pageCount; i++)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] pages[%d]: 0x%x.",
+ i,
+ pages[i]
+ );
+
+ if (!PageReserved(pages[i]))
+ {
+ SetPageDirty(pages[i]);
+ }
+
+#ifdef ANDROID
+ dma_sync_single_for_device(
+ gcvNULL,
+ page_to_phys(pages[i]),
+ PAGE_SIZE,
+ DMA_FROM_DEVICE);
+#endif
+ page_cache_release(pages[i]);
+ }
+
+ /* Success. */
+ status = gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ if (info != gcvNULL)
+ {
+ /* Free the page array. */
+ if (info->pages != gcvNULL)
+ {
+ kfree(info->pages);
+ }
+
+ kfree(info);
+ }
+
+ MEMORY_MAP_UNLOCK(Os);
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetBaseAddress
+**
+** Get the base address for the physical memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR BaseAddress
+** Pointer to a variable that will receive the base address.
+*/
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Return base address. */
+ *BaseAddress = Os->baseAddress;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ disable_irq(Os->device->irqLine);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ enable_irq(Os->device->irqLine);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkVERIFY_ARGUMENT(Destination != NULL);
+ gcmkVERIFY_ARGUMENT(Source != NULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memcpy(Destination, Source, Bytes);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ZeroMemory(
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkHEADER_ARG("Memory=0x%x Bytes=%lu", Memory, Bytes);
+
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memset(Memory, 0, Bytes);
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+#if gcdkUSE_MEMORY_RECORD
+MEMORY_RECORD_PTR
+CreateMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ )
+{
+ MEMORY_RECORD_PTR mr;
+
+ mr = (MEMORY_RECORD_PTR)kmalloc(sizeof(struct MEMORY_RECORD), GFP_ATOMIC);
+ if (mr == gcvNULL) return gcvNULL;
+
+ MEMORY_LOCK(Os);
+
+ mr->node = Node;
+
+ mr->prev = List->prev;
+ mr->next = List;
+ List->prev->next = mr;
+ List->prev = mr;
+
+ MEMORY_UNLOCK(Os);
+
+ return mr;
+}
+
+void
+DestoryMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR Mr
+ )
+{
+ MEMORY_LOCK(Os);
+
+ Mr->prev->next = Mr->next;
+ Mr->next->prev = Mr->prev;
+
+ MEMORY_UNLOCK(Os);
+
+ kfree(Mr);
+}
+
+MEMORY_RECORD_PTR
+FindMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ )
+{
+ MEMORY_RECORD_PTR mr;
+
+ MEMORY_LOCK(Os);
+
+ mr = List->next;
+
+ while (mr != List)
+ {
+ if (mr->node == Node)
+ {
+ MEMORY_UNLOCK(Os);
+
+ return mr;
+ }
+
+ mr = mr->next;
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ return gcvNULL;
+}
+
+void
+FreeAllMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List
+ )
+{
+ MEMORY_RECORD_PTR mr;
+ gctUINT i = 0;
+
+ MEMORY_LOCK(Os);
+
+ while (List->next != List)
+ {
+ mr = List->next;
+
+ mr->prev->next = mr->next;
+ mr->next->prev = mr->prev;
+
+ i++;
+
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "Unfreed %s memory: node: %p",
+ (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)?
+ "video" : (mr->node->Virtual.contiguous)?
+ "contiguous" : "virtual",
+ mr->node);
+
+ while (gcvTRUE)
+ {
+ if (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
+ {
+ if (mr->node->VidMem.locked == 0) break;
+ }
+ else
+ {
+ if (mr->node->Virtual.locked == 0) break;
+ }
+
+ gckVIDMEM_Unlock(mr->node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
+ }
+
+ gckVIDMEM_Free(mr->node);
+
+ kfree(mr);
+
+ MEMORY_LOCK(Os);
+ }
+
+ MEMORY_UNLOCK(Os);
+
+ if (i > 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "======== Total %d unfreed video/contiguous/virtual memory ========", i);
+ }
+}
+#endif
+
+/*******************************************************************************
+** gckOS_CacheFlush
+**
+** Flush the cache for the specified addresses. The GPU is going to need the
+** data. If the system is allocating memory as non-cachable, this function can
+** be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctHANDLE Process
+** Process handle Logical belongs to or gcvNULL if Logical belongs to
+** the kernel.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheFlush(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** gckOS_CacheInvalidate
+**
+** Flush the cache for the specified addresses and invalidate the lines as
+** well. The GPU is going to need and modify the data. If the system is
+** allocating memory as non-cachable, this function can be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctHANDLE Process
+** Process handle Logical belongs to or gcvNULL if Logical belongs to
+** the kernel.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheInvalidate(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+********************************* Broadcasting *********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Broadcast
+**
+** System hook for broadcast events from the kernel driver.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gckHARDWARE Hardware
+** Pointer to the gckHARDWARE object.
+**
+** gceBROADCAST Reason
+** Reason for the broadcast. Can be one of the following values:
+**
+** gcvBROADCAST_GPU_IDLE
+** Broadcasted when the kernel driver thinks the GPU might be
+** idle. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_COMMIT
+** Broadcasted when any client process commits a command
+** buffer. This can be used to handle power management.
+**
+** gcvBROADCAST_GPU_STUCK
+** Broadcasted when the kernel driver hits the timeout waiting
+** for the GPU.
+**
+** gcvBROADCAST_FIRST_PROCESS
+** First process is trying to connect to the kernel.
+**
+** gcvBROADCAST_LAST_PROCESS
+** Last process has detached from the kernel.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ )
+{
+ gceSTATUS status;
+ gctUINT32 idle = 0, dma = 0, axi = 0, read0 = 0, read1 = 0, write = 0;
+
+ gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Reason=%d", Os, Hardware, Reason);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
+
+ switch (Reason)
+ {
+ case gcvBROADCAST_FIRST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
+ break;
+
+ case gcvBROADCAST_LAST_PROCESS:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
+
+ /* Put GPU OFF. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware,
+ gcvPOWER_OFF_BROADCAST));
+
+ break;
+
+ case gcvBROADCAST_GPU_IDLE:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
+
+ /* Put GPU IDLE. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware,
+ gcvPOWER_IDLE_BROADCAST));
+
+ break;
+
+ case gcvBROADCAST_GPU_COMMIT:
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
+
+ /* Put GPU ON. */
+ gcmkONERROR(
+ gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON));
+ break;
+
+ case gcvBROADCAST_GPU_STUCK:
+ gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
+ gcmkPRINT("!!FATAL!! GPU Stuck");
+ gcmkPRINT(" idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
+
+ if (Hardware->chipFeatures & (1 << 4))
+ {
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
+ gcmkPRINT(" read0=0x%08X read1=0x%08X write=0x%08X",
+ read0, read1, write);
+ }
+
+ gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+ break;
+
+ case gcvBROADCAST_AXI_BUS_ERROR:
+ gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
+ gcmkPRINT("!!FATAL!! AXI Bus Error");
+ gcmkPRINT(" idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
+
+ if (Hardware->chipFeatures & (1 << 4))
+ {
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
+ gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
+ gcmkPRINT(" read0=0x%08X read1=0x%08X write=0x%08X",
+ read0, read1, write);
+ }
+
+ gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+********************************** Semaphores **********************************
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_CreateSemaphore
+**
+** Create a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Semaphore
+** Pointer to the variable that will receive the created semaphore.
+*/
+gceSTATUS
+gckOS_CreateSemaphore(
+ IN gckOS Os,
+ OUT gctPOINTER * Semaphore
+ )
+{
+ gceSTATUS status;
+ struct semaphore *sem;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Allocate the semaphore structure. */
+ gcmkONERROR(
+ gckOS_Allocate(Os, gcmSIZEOF(struct semaphore), (gctPOINTER *) &sem));
+
+ /* Initialize the semaphore. */
+ sema_init(sem, 1);
+
+ /* Return to caller. */
+ *Semaphore = (gctPOINTER) sem;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireSemaphore
+**
+** Acquire a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x", Os);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Acquire the semaphore. */
+ if (down_interruptible((struct semaphore *) Semaphore))
+ {
+ gcmkONERROR(gcvSTATUS_TIMEOUT);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseSemaphore
+**
+** Release a previously acquired semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_ReleaseSemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Release the semaphore. */
+ up((struct semaphore *) Semaphore);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySemaphore
+**
+** Destroy a semaphore.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** gctPOINTER Semaphore
+** Pointer to the semaphore thet needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySemaphore(
+ IN gckOS Os,
+ IN gctPOINTER Semaphore
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
+
+ /* Free the sempahore structure. */
+ gcmkONERROR(gckOS_Free(Os, Semaphore));
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetProcessID
+**
+** Get current process ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ProcessID
+** Pointer to the variable that receives the process ID.
+*/
+gceSTATUS
+gckOS_GetProcessID(
+ OUT gctUINT32_PTR ProcessID
+ )
+{
+ gcmkHEADER();
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(ProcessID != gcvNULL);
+
+ /* Get process ID. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ *ProcessID = task_tgid_vnr(current);
+#else
+ *ProcessID = current->tgid;
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ProcessID=%u", *ProcessID);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetThreadID
+**
+** Get current thread ID.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR ThreadID
+** Pointer to the variable that receives the thread ID.
+*/
+gceSTATUS
+gckOS_GetThreadID(
+ OUT gctUINT32_PTR ThreadID
+ )
+{
+ gcmkHEADER();
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(ThreadID != gcvNULL);
+
+ /* Get thread ID. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+ *ThreadID = task_pid_vnr(current);
+#else
+ *ThreadID = current->pid;
+#endif
+
+ /* Success. */
+ gcmkFOOTER_ARG("*ThreadID=%u", *ThreadID);
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetGPUPower
+**
+** Set the power of the GPU on or off.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to a gckOS object.
+**
+** gctBOOL Clock
+** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
+**
+** gctBOOL Power
+** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_SetGPUPower(
+ IN gckOS Os,
+ IN gctBOOL Clock,
+ IN gctBOOL Power
+ )
+{
+ gcmkHEADER_ARG("Os=0x%x Clock=%d Power=%d", Os, Clock, Power);
+
+ /* TODO: Put your code here. */
+
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_os_h_
+#define __gc_hal_kernel_os_h_
+
+typedef struct _LINUX_MDL_MAP
+{
+ gctINT pid;
+ gctPOINTER vmaAddr;
+ struct vm_area_struct * vma;
+ struct _LINUX_MDL_MAP * next;
+}
+LINUX_MDL_MAP, *PLINUX_MDL_MAP;
+
+typedef struct _LINUX_MDL
+{
+ gctINT pid;
+ char * addr;
+
+#ifdef NO_DMA_COHERENT
+ gctPOINTER kaddr;
+#endif /* NO_DMA_COHERENT */
+
+ gctINT numPages;
+ gctINT pagedMem;
+ gctBOOL contiguous;
+ dma_addr_t dmaHandle;
+ PLINUX_MDL_MAP maps;
+ struct _LINUX_MDL * prev;
+ struct _LINUX_MDL * next;
+}
+LINUX_MDL, *PLINUX_MDL;
+
+extern PLINUX_MDL_MAP
+FindMdlMap(
+ IN PLINUX_MDL Mdl,
+ IN gctINT PID
+ );
+
+typedef struct _DRIVER_ARGS
+{
+ gctPOINTER InputBuffer;
+ gctUINT32 InputBufferSize;
+ gctPOINTER OutputBuffer;
+ gctUINT32 OutputBufferSize;
+}
+DRIVER_ARGS;
+
+/* Cleanup the signal table. */
+gceSTATUS
+gckOS_CleanProcessSignal(
+ gckOS Os,
+ gctHANDLE Process
+ );
+
+#ifdef gcdkUSE_MEMORY_RECORD
+MEMORY_RECORD_PTR
+CreateMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ );
+
+void
+DestoryMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR Mr
+ );
+
+MEMORY_RECORD_PTR
+FindMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List,
+ gcuVIDMEM_NODE_PTR Node
+ );
+
+void
+FreeAllMemoryRecord(
+ gckOS Os,
+ MEMORY_RECORD_PTR List
+ );
+#endif
+
+#endif /* __gc_hal_kernel_os_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+/*
+ * gc_hal_common_qnx.h
+ *
+ * Created on: Jul 7, 2010
+ * Author: tarang
+ */
+
+#ifndef GC_HAL_COMMON_QNX_H_
+#define GC_HAL_COMMON_QNX_H_
+
+/******************************************************************************\
+******************************* QNX Control Codes ******************************
+\******************************************************************************/
+#ifndef _IOMGR_VIVANTE
+#define _IOMGR_VIVANTE (_IOMGR_PRIVATE_BASE + 0x301)
+#endif
+
+/*******************************************************************************
+** Signal management.
+**
+** Is much simpler in Neutrino versus Linux :-)
+**
+** Neutrino pulses are equivalent to RT signals (queued, small payload) except
+** they are explicitly received on a channel. We therefore dedicate a thread
+** to handle them.
+**
+** We don't use RT signals because:
+** 1. They can be delivered on any thread.
+** 2. We don't support SA_RESTART so blocking kernel calls can fail. It would be
+** impossible to robustly handle this condition in all libraries.
+**
+** Only downside is that more information needs to be passed between client/server
+** (signals require only PID, pulses require connection ID and receive ID).
+*/
+
+typedef struct _gcsSIGNAL
+{
+ /* Pointer to gcoOS object. */
+ gcoOS os;
+
+ /* Signaled state. */
+ gctBOOL state;
+
+ /* Manual reset flag. */
+ gctBOOL manual;
+
+ /* Mutex. */
+ pthread_mutex_t mutex;
+
+ /* Condition. */
+ pthread_cond_t condition;
+
+ /* Number of signals pending in the command queue. */
+ gctINT pending;
+
+ /* Number of signals received. */
+ gctINT received;
+}
+gcsSIGNAL;
+
+#endif /* GC_HAL_COMMON_QNX_H_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+#include <stdarg.h>
+
+/*
+ gcdBUFFERED_OUTPUT
+
+ When set to non-zero, all output is collected into a buffer with the
+ specified size. Once the buffer gets full, or the token "$$FLUSH$$" has
+ been received, the debug buffer will be printed to the console.
+*/
+#define gcdBUFFERED_OUTPUT 0
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
+static gctUINT32 _debugZones = gcvZONE_NONE;
+static gctINT _indent = 0;
+
+static void
+OutputDebugString(
+ IN gctCONST_STRING String
+ )
+{
+#if gcdBUFFERED_OUTPUT
+ static gctCHAR outputBuffer[gcdBUFFERED_OUTPUT];
+ static gctINT outputBufferIndex = 0;
+ gctINT n, i;
+
+ n = (String != gcvNULL) ? strlen(String) + 1 : 0;
+
+ if ((n == 0) || (outputBufferIndex + n > gcmSIZEOF(outputBuffer)))
+ {
+ for (i = 0; i < outputBufferIndex; i += strlen(outputBuffer + i) + 1)
+ {
+ printf(outputBuffer + i);
+ }
+
+ outputBufferIndex = 0;
+ }
+
+ if (n > 0)
+ {
+ memcpy(outputBuffer + outputBufferIndex, String, n);
+ outputBufferIndex += n;
+ }
+#else
+ if (String != gcvNULL)
+ {
+ printf(String);
+ }
+#endif
+}
+
+static void
+_Print(
+ IN gctCONST_STRING Message,
+ IN va_list Arguments
+ )
+{
+ char buffer[1024];
+ int i, n;
+
+ if (strcmp(Message, "$$FLUSH$$") == 0)
+ {
+ OutputDebugString(gcvNULL);
+ return;
+ }
+
+ if (strncmp(Message, "--", 2) == 0)
+ {
+ if (_indent == 0)
+ {
+ printf("ERROR: _indent=0\n");
+ }
+
+ _indent -= 2;
+ }
+
+ for (i = 0; i < _indent; ++i)
+ {
+ buffer[i] = ' ';
+ }
+
+ /* Print message to buffer. */
+ n = vsnprintf(buffer + i, sizeof(buffer) - i, Message, Arguments);
+ if ((n <= 0) || (buffer[i + n - 1] != '\n'))
+ {
+ /* Append new-line. */
+ strncat(buffer, "\n", sizeof(buffer));
+ }
+
+ /* Output to debugger. */
+ OutputDebugString(buffer);
+
+ if (strncmp(Message, "++", 2) == 0)
+ {
+ _indent += 2;
+ }
+}
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#define _DEBUGPRINT(Message) \
+{ \
+ va_list arguments; \
+ \
+ va_start(arguments, Message); \
+ _Print(Message, arguments); \
+ va_end(arguments); \
+}
+
+/******************************************************************************\
+********************************** Debug Code **********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Print
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTrace
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZone
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ _DEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugBreak
+**
+** Break into the debugger.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugBreak(
+ void
+ )
+{
+ gckOS_DebugTrace(gcvLEVEL_ERROR, "gckOS_DebugBreak");
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFatal
+**
+** Send a message to the debugger and break into the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ _DEBUGPRINT(Message);
+
+ /* Break into the debugger. */
+ gckOS_DebugBreak();
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevel
+**
+** Set the debug level.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ )
+{
+ _debugLevel = Level;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZone
+**
+** Set the debug zone.
+**
+** INPUT:
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ )
+{
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevelZone
+**
+** Set the debug level and zone.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ )
+{
+ _debugLevel = Level;
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZones
+**
+** Enable or disable debug zones.
+**
+** INPUT:
+**
+** gctUINT32 Zones
+** Debug zones to enable or disable.
+**
+** gctBOOL Enable
+** Set to gcvTRUE to enable the zones (or the Zones with the current
+** zones) or gcvFALSE to disable the specified Zones.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ )
+{
+ if (Enable)
+ {
+ /* Enable the zones. */
+ _debugZones |= Zones;
+ }
+ else
+ {
+ /* Disable the zones. */
+ _debugZones &= ~Zones;
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_Verify
+**
+** Called to verify the result of a function call.
+**
+** INPUT:
+**
+** gceSTATUS Status
+** Function call result.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Verify(
+ IN gceSTATUS Status
+ )
+{
+ _lastError = Status;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+#include <sys/mman.h>
+#include <sys/siginfo.h>
+
+#define _GC_OBJ_ZONE gcvZONE_DEVICE
+
+/******************************************************************************\
+******************************** gckGALDEVICE Code *******************************
+\******************************************************************************/
+
+gceSTATUS
+gckGALDEVICE_AllocateMemory(
+ IN gckGALDEVICE Device,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER *Logical,
+ OUT gctPHYS_ADDR *Physical,
+ OUT gctUINT32 *PhysAddr
+ )
+{
+ gceSTATUS status;
+
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
+
+ status = gckOS_AllocateContiguous(Device->os,
+ gcvFALSE,
+ &Bytes,
+ Physical,
+ Logical);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "gckGALDEVICE_AllocateMemory: error status->0x%x",
+ status);
+
+ return status;
+ }
+
+ *PhysAddr = (gctUINT32)(*(off_t*) Physical) - Device->baseAddress;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "gckGALDEVICE_AllocateMemory: phys_addr->0x%x phsical->0x%x Logical->0x%x",
+ (gctUINT32)*Physical,
+ (gctUINT32)*PhysAddr,
+ (gctUINT32)*Logical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckGALDEVICE_FreeMemory(
+ IN gckGALDEVICE Device,
+ IN gctPOINTER Logical,
+ IN gctPHYS_ADDR Physical)
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ return gckOS_FreeContiguous(Device->os,
+ Physical,
+ Logical,
+ 0);
+}
+
+/* TODO. fix global sigevent to be part of device. */
+struct sigevent irqEvent;
+
+const struct sigevent* isrRoutine(void* arg, int id)
+{
+ gckGALDEVICE device = (gckGALDEVICE)arg;
+
+ /* Call kernel interrupt notification. */
+ if (gckKERNEL_Notify(device->kernel,
+ gcvNOTIFY_INTERRUPT,
+ gcvTRUE) == gcvSTATUS_OK)
+ {
+ InterruptUnmask(device->irqLine, device->irqId);
+
+ return &irqEvent;
+ }
+
+ return gcvNULL;
+}
+
+static void* threadRoutine(void *ctxt)
+{
+ gckGALDEVICE device = (gckGALDEVICE) ctxt;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Starting ISR Thread with irq:%d\n",
+ device->irqLine);
+
+ SIGEV_INTR_INIT(&irqEvent);
+
+ /* Obtain I/O privileges */
+ ThreadCtl( _NTO_TCTL_IO, 0 );
+
+ device->irqId = InterruptAttach(device->irqLine,
+ isrRoutine,
+ (void*)device,
+ gcmSIZEOF(struct _gckGALDEVICE),
+ 0);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "irqId:%d\n",
+ device->irqId);
+
+ if (device->irqId < 0) {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Setup_ISR: "
+ "Could not register irq line->%d\n",
+ device->irqLine);
+
+ device->isrInitialized = gcvFALSE;
+
+ return (void *)1;
+ }
+
+ printf("[Interrupt] Attached irqLine %d with id %d.\n",
+ device->irqLine, device->irqId);
+
+ device->isrInitialized = gcvTRUE;
+
+ while (1)
+ {
+ if (InterruptWait(0, NULL) == -1)
+ {
+ printf("[Interrupt] IST exiting\n");
+ /* Either something is wrong or the thread got canceled */
+ InterruptUnmask(device->irqLine, device->irqId);
+ pthread_exit(NULL);
+ }
+
+ gckKERNEL_Notify(device->kernel, gcvNOTIFY_INTERRUPT, gcvFALSE);
+ }
+
+ return (void *)0;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Setup_ISR
+**
+** Start the ISR routine.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Setup successfully.
+** gcvSTATUS_GENERIC_IO
+** Setup failed.
+*/
+gceSTATUS
+gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Release_ISR
+**
+** Release the irq line.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ return gcvSTATUS_OK;
+}
+
+
+int
+gsl_free_interrupts()
+{
+
+ return 0;
+}
+/*******************************************************************************
+**
+** gckGALDEVICE_Start_Thread
+**
+** Start the daemon thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+** gcvSTATUS_GENERIC_IO
+** Start failed.
+*/
+gceSTATUS
+gckGALDEVICE_Start_Thread(
+ IN gckGALDEVICE Device
+ )
+{
+ pthread_attr_t attr;
+ struct sched_param sched;
+ gctINT ret;
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Start_Thread: Creating threadRoutine\n");
+
+ pthread_attr_init(&attr);
+ pthread_attr_getschedparam(&attr, &sched);
+ sched.sched_priority += 10;
+ pthread_attr_setschedparam(&attr, &sched);
+ pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+
+ /* Start the interrupt service thread */
+ if ((ret = pthread_create(&Device->threadCtxt, &attr, threadRoutine, Device)) != 0)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Start_Thread: Failed with code %d\n",
+ ret);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ pthread_setname_np(Device->threadCtxt, "galcore-IST");
+
+ Device->threadInitialized = gcvTRUE;
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Start_Thread: "
+ "Start the daemon thread.\n");
+
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop_Thread
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop_Thread(
+ gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ /* stop the thread */
+ if (Device->threadInitialized)
+ {
+ InterruptDetach(Device->irqId);
+ Device->irqId = 0;
+ ConnectDetach(Device->coid);
+ Device->coid = 0;
+ ChannelDestroy(Device->chid);
+ Device->chid = 0;
+
+ pthread_cancel(Device->threadCtxt);
+ pthread_join(Device->threadCtxt, NULL);
+ Device->threadCtxt = 0;
+
+ Device->threadInitialized = gcvFALSE;
+ Device->isrInitialized = gcvFALSE;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Start
+**
+** Start the gal device, including the following actions: setup the isr routine
+** and start the daemon thread.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** gcvSTATUS_OK
+** Start successfully.
+*/
+gceSTATUS
+gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ )
+{
+ gceSTATUS ret;
+ /* Start the daemon thread. */
+ gcmkVERIFY_OK((ret = gckGALDEVICE_Start_Thread(Device)));
+
+ return ret;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Stop
+**
+** Stop the gal device, including the following actions: stop the daemon
+** thread, release the irq.
+**
+** INPUT:
+**
+** gckGALDEVICE Device
+** Pointer to an gckGALDEVICE object.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ )
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ if (Device->threadInitialized)
+ {
+ gckGALDEVICE_Stop_Thread(Device);
+ }
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Construct
+**
+** Constructor.
+**
+** INPUT:
+**
+** OUTPUT:
+**
+** gckGALDEVICE * Device
+** Pointer to a variable receiving the gckGALDEVICE object pointer on
+** success.
+*/
+gceSTATUS
+gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 BaseAddress,
+ OUT gckGALDEVICE *Device
+ )
+{
+ gctUINT32 internalBaseAddress, internalAlignment;
+ gctUINT32 externalBaseAddress, externalAlignment;
+ gctUINT32 horizontalTileSize, verticalTileSize;
+ gctUINT32 physAddr;
+ gctUINT32 physical;
+ gckGALDEVICE device;
+ gceSTATUS status;
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Enter gckGALDEVICE_Construct\n");
+
+ /* Allocate device structure. */
+ device = calloc(1, sizeof(struct _gckGALDEVICE));
+ if (!device)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Can't allocate memory.\n");
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ physical = RegisterMemBase;
+
+ /* Set up register memory region */
+ if (physical != 0)
+ {
+ /* Request a region. */
+ device->registerBase = (gctPOINTER)mmap_device_io(RegisterMemSize, RegisterMemBase);
+
+ if ((uintptr_t)device->registerBase == MAP_DEVICE_FAILED)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Unable to map location->0x%lX for size->%ld\n",
+ RegisterMemBase,
+ RegisterMemSize);
+
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ physical += RegisterMemSize;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: "
+ "RegisterBase after mapping Address->0x%x is 0x%x\n",
+ (gctUINT32)RegisterMemBase,
+ (gctUINT32)device->registerBase);
+ }
+
+ /* construct the gckOS object */
+ device->baseAddress = BaseAddress;
+ gcmkONERROR(
+ gckOS_Construct(device, &device->os));
+
+ /* construct the gckKERNEL object. */
+ gcmkONERROR(
+ gckKERNEL_Construct(device->os, device, &device->kernel));
+
+ gcmkONERROR(
+ gckHARDWARE_SetFastClear(device->kernel->hardware,
+ FastClear,
+ Compression));
+
+ /* query the ceiling of the system memory */
+ gcmkONERROR(
+ gckHARDWARE_QuerySystemMemory(device->kernel->hardware,
+ &device->systemMemorySize,
+ &device->systemMemoryBaseAddress));
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: "
+ "Will be trying to allocate contiguous memory of 0x%x bytes\n",
+ (gctUINT32)device->systemMemoryBaseAddress);
+
+#if COMMAND_PROCESSOR_VERSION == 1
+ /* start the command queue */
+ gcmkVERIFY_OK(gckCOMMAND_Start(device->kernel->command));
+#endif
+
+ /* initialize the thread daemon */
+ memset(&device->isrLock, 0, sizeof(device->isrLock));
+
+ device->threadInitialized = gcvFALSE;
+ device->killThread = gcvFALSE;
+
+ /* initialize the isr */
+ device->isrInitialized = gcvFALSE;
+ device->dataReady = gcvFALSE;
+ device->irqLine = IrqLine;
+
+ /* query the amount of video memory */
+ gcmkVERIFY_OK(gckHARDWARE_QueryMemory(device->kernel->hardware,
+ &device->internalSize,
+ &internalBaseAddress,
+ &internalAlignment,
+ &device->externalSize,
+ &externalBaseAddress,
+ &externalAlignment,
+ &horizontalTileSize,
+ &verticalTileSize));
+
+ /* set up the internal memory region */
+ if (device->internalSize > 0)
+ {
+ gceSTATUS status = gckVIDMEM_Construct(device->os,
+ internalBaseAddress,
+ device->internalSize,
+ internalAlignment,
+ 0,
+ &device->internalVidMem);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* error, remove internal heap */
+ device->internalSize = 0;
+ }
+ else
+ {
+ /* map internal memory */
+ device->internalPhysical = (gctPHYS_ADDR)physical;
+ device->internalLogical = (gctPOINTER)mmap_device_io(device->internalSize, physical);
+
+ gcmkASSERT(device->internalLogical != NULL);
+
+ physical += device->internalSize;
+ }
+ }
+
+ if (device->externalSize > 0)
+ {
+ /* create the external memory heap */
+ gceSTATUS status = gckVIDMEM_Construct(device->os,
+ externalBaseAddress,
+ device->externalSize,
+ externalAlignment,
+ 0,
+ &device->externalVidMem);
+
+ if (gcmIS_ERROR(status))
+ {
+ /* error, remove internal heap */
+ device->externalSize = 0;
+ }
+ else
+ {
+ /* map internal memory */
+ device->externalPhysical = (gctPHYS_ADDR)physical;
+ device->externalLogical = (gctPOINTER)mmap_device_io(device->externalSize, physical);
+
+ gcmkASSERT(device->externalLogical != NULL);
+
+ physical += device->externalSize;
+ }
+ }
+
+ /* set up the contiguous memory */
+ device->contiguousSize = ContiguousSize;
+
+ if (ContiguousBase == 0)
+ {
+ status = gcvSTATUS_OUT_OF_MEMORY;
+
+ while (device->contiguousSize > 0)
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Will be trying to allocate contiguous memory of %ld bytes\n",
+ device->contiguousSize
+ );
+
+ /* allocate contiguous memory */
+ status = gckGALDEVICE_AllocateMemory(
+ device,
+ device->contiguousSize,
+ &device->contiguousBase,
+ &device->contiguousPhysical,
+ &physAddr
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Contiguous allocated size->0x%08X Virt->0x%08lX physAddr->0x%08X\n",
+ device->contiguousSize,
+ device->contiguousBase,
+ physAddr
+ );
+
+ status = gckVIDMEM_Construct(
+ device->os,
+ physAddr | device->systemMemoryBaseAddress,
+ device->contiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_SUCCESS(status))
+ {
+ device->contiguousMapped = gcvFALSE;
+
+ /* success, abort loop */
+ gcmkTRACE_ZONE(
+ gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "Using %u bytes of contiguous memory.\n",
+ device->contiguousSize
+ );
+
+ break;
+ }
+
+ gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(
+ device,
+ device->contiguousBase,
+ device->contiguousPhysical
+ ));
+
+ device->contiguousBase = NULL;
+ }
+
+ device->contiguousSize -= (4 << 20);
+ }
+ }
+ else
+ {
+ /* Create the contiguous memory heap. */
+ status = gckVIDMEM_Construct(
+ device->os,
+ (ContiguousBase - device->baseAddress) | device->systemMemoryBaseAddress,
+ ContiguousSize,
+ 64,
+ BankSize,
+ &device->contiguousVidMem
+ );
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error, roll back. */
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+ }
+ else
+ {
+ /* Map the contiguous memory. */
+ device->contiguousPhysical = (gctPHYS_ADDR) ContiguousBase;
+ device->contiguousSize = ContiguousSize;
+ device->contiguousBase = (gctPOINTER) mmap_device_io(ContiguousSize, ContiguousBase);
+ device->contiguousMapped = gcvTRUE;
+
+ if (device->contiguousBase == gcvNULL)
+ {
+ /* Error, roll back. */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(device->contiguousVidMem));
+ device->contiguousVidMem = gcvNULL;
+ device->contiguousSize = 0;
+
+ status = gcvSTATUS_OUT_OF_RESOURCES;
+ }
+ }
+ }
+
+ *Device = device;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Construct: Initialized device->0x%x contiguous->%lu @ 0x%x (0x%08X)\n",
+ device,
+ device->contiguousSize,
+ device->contiguousBase,
+ device->contiguousPhysical);
+
+ return gcvSTATUS_OK;
+OnError:
+ /* Roll back. */
+
+ /* Destroy the gckKERNEL object. */
+ if ( Device != gcvNULL)
+ {
+ gcmkVERIFY_OK(gckGALDEVICE_Destroy(*Device));
+ }
+
+ /* Return the status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckGALDEVICE_Destroy
+**
+** Class destructor.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+**
+** RETURNS:
+**
+** Nothing.
+*/
+gceSTATUS
+gckGALDEVICE_Destroy(
+ gckGALDEVICE Device)
+{
+ gcmkVERIFY_ARGUMENT(Device != NULL);
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[ENTER] gckGALDEVICE_Destroy\n");
+
+ /* Destroy the gckKERNEL object. */
+ gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernel));
+
+ if (Device->internalVidMem != gcvNULL)
+ {
+ /* destroy the internal heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
+
+ /* unmap the internal memory */
+ munmap_device_io((uintptr_t)Device->internalLogical, Device->internalSize);
+ }
+
+ if (Device->externalVidMem != gcvNULL)
+ {
+ /* destroy the internal heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
+
+ /* unmap the external memory */
+ munmap_device_io((uintptr_t)Device->externalLogical, Device->externalSize);
+ }
+
+ if (Device->contiguousVidMem != gcvNULL)
+ {
+ /* Destroy the contiguous heap */
+ gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
+
+ if (Device->contiguousMapped)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Destroy: "
+ "Unmapping contiguous memory->0x%08lX\n",
+ Device->contiguousBase);
+
+ munmap_device_io((uintptr_t)Device->contiguousBase, Device->contiguousSize);
+ }
+ else
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] gckGALDEVICE_Destroy: "
+ "Freeing contiguous memory->0x%08lX\n",
+ Device->contiguousBase);
+
+ gcmkVERIFY_OK(gckGALDEVICE_FreeMemory(Device,
+ Device->contiguousBase,
+ Device->contiguousPhysical));
+ }
+ }
+
+ if (Device->registerBase)
+ {
+ munmap_device_io((uintptr_t)Device->registerBase, Device->registerSize);
+ }
+
+ /* Destroy the gckOS object. */
+ gcmkVERIFY_OK(gckOS_Destroy(Device->os));
+
+ free(Device);
+
+ gcmkTRACE(gcvLEVEL_VERBOSE, "[galcore] Leave gckGALDEVICE_Destroy\n");
+
+ return gcvSTATUS_OK;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_device_h_
+#define __gc_hal_kernel_device_h_
+
+/******************************************************************************\
+******************************* gckGALDEVICE Structure *******************************
+\******************************************************************************/
+
+#define GALCORE_INTERRUPT_PULSE 0x5D
+
+typedef struct _gckGALDEVICE
+{
+ /* Objects. */
+ gckOS os;
+ gckKERNEL kernel;
+
+ /* Attributes. */
+ gctSIZE_T internalSize;
+ gctPHYS_ADDR internalPhysical;
+ gctPOINTER internalLogical;
+ gckVIDMEM internalVidMem;
+ gctSIZE_T externalSize;
+ gctPHYS_ADDR externalPhysical;
+ gctPOINTER externalLogical;
+ gckVIDMEM externalVidMem;
+ gckVIDMEM contiguousVidMem;
+ gctPOINTER contiguousBase;
+ gctPHYS_ADDR contiguousPhysical;
+ gctSIZE_T contiguousSize;
+ gctBOOL contiguousMapped;
+ gctPOINTER contiguousMappedUser;
+ gctSIZE_T systemMemorySize;
+ gctUINT32 systemMemoryBaseAddress;
+ gctPOINTER registerBase;
+ gctSIZE_T registerSize;
+ gctUINT32 baseAddress;
+
+ /* IRQ management. */
+ gctINT irqLine;
+ gctINT irqId;
+ gctBOOL isrInitialized;
+ gctBOOL dataReady;
+ intrspin_t isrLock;
+ struct sigevent event;
+ int chid;
+ int coid;
+
+ /* Thread management. */
+ pthread_t threadCtxt;
+ gctBOOL threadInitialized;
+ gctBOOL killThread;
+}
+* gckGALDEVICE;
+
+typedef struct _gcsHAL_PRIVATE_DATA
+{
+ gckGALDEVICE device;
+ gctPOINTER mappedMemory;
+ gctPOINTER contiguousLogical;
+}
+gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
+
+gceSTATUS gckGALDEVICE_Setup_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Release_ISR(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start_Thread(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop_Thread(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Start(
+ IN gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Stop(
+ gckGALDEVICE Device
+ );
+
+gceSTATUS gckGALDEVICE_Construct(
+ IN gctINT IrqLine,
+ IN gctUINT32 RegisterMemBase,
+ IN gctSIZE_T RegisterMemSize,
+ IN gctUINT32 ContiguousBase,
+ IN gctSIZE_T ContiguousSize,
+ IN gctSIZE_T BankSize,
+ IN gctINT FastClear,
+ IN gctINT Compression,
+ IN gctUINT32 BaseAddress,
+ OUT gckGALDEVICE *Device
+ );
+
+gceSTATUS gckGALDEVICE_Destroy(
+ IN gckGALDEVICE Device
+ );
+
+#endif /* __gc_hal_kernel_device_h_ */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_user_context.h"
+
+# include <winmgr/gpu.h>
+
+static gckGALDEVICE galDevice;
+
+/* GN TODO take these from the graphics.conf file. */
+#ifdef MMP2
+int irqLine = 8;
+long registerMemBase = 0xd420d000;
+#else
+int irqLine = 48;
+long registerMemBase = 0xf1840000;
+#endif
+
+/* Configurable Memory sizes. */
+unsigned long contiguousSize = ( 64 << 20); /* Video memory pool. */
+unsigned int internalPoolSize = ( 16 << 20); /* Kernel local memory pool. */
+unsigned int sharedPoolSize = ( 8 << 20); /* Shared per-client memory pool initial size. */
+unsigned long registerMemSize = (256 << 10); /* GPU register memory size. */
+
+/* ContiguousBase should be 0,
+ * for video memory to be allocated from the memory pool. */
+unsigned long contiguousBase = 0;
+long bankSize = 0;
+int fastClear = -1;
+int compression = -1;
+unsigned long baseAddress = 0;
+
+/* Global video memory pool. */
+typedef struct _gcsMEM_POOL
+{
+ gctINT32 freePage;
+ gctSIZE_T pageCount;
+ gctUINT32 pageSize;
+ gctUINT32 poolSize;
+ pthread_mutex_t mutex;
+ gctUINT32 addr;
+ gctUINT32 paddr;
+ gckPAGE_USAGE pageUsage;
+ gctCHAR fdName[64];
+ gctINT fd;
+} gcsMEM_POOL;
+
+gcsMEM_POOL memPool;
+
+/* Pointer to list of shared memory pools. */
+gckSHM_POOL shmPoolList;
+pthread_mutex_t shmPoolListMutex;
+
+/* Resource Manager Globals. */
+struct _gcsRESMGR_GLOBALS
+{
+ dispatch_t *dpp;
+ dispatch_context_t *ctp;
+ int id;
+ thread_pool_attr_t pool_attr;
+ thread_pool_t *tpp;
+ pthread_t root;
+} resmgr_globals;
+
+win_gpu_2_cm_iface_t *g_qnx_gpu_2_cm_iface = 0;
+static resmgr_connect_funcs_t connect_funcs;
+static resmgr_io_funcs_t io_funcs;
+static iofunc_attr_t attr;
+
+gceSTATUS gckVIDMEM_FreeHandleMemory(IN gckVIDMEM Memory, IN gctHANDLE Handle);
+
+gceSTATUS
+drv_mempool_init()
+{
+ off64_t paddr;
+ void* addr;
+ size_t pcontig;
+
+ /* Default 4KB page size. */
+ memPool.pageSize = __PAGESIZE;
+
+ /* Compute number of pages. */
+ memPool.pageCount = (contiguousSize + internalPoolSize) / memPool.pageSize;
+ gcmkASSERT(memPool.pageCount <= 65536);
+
+ /* Align memPoolSize to page size. */
+ memPool.poolSize = memPool.pageCount * memPool.pageSize;
+
+ /* Allocate a single chunk of physical memory.
+ * Zero memory with MAP_ANON so we don't leak any sensitive information by chance. */
+ snprintf(memPool.fdName, sizeof(memPool.fdName), "galcore:vidmem:%d", getpid());
+ memPool.fd = shm_open(memPool.fdName, O_RDWR|O_CREAT, 0777);
+ if (memPool.fd == -1) {
+ fprintf(stderr, "galcore:%s[%d]: shm_open failed\n", __FUNCTION__, __LINE__);
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ shm_unlink(memPool.fdName);
+
+ if (shm_ctl_special(memPool.fd, SHMCTL_ANON|SHMCTL_PHYS, 0, memPool.poolSize, 0x9) == -1) {
+ fprintf(stderr, "galcore:%s[%d]: shm_ctl_special failed\n", __FUNCTION__, __LINE__);
+ close(memPool.fd);
+ memPool.fd = -1;
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ addr = mmap64(0, memPool.poolSize, PROT_READ|PROT_WRITE, MAP_SHARED, memPool.fd, 0);
+ if (addr == MAP_FAILED) {
+ fprintf(stderr, "galcore:%s[%d]: mmap64 failed\n", __FUNCTION__, __LINE__);
+ close(memPool.fd);
+ memPool.fd = -1;
+ return gcvSTATUS_GENERIC_IO;
+ }
+ memPool.addr = (gctUINT32)addr;
+
+ if (mem_offset64(addr, NOFD, memPool.poolSize, &paddr, &pcontig) == -1)
+ {
+ fprintf(stderr, "galcore:%s[%d]: mem_offset64 failed\n", __FUNCTION__, __LINE__);
+ munmap(addr, memPool.poolSize);
+ close(memPool.fd);
+ memPool.fd = -1;
+ memPool.addr = NULL;
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* TODO. Truncating 64bit value. */
+ memPool.paddr = (gctUINT32)paddr;
+
+ printf( "Mempool Map addr range[%x-%x]\n", memPool.addr, memPool.addr + memPool.poolSize);
+ printf( "Mempool Map paddr range[%x-%x]\n", memPool.paddr, memPool.paddr + memPool.poolSize );
+
+ /* Allocate the page usage array and Initialize all pages to free. */
+ memPool.pageUsage = (gckPAGE_USAGE)calloc(
+ memPool.pageCount,
+ sizeof(struct _gckPAGE_USAGE));
+
+ if (memPool.pageUsage == gcvNULL)
+ {
+ fprintf( stderr, "malloc failed: %s\n", strerror( errno ) );
+ munmap(addr, memPool.poolSize);
+ close(memPool.fd);
+ memPool.fd = -1;
+ memPool.addr = NULL;
+ memPool.paddr = 0;
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* The first page is free.*/
+ memPool.freePage = 0;
+
+ /* Initialize the semaphore. */
+ if (pthread_mutex_init(&memPool.mutex, NULL) != EOK)
+ {
+ free(memPool.pageUsage);
+ munmap(addr, memPool.poolSize);
+ close(memPool.fd);
+ memPool.fd = -1;
+ memPool.addr = NULL;
+ memPool.paddr = 0;
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ return gcvSTATUS_OK;
+}
+
+void
+drv_mempool_destroy()
+{
+ pthread_mutex_destroy(&memPool.mutex);
+ free(memPool.pageUsage);
+ memPool.pageUsage = NULL;
+ munmap((void*)memPool.addr, memPool.poolSize);
+ close(memPool.fd);
+ memPool.fd = -1;
+ memPool.addr = NULL;
+ memPool.paddr = 0;
+}
+
+gctINT
+drv_mempool_get_fileDescriptor()
+{
+ return memPool.fd;
+}
+
+gctUINT32
+drv_mempool_get_basePAddress()
+{
+ return memPool.paddr;
+}
+
+gctUINT32
+drv_mempool_get_baseAddress()
+{
+ return memPool.addr;
+}
+
+gctUINT32
+drv_mempool_get_page_size()
+{
+ return memPool.pageSize;
+}
+
+gceSTATUS
+drv_mempool_mem_offset(
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address)
+{
+ gctUINT32 logical = (gctUINT32)Logical;
+
+ if ( Address == gcvNULL )
+ return gcvSTATUS_INVALID_ARGUMENT;
+
+ if ( logical < memPool.addr
+ || logical > (memPool.addr + memPool.poolSize))
+ return gcvSTATUS_INVALID_ARGUMENT;
+
+ *Address = (logical - memPool.addr) + memPool.paddr;
+
+ return gcvSTATUS_OK;
+}
+
+/* Allocate pages from mapped shared memory.
+ Return Physical and Logical addresses.
+*/
+void
+drv_mempool_alloc_contiguous(
+ IN gctUINT32 Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctSIZE_T i, j;
+ gctSIZE_T pageCount;
+
+ pthread_mutex_lock(&memPool.mutex);
+
+ /* Compute the number of required pages. */
+ pageCount = gcmALIGN(Bytes, drv_mempool_get_page_size()) / drv_mempool_get_page_size();
+
+ if ( (pageCount <= 0) || (memPool.freePage < 0) )
+ {
+ *Physical = gcvNULL;
+ *Logical = gcvNULL;
+ pthread_mutex_unlock(&memPool.mutex);
+ /* No free pages left. */
+ return;
+ }
+
+ /* Try finding enough contiguous free pages. */
+ for (i = memPool.freePage; i < memPool.pageCount;)
+ {
+ /* All pages behind this free page should be free. */
+ gctSIZE_T j;
+ for (j = 1; j < pageCount; ++j)
+ {
+ if (memPool.pageUsage[i + j].pageCount != 0)
+ {
+ /* Bail out if page is allocated. */
+ break;
+ }
+ }
+
+ if (j == pageCount)
+ {
+ /* We found a spot that has enough free pages. */
+ break;
+ }
+
+ /* Move to the page after the allocated page. */
+ i += j + 1;
+
+ /* Find the next free page. */
+ while ((i < memPool.pageCount) && (memPool.pageUsage[i].pageCount != 0))
+ {
+ ++i;
+ }
+ }
+
+ if (i >= memPool.pageCount)
+ {
+ *Physical = gcvNULL;
+ *Logical = gcvNULL;
+ pthread_mutex_unlock(&memPool.mutex);
+ /* Not enough contiguous pages. */
+ return;
+ }
+
+ /* Check if we allocate from the first free page. */
+ if (i == memPool.freePage)
+ {
+ /* Move first free page to beyond the contiguous request. */
+ memPool.freePage = i + pageCount;
+
+ /* Find first free page. */
+ while ( (memPool.freePage < memPool.pageCount) &&
+ (memPool.pageUsage[memPool.freePage].pageCount != 0) )
+ {
+ ++memPool.freePage;
+ }
+
+ if (memPool.freePage >= memPool.pageCount)
+ {
+ /* No more free pages. */
+ memPool.freePage = -1;
+ }
+ }
+
+ /* Walk all pages. */
+ for (j = 0; j < pageCount; ++j)
+ {
+ /* Store page count in each pageUsage to mark page is allocated. */
+ memPool.pageUsage[i+j].pageCount = pageCount;
+ }
+
+ gcmkTRACE(gcvLEVEL_INFO, "Allocated %u contiguous pages from 0x%X\n",
+ pageCount, i);
+
+ /* Success. */
+ *Physical = (gctPHYS_ADDR)(i * memPool.pageSize + (gctUINT32)memPool.paddr);
+ *Logical = (gctPOINTER)(i * memPool.pageSize + (gctUINT32)memPool.addr);
+
+ pthread_mutex_unlock(&memPool.mutex);
+}
+
+int drv_mempool_free(gctPOINTER Logical)
+{
+ gctUINT16 pageCount;
+ gctSIZE_T i;
+ gctINT32 pageIndex;
+
+ gcmkTRACE(gcvLEVEL_INFO, "Freeing pages @ %x\n", Logical);
+
+ pthread_mutex_lock(&memPool.mutex);
+
+ pageIndex = ((gctUINT32)Logical - (gctUINT32)memPool.addr) / memPool.pageSize;
+
+ /* Verify the memory is valid and unlocked. */
+ if ( (pageIndex < 0) || (pageIndex >= memPool.pageCount) )
+ {
+ pthread_mutex_unlock(&memPool.mutex);
+ gcmkTRACE(gcvLEVEL_ERROR, "Invalid page index @ %d\n", pageIndex);
+ return -1;
+ }
+
+ pageCount = memPool.pageUsage[pageIndex].pageCount;
+
+ /* Mark all used pages as free. */
+ for (i = 0; i < pageCount; ++i)
+ {
+ gcmkASSERT(memPool.pageUsage[i + pageIndex].pageCount == pageCount);
+
+ memPool.pageUsage[i + pageIndex].pageCount = 0;
+ }
+
+ /* Update first free page. */
+ if ( (memPool.freePage < 0) || (pageIndex < memPool.freePage) )
+ {
+ memPool.freePage = pageIndex;
+ }
+
+ pthread_mutex_unlock(&memPool.mutex);
+
+ gcmkTRACE(gcvLEVEL_INFO, "Free'd %u contiguos pages from 0x%X @ 0x%x\n",
+ pageCount, pageIndex);
+
+ return 1;
+}
+
+/*
+ * Initialize shm pool list and mutex.
+ */
+gceSTATUS
+drv_shm_init()
+{
+ shmPoolList = gcvNULL;
+ pthread_mutex_init(&shmPoolListMutex, 0);
+ return gcvSTATUS_OK;
+/* resmgr_globals.shmpool = gcvNULL;
+ return pthread_mutex_init(&resmgr_globals.shmMutex, 0);*/
+}
+
+gceSTATUS
+drv_shm_destroy()
+{
+ gckSHM_POOL shmPool;
+ gctUINT32 count = 0;
+
+ pthread_mutex_destroy(&shmPoolListMutex);
+
+ shmPool = shmPoolList;
+ while (shmPool != gcvNULL)
+ {
+ /* Remove this pool from the list. */
+ drv_shmpool_destroy(shmPool);
+
+ shmPool = shmPool->nextPool;
+ count++;
+ }
+
+ return gcvSTATUS_OK;
+/* resmgr_globals.shmpool = gcvNULL;
+ return pthread_mutex_destroy(&resmgr_globals.shmMutex);*/
+}
+
+/*
+ * Get the shm pool associated with this Handle and PID and lock it.
+ * Create one, if not present.
+ */
+gckSHM_POOL
+drv_shm_acquire_pool(
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle
+ )
+{
+ gckSHM_POOL shmPool, tail = gcvNULL;
+
+ pthread_mutex_lock(&shmPoolListMutex);
+
+ shmPool = shmPoolList;
+ while (shmPool != gcvNULL)
+ {
+ if (shmPool->Handle == Handle && shmPool->pid == Pid)
+ {
+ pthread_mutex_unlock(&shmPoolListMutex);
+ return shmPool;
+ }
+
+ tail = shmPool;
+ shmPool = shmPool->nextPool;
+ }
+
+ /* TODO: Start with smaller shmMemory pool size and increase on demand. */
+ /* Default 4KB page size. */
+ shmPool = drv_shmpool_create(Pid, Handle, sharedPoolSize, __PAGESIZE);
+
+ /* Add this pool to tail. */
+ if ( shmPool != gcvNULL )
+ {
+ if (tail != gcvNULL )
+ {
+ tail->nextPool = shmPool;
+ }
+ else
+ {
+ /* Set this pool as head. */
+ shmPoolList = shmPool;
+ }
+
+ shmPool->nextPool = gcvNULL;
+ }
+ else
+ {
+ /* Failed to create new shmPool. */
+ }
+
+ pthread_mutex_unlock(&shmPoolListMutex);
+ return shmPool;
+}
+
+/*
+ * Get the shm pool associated with this Logical pointer.
+ */
+gckSHM_POOL
+drv_shm_acquire_pool2(
+ IN gctPOINTER Logical
+ )
+{
+ gckSHM_POOL shmPool, tail = gcvNULL;
+
+ pthread_mutex_lock(&shmPoolListMutex);
+
+ shmPool = shmPoolList;
+ while (shmPool != gcvNULL)
+ {
+ /* Check if this address is in range of this shmPool. */
+ if (shmPool->Logical <= (gctUINT32)Logical &&
+ (shmPool->Logical + shmPool->pageCount * shmPool->pageSize) > (gctUINT32)Logical)
+ {
+ pthread_mutex_unlock(&shmPoolListMutex);
+ return shmPool;
+ }
+
+ tail = shmPool;
+ shmPool = shmPool->nextPool;
+ }
+
+ /* Failed to find associated shmPool. */
+ pthread_mutex_unlock(&shmPoolListMutex);
+ return shmPool;
+}
+
+/*
+ * Remove the shm pool associated with this ocb.
+ */
+gceSTATUS
+drv_shm_remove_pool(
+ IN gctHANDLE Handle
+ )
+{
+ gckSHM_POOL shmPool, prev = gcvNULL;
+
+ pthread_mutex_lock(&shmPoolListMutex);
+
+ shmPool = shmPoolList;
+
+ while (shmPool != gcvNULL)
+ {
+ /* Remove this pool from the list. */
+ if (shmPool->Handle == Handle)
+ {
+ if (prev == gcvNULL)
+ {
+ shmPoolList = shmPool->nextPool;
+ }
+ else
+ {
+ prev->nextPool = shmPool->nextPool;
+ }
+
+ drv_shmpool_destroy(shmPool);
+
+ pthread_mutex_unlock(&shmPoolListMutex);
+ return gcvSTATUS_OK;
+ }
+
+ prev = shmPool;
+ shmPool = shmPool->nextPool;
+ }
+
+ pthread_mutex_unlock(&shmPoolListMutex);
+
+ return gcvSTATUS_INVALID_ARGUMENT;
+}
+
+gceSTATUS
+drv_shmpool_mem_offset(
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address)
+{
+ gctUINT32 logical = (gctUINT32)Logical;
+ gckSHM_POOL shmPool;
+
+ if ( Address == gcvNULL )
+ return gcvSTATUS_INVALID_ARGUMENT;
+
+ pthread_mutex_lock(&shmPoolListMutex);
+
+ shmPool = shmPoolList;
+ while (shmPool != gcvNULL)
+ {
+ if ( (logical >= shmPool->Logical)
+ && (logical < (shmPool->Logical + shmPool->pageCount * shmPool->pageSize)))
+ {
+ *Address = (logical - shmPool->Logical ) + shmPool->Physical;
+ pthread_mutex_unlock(&shmPoolListMutex);
+ return gcvSTATUS_OK;
+ }
+
+ shmPool = shmPool->nextPool;
+ }
+
+ pthread_mutex_unlock(&shmPoolListMutex);
+
+ return gcvSTATUS_INVALID_ARGUMENT;
+}
+
+/* Initialize a shm pool with this ocb. */
+gckSHM_POOL drv_shmpool_create(
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle,
+ IN gctUINT32 PoolSize,
+ IN gctUINT32 PageSize)
+{
+ int rc, poolSize;
+ void* addr;
+ char shm_file_name[20] = "shm_galcore";
+ gctUINT32 i, pid;
+ gckSHM_POOL shm = (gckSHM_POOL) calloc(1, sizeof(struct _gckSHM_POOL));
+
+ /* Compute number of pages. */
+ shm->pageSize = PageSize;
+ shm->pageCount = PoolSize / shm->pageSize;
+ gcmkASSERT(shm->pageCount <= 65536);
+
+ /* Align poolSize to pageSize. */
+ poolSize = shm->pageCount * shm->pageSize;
+
+ shm->pid = Pid;
+ shm->Handle = Handle;
+
+ /* Initialize the semaphore. */
+ if (pthread_mutex_init(&shm->mutex, NULL) != EOK)
+ {
+ fprintf( stderr, "pthread_mutex_init failed: %s\n", strerror( errno ) );
+ free(shm);
+ return gcvNULL;
+ }
+
+ /* Create a pseudo unique name, so as to not open
+ * the same file twice from different threads at the same time. */
+ pid = Pid;
+ i = strlen(shm_file_name);
+ while(pid)
+ {
+ shm_file_name[i++] = (char)(pid % 10 + '0');
+ pid /= 10;
+ }
+ shm_file_name[i] = '\0';
+
+ shm->fd = shm_open(shm_file_name, O_RDWR | O_CREAT, 0777);
+ if (shm->fd == -1) {
+ free(shm);
+ return gcvNULL;
+ }
+
+ shm_unlink(shm_file_name);
+
+ /* Special flags for this shm, to make it write buffered. */
+ rc = shm_ctl_special(shm->fd,
+ SHMCTL_ANON | SHMCTL_PHYS /*| SHMCTL_LAZYWRITE*/,
+ 0,
+ poolSize,
+ 0x9);
+ if (rc == -1) {
+ close(shm->fd);
+ free(shm);
+ return gcvNULL;
+ }
+
+ /* Map this memory inside user and galcore. */
+ addr = mmap64_join(Pid,
+ 0,
+ poolSize,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ shm->fd,
+ 0);
+ if (addr == MAP_FAILED)
+ {
+ free(shm);
+ return gcvNULL;
+ }
+
+ /* TODO: Dont close fd if need to truncate shm later. */
+ rc = close(shm->fd);
+ if (rc == -1) {
+ free(shm);
+ return gcvNULL;
+ }
+
+ shm->Logical = (gctUINT32) addr;
+
+ /* fd should be NOFD here, to get physical address. */
+ rc = mem_offset( addr, NOFD, 1, (off_t *)&shm->Physical, NULL);
+ if (rc == -1) {
+ free(shm);
+ return gcvNULL;
+ }
+
+ /* TODO: MLOCK may or may not be needed!. */
+ mlock((void*)shm->Logical, poolSize);
+
+ /* Allocate the page usage array and Initialize all pages to free. */
+ shm->pageUsage = (gckPAGE_USAGE)calloc(shm->pageCount, sizeof(struct _gckPAGE_USAGE));
+ if (shm->pageUsage == gcvNULL)
+ {
+ munmap((void*)shm->Logical, poolSize);
+ munmap_peer(Pid, (void*)shm->Logical, poolSize);
+ free(shm);
+ return gcvNULL;
+ }
+
+ /* The first page is free. */
+ shm->freePage = 0;
+
+ return shm;
+}
+
+void
+drv_shmpool_destroy(
+ IN gckSHM_POOL ShmPool)
+{
+ if (ShmPool)
+ {
+ int poolSize = ShmPool->pageCount * ShmPool->pageSize;
+ if (ShmPool->pageUsage)
+ free(ShmPool->pageUsage);
+ if (ShmPool->Logical)
+ {
+ munmap((void*)ShmPool->Logical, poolSize);
+ munmap_peer(ShmPool->pid, (void*)ShmPool->Logical, poolSize);
+ }
+ }
+}
+
+gctUINT32
+drv_shmpool_get_BaseAddress(
+ IN gckSHM_POOL ShmPool
+ )
+{
+ gcmkASSERT(ShmPool != 0);
+
+ if (!ShmPool)
+ return 0;
+
+ return ShmPool->Logical;
+}
+
+gctUINT32
+drv_shmpool_get_page_size(
+ IN gckSHM_POOL ShmPool
+ )
+{
+ gcmkASSERT(ShmPool != 0);
+
+ if (!ShmPool)
+ return 0;
+
+ return ShmPool->pageSize;
+}
+
+/* Allocate pages from mapped shared memory.
+ Return Logical user address.
+*/
+gctPOINTER
+drv_shmpool_alloc_contiguous(
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle,
+ IN gctUINT32 Bytes
+ )
+{
+ gctSIZE_T i, j;
+ int pageSize;
+ gctSIZE_T pageCount;
+ gckSHM_POOL shmPool = drv_shm_acquire_pool(Pid, Handle);
+
+ if (shmPool == gcvNULL)
+ {
+ return gcvNULL;
+ }
+ /* Compute the number of required pages. */
+ pageSize = drv_shmpool_get_page_size(shmPool);
+ if ( pageSize == 0 )
+ {
+ /* Invalid pageSize. */
+ return gcvNULL;
+ }
+
+ pageCount = gcmALIGN(Bytes, pageSize) / pageSize;
+
+ if ( (pageCount <= 0) || (shmPool->freePage < 0) )
+ {
+ /* No free pages left. */
+ return gcvNULL;
+ }
+
+ if ( (pageCount <= 0) || (shmPool->freePage < 0) )
+ {
+ /* No free pages left. */
+ return gcvNULL;
+ }
+
+ /* Try finding enough contiguous free pages. */
+ for (i = shmPool->freePage; i < shmPool->pageCount;)
+ {
+ /* All pages behind this free page should be free. */
+ gctSIZE_T j;
+ for (j = 1; j < pageCount; ++j)
+ {
+ if (shmPool->pageUsage[i + j].pageCount != 0)
+ {
+ /* Bail out if page is allocated. */
+ break;
+ }
+ }
+
+ if (j == pageCount)
+ {
+ /* We found a spot that has enough free pages. */
+ break;
+ }
+
+ /* Move to the page after the allocated page. */
+ i += j + 1;
+
+ /* Find the next free page. */
+ while ((i < shmPool->pageCount) && (shmPool->pageUsage[i].pageCount != 0))
+ {
+ ++i;
+ }
+ }
+
+ if (i >= shmPool->pageCount)
+ {
+ /* Not enough contiguous pages. */
+ return gcvNULL;
+ }
+
+ /* Check if we allocate from the first free page. */
+ if (i == shmPool->freePage)
+ {
+ /* Move first free page to beyond the contiguous request. */
+ shmPool->freePage = i + pageCount;
+
+ /* Find first free page. */
+ while ( (shmPool->freePage < shmPool->pageCount) &&
+ (shmPool->pageUsage[shmPool->freePage].pageCount != 0) )
+ {
+ ++shmPool->freePage;
+ }
+
+ if (shmPool->freePage >= shmPool->pageCount)
+ {
+ /* No more free pages. */
+ shmPool->freePage = -1;
+ }
+ }
+
+ /* Walk all pages. */
+ for (j = 0; j < pageCount; ++j)
+ {
+ /* Store page count in each pageUsage to mark page is allocated. */
+ shmPool->pageUsage[i+j].pageCount = pageCount;
+ }
+
+ gcmkTRACE(gcvLEVEL_INFO, "Allocated %u contiguos pages from 0x%X\n",
+ pageCount, i);
+
+ /* Success. */
+ return (gctPOINTER)(i * shmPool->pageSize + shmPool->Logical);
+}
+
+gctUINT32
+drv_shmpool_free(
+ IN gctPOINTER Logical
+ )
+{
+ gctUINT16 pageCount;
+ gctSIZE_T i;
+ gctINT32 pageIndex;
+ gckSHM_POOL shmPool = drv_shm_acquire_pool2(Logical);
+
+ if (shmPool == gcvNULL)
+ {
+ gcmkTRACE(gcvLEVEL_ERROR, "Invalid Logical addr: %x.\n", Logical);
+ return 0;
+ }
+
+ pageIndex = ((gctUINT32)Logical - shmPool->Logical)/shmPool->pageSize;
+
+ gcmkTRACE(gcvLEVEL_INFO, "Freeing pages @ %d\n", pageIndex);
+
+ /* Verify the memory is valid and unlocked. */
+ if ( (pageIndex < 0) || (pageIndex >= shmPool->pageCount) )
+ {
+ gcmkTRACE(gcvLEVEL_ERROR, "Invalid page index @ %d\n", pageIndex);
+
+ return 0;
+ }
+
+ pageCount = shmPool->pageUsage[pageIndex].pageCount;
+
+ /* Mark all used pages as free. */
+ for (i = 0; i < pageCount; ++i)
+ {
+ gcmkASSERT(shmPool->pageUsage[i + pageIndex].pageCount == pageCount);
+
+ shmPool->pageUsage[i + pageIndex].pageCount = 0;
+ }
+
+ /* Update first free page. */
+ if ( (shmPool->freePage < 0) || (pageIndex < shmPool->freePage) )
+ {
+ shmPool->freePage = pageIndex;
+ }
+
+ gcmkTRACE(gcvLEVEL_INFO, "Free'd %u contiguos pages from 0x%X @ 0x%x\n",
+ pageCount, pageIndex);
+
+ return 1;
+}
+
+int drv_msg(resmgr_context_t *ctp,
+ io_msg_t *msg,
+ RESMGR_OCB_T *ocb)
+{
+ gcsDRIVER_ARGS *drvArgs = (gcsDRIVER_ARGS *)msg;
+ int rc;
+ gceSTATUS status;
+ gcsQUEUE_PTR queue;
+
+#define UNLOCK_RESMGR
+#ifdef UNLOCK_RESMGR
+ iofunc_attr_unlock(&attr);
+#endif
+
+ if ((drvArgs->iomsg.i.type != _IO_MSG)
+ || (drvArgs->iomsg.i.mgrid != _IOMGR_VIVANTE)
+ || (drvArgs->iomsg.i.subtype != IOCTL_GCHAL_INTERFACE
+ && drvArgs->iomsg.i.subtype != IOCTL_GCHAL_KERNEL_INTERFACE
+ && drvArgs->iomsg.i.subtype != IOCTL_GCHAL_TERMINATE))
+ {
+ /* Unknown command. Fail the I/O. */
+#ifdef UNLOCK_RESMGR
+ iofunc_attr_lock(&attr);
+#endif
+ rc = ENOSYS;
+ if (ctp->info.scoid != -1)
+ return _RESMGR_STATUS(ctp, rc);
+ return _RESMGR_NOREPLY;
+ }
+
+ if (drvArgs->iomsg.i.subtype == IOCTL_GCHAL_TERMINATE)
+ {
+ /* terminate the resource manager */
+ pthread_kill(resmgr_globals.root, SIGTERM);
+#ifdef UNLOCK_RESMGR
+ iofunc_attr_lock(&attr);
+#endif
+ return _RESMGR_NOREPLY;
+ }
+
+ /* Save channel handle and pid for later functions. */
+ drvArgs->iface.handle = (gctHANDLE)ocb;
+ drvArgs->iface.pid = (gctUINT32)ctp->info.pid;
+
+ /* Store receive ID with signal event so that we can later respond via pulse. */
+ switch (drvArgs->iface.command)
+ {
+ case gcvHAL_SIGNAL:
+ printf("Setup rcvid as:%d\n", ctp->rcvid);
+ drvArgs->iface.u.Signal.rcvid = ctp->rcvid;
+ break;
+
+ case gcvHAL_EVENT_COMMIT:
+ for (queue = drvArgs->iface.u.Event.queue; queue != gcvNULL; queue = queue->next)
+ {
+ if (queue->iface.command == gcvHAL_SIGNAL)
+ {
+ queue->iface.u.Signal.rcvid = ctp->rcvid;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ status = gckKERNEL_Dispatch(galDevice->kernel,
+ (drvArgs->iomsg.i.subtype == IOCTL_GCHAL_INTERFACE),
+ &drvArgs->iface);
+
+ if (gcmIS_ERROR(status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+ "[galcore] gckKERNEL_Dispatch returned %d.\n",
+ status);
+ }
+ else if (gcmIS_ERROR(drvArgs->iface.status))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DRIVER,
+ "[galcore] IOCTL %d returned %d.\n",
+ drvArgs->iface.command,
+ drvArgs->iface.status);
+ }
+
+ /* Reply data back to the user. */
+ MsgReply(ctp->rcvid, EOK, (gctPOINTER) &drvArgs->iface, sizeof(gcsHAL_INTERFACE));
+
+#ifdef UNLOCK_RESMGR
+ iofunc_attr_lock(&attr);
+#endif
+
+ gcmkTRACE(gcvLEVEL_INFO, "Replied message with command %d, status %d\n",
+ drvArgs->iface.command,
+ drvArgs->iface.status);
+
+ return (_RESMGR_NOREPLY);
+}
+
+static int drv_init(void)
+{
+ /* TODO: Enable clock by driver support? */
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "Entering drv_init\n");
+
+ /* Create the GAL device. */
+ gcmkVERIFY_OK(gckGALDEVICE_Construct(irqLine,
+ registerMemBase,
+ registerMemSize,
+ contiguousBase,
+ contiguousSize,
+ bankSize,
+ fastClear,
+ compression,
+ baseAddress,
+ &galDevice));
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "galcore device constructed.\n");
+
+ /* Start the GAL device. */
+ if (gcmIS_ERROR(gckGALDEVICE_Start(galDevice)))
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
+ "[galcore] Can't start the gal device.\n");
+
+ /* Roll back. */
+ gckGALDEVICE_Stop(galDevice);
+ gckGALDEVICE_Destroy(galDevice);
+
+ return -1;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
+ "[galcore] irqLine->%ld, contiguousSize->%lu, memBase->0x%lX\n",
+ irqLine,
+ contiguousSize,
+ registerMemBase);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "[galcore] driver registered successfully.\n");
+
+ return 0;
+}
+
+static void drv_exit(void)
+{
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_DRIVER,
+ "[galcore] Entering drv_exit\n");
+
+ gckGALDEVICE_Stop(galDevice);
+ gckGALDEVICE_Destroy(galDevice);
+
+}
+
+/* Invoked by OS, when a connection is closed or dies. */
+int
+drv_close_ocb(resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb)
+{
+ gckVIDMEM videoMemory;
+ gceSTATUS status;
+
+ /* Free virtual memory owned by this client. */
+ gckMMU_FreeHandleMemory(galDevice->kernel->mmu, (gctHANDLE)ocb);
+
+ /* Free system memory owned by the client. */
+ status = gckKERNEL_GetVideoMemoryPool(galDevice->kernel, gcvPOOL_SYSTEM, &videoMemory);
+
+ if (status == gcvSTATUS_OK)
+ {
+ gckVIDMEM_FreeHandleMemory(videoMemory,
+ (gctHANDLE)ocb);
+ }
+
+ /* Free shared memory and its mapping. */
+ drv_shm_remove_pool(ocb);
+
+ return iofunc_close_ocb_default(ctp, reserved, ocb);
+}
+
+int gpu_init()
+{
+ /* Declare variables we'll be using. */
+ resmgr_attr_t resmgr_attr;
+ sigset_t sigset;
+ int rc;
+
+ if (drv_mempool_init() != gcvSTATUS_OK)
+ {
+ fprintf(stderr, "drv_mempool_init failed.");
+ goto fail_001;
+ }
+
+ if (drv_shm_init() != gcvSTATUS_OK)
+ {
+ fprintf(stderr, "drv_mempool_init failed.");
+ goto fail_002;
+ }
+
+ if (drv_init() != 0)
+ {
+ fprintf(stderr, "drv_init failed.");
+ goto fail_003;
+ }
+
+ /* initialize dispatch interface */
+ if((resmgr_globals.dpp = dispatch_create()) == NULL)
+ {
+ fprintf(stderr, "Unable to allocate dispatch handle.\n");
+ goto fail_004;
+ }
+
+ /* initialize resource manager attributes */
+ memset(&resmgr_attr, 0, sizeof resmgr_attr);
+ resmgr_attr.nparts_max = 1;
+ resmgr_attr.msg_max_size = 2048;
+
+ /* initialize functions for handling messages */
+ iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs,
+ _RESMGR_IO_NFUNCS, &io_funcs);
+
+ /* Register io handling functions. */
+ io_funcs.msg = drv_msg;
+ io_funcs.close_ocb = drv_close_ocb;
+
+
+ /* initialize attribute structure used by the device */
+ iofunc_attr_init(&attr, S_IFNAM | 0666, 0, 0);
+
+ /* attach our device name */
+ resmgr_globals.id = resmgr_attach(
+ resmgr_globals.dpp,/* dispatch handle */
+ &resmgr_attr, /* resource manager attrs */
+ GAL_DEV, /* device name */
+ _FTYPE_ANY, /* open type */
+ _RESMGR_FLAG_SELF, /* flags */
+ &connect_funcs, /* connect routines */
+ &io_funcs, /* I/O routines */
+ &attr); /* handle */
+ if (resmgr_globals.id == -1) {
+ fprintf(stderr, "Unable to attach name.\n");
+ goto fail_005;
+ }
+
+ /* Prevent signals from affecting resmgr threads. */
+ sigfillset(&sigset);
+ sigdelset(&sigset, SIGTERM);
+ pthread_sigmask(SIG_BLOCK, &sigset, NULL);
+
+ /* initialize thread pool attributes */
+ memset(&resmgr_globals.pool_attr, 0, sizeof(resmgr_globals.pool_attr));
+ resmgr_globals.pool_attr.handle = resmgr_globals.dpp;
+ resmgr_globals.pool_attr.context_alloc = resmgr_context_alloc;
+ resmgr_globals.pool_attr.block_func = resmgr_block;
+ resmgr_globals.pool_attr.unblock_func = resmgr_unblock;
+ resmgr_globals.pool_attr.handler_func = resmgr_handler;
+ resmgr_globals.pool_attr.context_free = resmgr_context_free;
+ resmgr_globals.pool_attr.lo_water = 2;
+ resmgr_globals.pool_attr.hi_water = 4;
+ resmgr_globals.pool_attr.increment = 1;
+ resmgr_globals.pool_attr.maximum = 50;
+#if (defined(_NTO_VERSION) && (_NTO_VERSION >= 650))
+ resmgr_globals.pool_attr.tid_name = "galcore-message-handler";
+#endif
+
+ /* allocate a thread pool handle */
+ resmgr_globals.tpp = thread_pool_create(&resmgr_globals.pool_attr, POOL_FLAG_EXIT_SELF);
+ if (resmgr_globals.tpp == NULL)
+ {
+ goto fail_006;
+ }
+
+ rc = pthread_create(NULL, resmgr_globals.pool_attr.attr, (void * (*)(void *))thread_pool_start, resmgr_globals.tpp);
+ if (rc != 0)
+ {
+ goto fail_007;
+ }
+
+ /* TODO: gpu_suspend, gpu_resume */
+
+ return EXIT_SUCCESS;
+
+fail_007:
+ thread_pool_destroy(resmgr_globals.tpp);
+fail_006:
+ resmgr_detach(resmgr_globals.dpp, resmgr_globals.id, 0);
+fail_005:
+ dispatch_destroy(resmgr_globals.dpp);
+fail_004:
+ drv_exit();
+fail_003:
+ drv_shm_destroy();
+fail_002:
+ drv_mempool_destroy();
+fail_001:
+ return EXIT_FAILURE;
+}
+
+int gpu_fini()
+{
+ thread_pool_destroy(resmgr_globals.tpp);
+ resmgr_detach(resmgr_globals.dpp, resmgr_globals.id, 0);
+ dispatch_destroy(resmgr_globals.dpp);
+ drv_exit();
+ drv_shm_destroy();
+ drv_mempool_destroy();
+ return EXIT_SUCCESS;
+}
+
+#ifndef QNX_USE_OLD_FRAMEWORK
+
+int GPU_Startup(win_gpu_2_cm_iface_t *iface)
+{
+ g_qnx_gpu_2_cm_iface = iface;
+ return gpu_init();
+}
+
+int GPU_Shutdown()
+{
+ g_qnx_gpu_2_cm_iface = NULL;
+ return gpu_fini();
+}
+
+void win_gpu_module_getfuncs(win_cm_2_gpu_iface_t *iface)
+{
+ iface->init = GPU_Startup;
+ iface->fini = GPU_Shutdown;
+}
+
+#else /* QNX_USE_OLD_FRAMEWORK */
+
+int drv_resmgr_loop()
+{
+ sigset_t sigset;
+ siginfo_t info;
+
+ resmgr_globals.root = pthread_self();
+
+ /* Background ourselves */
+ procmgr_daemon(EXIT_SUCCESS, PROCMGR_DAEMON_NODEVNULL |
+ PROCMGR_DAEMON_NOCHDIR |
+ PROCMGR_DAEMON_NOCLOSE);
+
+ /*
+ * This thread ignores all signals except SIGTERM. On receipt of
+ * a SIGTERM, we shut everything down and exit.
+ */
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGTERM);
+
+ while (1)
+ {
+ if (SignalWaitinfo(&sigset, &info) == -1)
+ continue;
+ if (info.si_signo == SIGTERM)
+ {
+ break;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int drv_start_cmd()
+{
+ int rc;
+
+ printf("Starting up...\n");
+ fflush(stdout);
+
+ pthread_setname_np(pthread_self(), "vivante-monitor");
+
+ if ((rc = gpu_init()) != EXIT_SUCCESS)
+ {
+ fprintf(stderr, "Initialization failed!, Exiting.");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Running galcore...\n");
+ fflush(stdout);
+ rc = drv_resmgr_loop();
+ printf("Shutting down galcore...\n");
+ fflush(stdout);
+
+ gpu_fini();
+
+ return EXIT_SUCCESS;
+}
+
+int drv_stop_cmd()
+{
+ gcsDRIVER_ARGS args;
+ int fd, rc;
+
+ /* Open the gpu device. */
+ fd = open(DRV_NAME, O_RDONLY);
+ if (fd == -1)
+ {
+ fprintf(stderr, "Could not connect to " DRV_NAME);
+ return EXIT_FAILURE;
+ }
+
+ /* Send the term message. */
+ args.iomsg.i.type = _IO_MSG;
+ args.iomsg.i.subtype = IOCTL_GCHAL_TERMINATE;
+ args.iomsg.i.mgrid = _IOMGR_VIVANTE;
+ args.iomsg.i.combine_len = sizeof(io_msg_t);
+
+ do {
+ rc = MsgSend_r(fd, &args, args.iomsg.i.combine_len, NULL, 0);
+ } while ((rc * -1) == EINTR);
+
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+ enum { start, stop } cmd = start;
+ int i;
+ int rc = EXIT_FAILURE;
+
+ /* Process command lines -start, -stop, -c (file), -d [file]. */
+ for (i = 1; i < argc; i++)
+ {
+ if (stricmp(argv[i], "-start") == 0)
+ {
+ cmd = start;
+ }
+ else if (strcmp(argv[i], "-stop") == 0)
+ {
+ cmd = stop;
+ }
+ else if (strncmp(argv[i], "-poolsize=", strlen("-poolsize=")) == 0)
+ {
+ /* The syntax of the poolsize option is -poolsize=(number).
+ * All we need is to convert the number that starts after the '='.*/
+ contiguousSize = atoi(argv[i] + strlen("-poolsize="));
+ if (contiguousSize <= 0)
+ {
+ fprintf(stderr, "%s: poolsize needs to be a positive number\n", strerror(errno));
+ return rc;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "%s: bad command line\n", argv[0]);
+ return rc;
+ }
+ }
+
+ switch (cmd)
+ {
+ case start:
+ /* Elevate thread priority to do IO. */
+ ThreadCtl(_NTO_TCTL_IO, 0);
+ rc = drv_start_cmd();
+ break;
+
+ case stop:
+ rc = drv_stop_cmd();
+ break;
+ }
+
+ return rc;
+}
+
+#endif /* QNX_USE_OLD_FRAMEWORK */
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+
+
+
+# include <winmgr/gpu.h>
+
+#define USE_VMALLOC 0
+
+#define _GC_OBJ_ZONE gcvZONE_OS
+
+#define MEMORY_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryLock, \
+ gcvINFINITE))
+
+#define MEMORY_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
+
+#define MEMORY_MAP_LOCK(os) \
+ gcmkVERIFY_OK(gckOS_AcquireMutex( \
+ (os), \
+ (os)->memoryMapLock, \
+ gcvINFINITE))
+
+#define MEMORY_MAP_UNLOCK(os) \
+ gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
+
+/******************************************************************************\
+********************************** Structures **********************************
+\******************************************************************************/
+
+struct _gckOS
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Heap. */
+ gckHEAP heap;
+
+ /* Pointer to device */
+ gckGALDEVICE device;
+
+ /* Memory management */
+ gctPOINTER memoryLock;
+ gctPOINTER memoryMapLock;
+ gctPOINTER mempoolBaseAddress;
+ gctPOINTER mempoolBasePAddress;
+ gctUINT32 mempoolPageSize;
+
+ gctUINT32 baseAddress;
+
+ /* Atomic operation lock. */
+ gctPOINTER atomicOperationLock;
+};
+
+
+typedef struct _gcskSIGNAL
+{
+ pthread_mutex_t *mutex;
+
+ /* Manual reset flag. */
+ gctBOOL manualReset;
+}
+gcskSIGNAL;
+
+typedef struct _gcskSIGNAL * gcskSIGNAL_PTR;
+
+
+/*******************************************************************************
+**
+** gckOS_Construct
+**
+** Construct a new gckOS object.
+**
+** INPUT:
+**
+** gctPOINTER Context
+** Pointer to the gckGALDEVICE class.
+**
+** OUTPUT:
+**
+** gckOS * Os
+** Pointer to a variable that will hold the pointer to the gckOS object.
+*/
+gceSTATUS gckOS_Construct(
+ IN gctPOINTER Context,
+ OUT gckOS * Os
+ )
+{
+ gckOS os;
+ gceSTATUS status;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Os != gcvNULL);
+
+ /* Allocate the gckOS object. */
+ os = (gckOS) malloc(gcmSIZEOF(struct _gckOS));
+
+ if (os == gcvNULL)
+ {
+ /* Out of memory. */
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Zero the memory. */
+ memset(os, 0, gcmSIZEOF(struct _gckOS));
+
+ /* Initialize the gckOS object. */
+ os->object.type = gcvOBJ_OS;
+
+ /* Set device device. */
+ os->device = Context;
+
+ /* IMPORTANT! No heap yet. */
+ os->heap = gcvNULL;
+
+ /* Initialize the memory lock. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &os->memoryLock));
+
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &os->memoryMapLock));
+
+ /* Create the gckHEAP object. */
+ gcmkONERROR(
+ gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
+
+ /* Find the base address of the physical memory. */
+ os->baseAddress = os->device->baseAddress;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "Physical base address set to 0x%08X.\n",
+ os->baseAddress);
+
+ os->mempoolBaseAddress = (gctPOINTER) drv_mempool_get_baseAddress();
+ os->mempoolBasePAddress = (gctPOINTER) drv_mempool_get_basePAddress();
+ os->mempoolPageSize = drv_mempool_get_page_size();
+
+
+ /* Initialize the atomic operations lock. */
+ gcmkONERROR(
+ gckOS_CreateMutex(os, &os->atomicOperationLock));
+
+ /* Return pointer to the gckOS object. */
+ *Os = os;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ if (os->heap != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckHEAP_Destroy(os->heap));
+ }
+
+ if (os->memoryMapLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryMapLock));
+ }
+
+ if (os->memoryLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->memoryLock));
+ }
+
+ if (os->atomicOperationLock != gcvNULL)
+ {
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(os, os->atomicOperationLock));
+ }
+
+ free(os);
+
+ /* Return the error. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Destroy
+**
+** Destroy an gckOS object.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object that needs to be destroyed.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Destroy(
+ IN gckOS Os
+ )
+{
+ gckHEAP heap;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ if (Os->heap != NULL)
+ {
+ /* Mark gckHEAP as gone. */
+ heap = Os->heap;
+ Os->heap = NULL;
+
+ /* Destroy the gckHEAP object. */
+ gcmkVERIFY_OK(
+ gckHEAP_Destroy(heap));
+ }
+
+ /* Destroy the memory lock. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->memoryMapLock));
+
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->memoryLock));
+
+ /* Destroy the atomic operation lock. */
+ gcmkVERIFY_OK(
+ gckOS_DeleteMutex(Os, Os->atomicOperationLock));
+
+ /* Mark the gckOS object as unknown. */
+ Os->object.type = gcvOBJ_UNKNOWN;
+
+ /* Free the gckOS object. */
+ free(Os);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_Allocate
+**
+** Allocate memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_Allocate(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gceSTATUS status;
+
+ /*gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);*/
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ /* Do we have a heap? */
+ if (Os->heap != NULL)
+ {
+ /* Allocate from the heap. */
+ gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
+ }
+
+ /* Success. */
+ /*gcmkFOOTER_ARG("*memory=0x%x", *Memory);*/
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Free
+**
+** Free allocated memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Free(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gceSTATUS status;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ /* Do we have a heap? */
+ if (Os->heap != NULL)
+ {
+ /* Free from the heap. */
+ gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
+ }
+ else
+ {
+ gcmkONERROR(gckOS_FreeMemory(Os, Memory));
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+/*******************************************************************************
+**
+** gckOS_AllocateMemory
+**
+** Allocate memory wrapper.
+**
+** INPUT:
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the allocated memory location.
+*/
+gceSTATUS
+gckOS_AllocateMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Memory
+ )
+{
+ gctPOINTER memory;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ memory = (gctPOINTER) calloc(1, Bytes);
+
+ if (memory == NULL)
+ {
+ /* Out of memory. */
+ gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
+ }
+
+ /* Return pointer to the memory allocation. */
+ *Memory = memory;
+
+ /* Success. */
+ gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
+ return gcvSTATUS_OK;
+
+OnError:
+ /* Return the status. */
+ gcmkFOOTER();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeMemory
+**
+** Free allocated memory wrapper.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory allocation to free.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_FreeMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory
+ )
+{
+ gcmkHEADER_ARG("Memory=0x%x", Memory);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Memory != NULL);
+
+ /* Free the memory from the OS pool. */
+ free(Memory);
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapMemory
+**
+** Map physical memory into the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Memory
+** Pointer to a variable that will hold the logical address of the
+** mapped memory.
+*/
+gceSTATUS gckOS_MapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "Enter gckOS_MapMemory\n");
+
+ MEMORY_LOCK(Os);
+
+ /* Map physical address. */
+ *Logical = mmap64(0,
+ Bytes,
+ PROT_READ | PROT_WRITE,
+ MAP_PHYS | MAP_SHARED,
+ NOFD,
+ (off_t)Physical);
+
+ MEMORY_UNLOCK(Os);
+
+ if (*Logical == MAP_FAILED)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: mmap error: %s\n",
+ strerror(errno));
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
+ "gckOS_MapMemory: User Mapped address for 0x%x is 0x%x\n",
+ (gctUINT32)Physical,
+ (gctUINT32)*Logical);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapMemory
+**
+** Unmap physical memory out of the current process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Start of physical address memory.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** gctPOINTER Memory
+** Pointer to a previously mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_UnmapMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != 0);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_UnmapMemory\n");
+
+ if (Logical)
+ {
+ gctUINT32 res;
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_UnmapMemory] Logical: 0x%x\n",
+ Logical
+ );
+
+ MEMORY_LOCK(Os);
+
+ res = munmap(Logical, Bytes);
+
+ MEMORY_UNLOCK(Os);
+
+ if (res == -1)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_UnmapMemory: munmap error: %s\n",
+ strerror(errno));
+
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateNonPagedMemory
+**
+** Allocate a number of pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that holds the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** allocation.
+*/
+gceSTATUS gckOS_AllocateNonPagedMemory(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+
+ if (InUserSpace)
+ {
+ /* TODO: Make a separate OS call for allocating from shared memory pool. */
+ *Logical = drv_shmpool_alloc_contiguous((gctUINT32)Physical, (gctHANDLE)Logical, *Bytes);
+
+ if (*Logical == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocateNonPagedMemory: Out of memory.");
+
+ *Bytes = 0;
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Used to distinguish from memory allocated in kernel space. */
+ *((gctUINT32*)Physical) = 0;
+ }
+ else
+ {
+ drv_mempool_alloc_contiguous(*Bytes, Physical, Logical);
+
+ if (*Physical == gcvNULL || *Logical == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocateNonPagedMemory: Out of memory.");
+
+ *Bytes = 0;
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocateNonPagedMemory: "
+ "Bytes->0x%x, Logical->0x%x Physical->0x%x\n",
+ (gctUINT32)*Bytes,
+ *Logical,
+ *Physical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeNonPagedMemory
+**
+** Free previously allocated and mapped pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes allocated.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocated memory.
+**
+** gctPOINTER Logical
+** Logical address of the allocated memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeNonPagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical
+ )
+{
+ int rc;
+
+ if (Physical)
+ {
+ rc = drv_mempool_free(Logical);
+ }
+ else
+ {
+ rc = drv_shmpool_free(Logical);
+ }
+
+ if (rc == -1)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreeNonPagedMemory: "
+ "Unmap Failed Logical->0x%x, Bytes->%d, Physical->0x%x\n",
+ (gctUINT32)Logical,
+ Bytes,
+ (gctUINT32)Physical);
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_FreeNonPagedMemory: "
+ "Logical->0x%x Physical->0x%x\n",
+ (gctUINT32)Logical,
+ (gctUINT32)Physical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReadRegister
+**
+** Read data from a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** OUTPUT:
+**
+** gctUINT32 * Data
+** Pointer to a variable that receives the data read from the register.
+*/
+gceSTATUS gckOS_ReadRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctUINT32 * Data
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Data != NULL);
+
+ *Data = (gctUINT32)in32((uintptr_t) ((gctUINT8 *)Os->device->registerBase + Address));
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_WriteRegister
+**
+** Write data to a register.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Address of register.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_WriteRegister(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ IN gctUINT32 Data
+ )
+{
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_WriteRegister: "
+ "Writing to physical address [%x] = %x\n",
+ (gctUINT8 *)Os->device->registerBase,
+ Data);
+
+ out32((uintptr_t) ((gctUINT8 *)Os->device->registerBase + Address), (uint32_t)Data);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPageSize
+**
+** Get the system's page size.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctSIZE_T * PageSize
+** Pointer to a variable that will receive the system's page size.
+*/
+gceSTATUS gckOS_GetPageSize(
+ IN gckOS Os,
+ OUT gctSIZE_T * PageSize
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(PageSize != NULL);
+
+ /* Return the page size. */
+ *PageSize = (gctSIZE_T) __PAGESIZE;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddressProcess
+**
+** Get the physical system address of a corresponding virtual address for a
+** given process.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** gctUINT ProcessID
+** Procedd ID.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Poinetr to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS
+gckOS_GetPhysicalAddressProcess(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctUINT ProcessID,
+ OUT gctUINT32 * Address
+ )
+{
+ return gckOS_GetPhysicalAddress(Os, Logical, Address);
+}
+
+/*******************************************************************************
+**
+** gckOS_GetPhysicalAddress
+**
+** Get the physical system address of a corresponding virtual address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Logical address.
+**
+** OUTPUT:
+**
+** gctUINT32 * Address
+** Pointer to a variable that receives the 32-bit physical adress.
+*/
+gceSTATUS gckOS_GetPhysicalAddress(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address
+ )
+{
+
+ gctUINT32 res;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ if ( drv_mempool_mem_offset(Logical, Address) != gcvSTATUS_OK)
+ {
+ if ( drv_shmpool_mem_offset(Logical, Address) != gcvSTATUS_OK)
+ {
+ printf("Warning, using mem_offset for Logical:%x!\n", (gctUINT32) Logical);
+
+ MEMORY_LOCK(Os);
+
+ /* TODO: mem_offset in QNX works only for memory that is allocated
+ contiguosly using gckOS_AllocateContiguous(). */
+ res = mem_offset( Logical, NOFD, 1, (off_t *)Address, NULL);
+
+ if (res == -1)
+ {
+ MEMORY_UNLOCK(Os);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_GetPhysicalAddress: "
+ "Unable to get physical address for 0x%x\n",
+ (gctUINT32)Logical);
+
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ MEMORY_UNLOCK(Os);
+ }
+ }
+
+ /* Subtract base address to get a GPU physical address. */
+ gcmASSERT(*Address >= Os->baseAddress);
+ *Address -= Os->baseAddress;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_GetPhysicalAddress: Logical->0x%x Physical->0x%x\n",
+ (gctUINT32)Logical,
+ (gctUINT32)*Address);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPhysical
+**
+** Map a physical address into kernel space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Physical
+** Physical address of the memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the base address of the mapped
+** memory.
+*/
+gceSTATUS gckOS_MapPhysical(
+ IN gckOS Os,
+ IN gctUINT32 Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ gctUINT32 physical;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
+
+ MEMORY_LOCK(Os);
+
+ /* Compute true physical address (before subtraction of the baseAddress). */
+ physical = Physical + Os->baseAddress;
+
+ /* Map physical address. */
+ *Logical = mmap64(0,
+ Bytes,
+ PROT_READ | PROT_WRITE,
+ MAP_PHYS | MAP_SHARED | MAP_NOINIT,
+ NOFD,
+ (off_t)physical);
+
+ MEMORY_UNLOCK(Os);
+
+ if (*Logical == MAP_FAILED)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_MapMemory: mmap error: %s\n",
+ strerror(errno));
+
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
+ "gckOS_MapPhysical: "
+ "Physical->0x%X Bytes->0x%X Logical->0x%X\n",
+ (gctUINT32) Physical,
+ (gctUINT32) Bytes,
+ (gctUINT32) *Logical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapPhysical
+**
+** Unmap a previously mapped memory region from kernel memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Logical
+** Pointer to the base address of the memory to unmap.
+**
+** gctSIZE_T Bytes
+** Number of bytes to unmap.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_UnmapPhysical(
+ IN gckOS Os,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ gctUINT32 res;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ MEMORY_LOCK(Os);
+
+ res = munmap(Logical, Bytes);
+
+ MEMORY_UNLOCK(Os);
+
+ if (res == -1)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_ERROR,
+ gcvZONE_OS,
+ "gckOS_UnmapMemory: munmap error: %s\n",
+ strerror(errno));
+
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_UnmapPhysical: "
+ "Logical->0x%x Bytes->0x%x\n",
+ (gctUINT32)Logical,
+ (gctUINT32)Bytes);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateMutex
+**
+** Create a new mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** OUTPUT:
+**
+** gctPOINTER * Mutex
+** Pointer to a variable that will hold a pointer to the mutex.
+*/
+gceSTATUS gckOS_CreateMutex(
+ IN gckOS Os,
+ OUT gctPOINTER * Mutex
+ )
+{
+ gctUINT32 res;
+
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+ /* Allocate a FAST_MUTEX structure. */
+ *Mutex = (gctPOINTER) malloc(sizeof(pthread_mutex_t));
+
+ if (*Mutex == gcvNULL)
+ {
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Initialize the semaphore.. Come up in unlocked state. */
+ res = pthread_mutex_init((pthread_mutex_t *)(*Mutex), NULL);
+ if (res != EOK)
+ {
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Return status. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_DeleteMutex
+**
+** Delete a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mute to be deleted.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_DeleteMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ gctUINT32 res;
+
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+ res = pthread_mutex_destroy((pthread_mutex_t *)(Mutex));
+
+ if (res != EOK)
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Delete the fast mutex. */
+ free(Mutex);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AcquireMutex
+**
+** Acquire a mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be acquired.
+**
+** gctUINT32 Timeout
+** Timeout value specified in milliseconds.
+** Specify the value of gcvINFINITE to keep the thread suspended
+** until the mutex has been acquired.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AcquireMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex,
+ IN gctUINT32 Timeout
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
+
+ if (Timeout == gcvINFINITE)
+ {
+ pthread_mutex_lock((pthread_mutex_t *) Mutex);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ while (Timeout-- > 0)
+ {
+ /* Try to acquire the fast mutex. */
+ if (!pthread_mutex_trylock((pthread_mutex_t *) Mutex))
+ {
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+
+ /* Wait for 1 millisecond. */
+ gcmkVERIFY_OK(gckOS_Delay(Os, 1));
+ }
+
+ /* Timeout. */
+ return gcvSTATUS_TIMEOUT;
+}
+
+/*******************************************************************************
+**
+** gckOS_ReleaseMutex
+**
+** Release an acquired mutex.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Mutex
+** Pointer to the mutex to be released.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_ReleaseMutex(
+ IN gckOS Os,
+ IN gctPOINTER Mutex
+ )
+{
+ /* Validate the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Mutex != NULL);
+
+ /* Release the fast mutex. */
+ pthread_mutex_unlock((pthread_mutex_t *) Mutex);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchange
+**
+** Atomically exchange a pair of 32-bit values.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctINT32_PTR Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctINT32 NewValue
+** Specifies a new value for the 32-bit value pointed to by Target.
+**
+** OUT gctINT32_PTR OldValue
+** The old value of the 32-bit value pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchange(
+ IN gckOS Os,
+ IN OUT gctUINT32_PTR Target,
+ IN gctUINT32 NewValue,
+ OUT gctUINT32_PTR OldValue
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Acquire atomic operation lock. */
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
+ Os->atomicOperationLock,
+ gcvINFINITE));
+
+ /* Exchange the pair of 32-bit values. */
+ *OldValue = *Target;
+ *Target = NewValue;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->atomicOperationLock));
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_AtomicExchangePtr
+**
+** Atomically exchange a pair of pointers.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN OUT gctPOINTER * Target
+** Pointer to the 32-bit value to exchange.
+**
+** IN gctPOINTER NewValue
+** Specifies a new value for the pointer pointed to by Target.
+**
+** OUT gctPOINTER * OldValue
+** The old value of the pointer pointed to by Target.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_AtomicExchangePtr(
+ IN gckOS Os,
+ IN OUT gctPOINTER * Target,
+ IN gctPOINTER NewValue,
+ OUT gctPOINTER * OldValue
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ /* Acquire atomic operation lock. */
+ gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
+ Os->atomicOperationLock,
+ gcvINFINITE));
+
+ /* Exchange the pair of pointers. */
+ *OldValue = *Target;
+ *Target = NewValue;
+
+ gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->atomicOperationLock));
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_Delay
+**
+** Delay execution of the current thread for a number of milliseconds.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Delay
+** Delay to sleep, specified in milliseconds.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_Delay(
+ IN gckOS Os,
+ IN gctUINT32 Delay
+ )
+{
+ /* Schedule delay. */
+ delay(Delay);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MemoryBarrier
+**
+** Make sure the CPU has executed everything up to this point and the data got
+** written to the specified pointer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of memory that needs to be barriered.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_MemoryBarrier(
+ IN gckOS Os,
+ IN gctPOINTER Address
+ )
+{
+ /* Verify thearguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ __cpu_membarrier();
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemory
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS
+gckOS_AllocatePagedMemory(
+ IN gckOS Os,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ return gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical);
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocatePagedMemoryEx
+**
+** Allocate memory from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL Contiguous
+** Need contiguous memory or not.
+**
+** gctSIZE_T Bytes
+** Number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+*/
+gceSTATUS gckOS_AllocatePagedMemoryEx(
+ IN gckOS Os,
+ IN gctBOOL Contiguous,
+ IN gctSIZE_T Bytes,
+ OUT gctPHYS_ADDR * Physical
+ )
+{
+ int rc, fd, shm_ctl_flags = SHMCTL_ANON | SHMCTL_LAZYWRITE;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_AllocatePagedMemory\n");
+
+ if (Contiguous)
+ {
+ shm_ctl_flags |= SHMCTL_PHYS;
+ }
+
+ /* Lock down, to avoid opening same shm file twice. */
+ MEMORY_LOCK(Os);
+
+ fd = shm_open("shm_gal", O_RDWR | O_CREAT, 0777);
+ if (fd == -1) {
+ printf("shm_open failed. error %s\n", strerror( errno ) );
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* Free to use the same name for next create shm object after shm_unlink. */
+ shm_unlink("shm_gal");
+
+ MEMORY_UNLOCK(Os);
+
+ /* Special flags for this shm, to make it write buffered. */
+ /* Virtual memory doesn't need to be physically contiguous. */
+ /* Allocations would be page aligned. */
+ rc = shm_ctl_special(fd,
+ SHMCTL_ANON /*| SHMCTL_PHYS*/ | SHMCTL_LAZYWRITE,
+ 0,
+ Bytes,
+ 0x9);
+ if (rc == -1) {
+ printf("shm_ctl_special failed. error %s\n", strerror( errno ) );
+ close(fd);
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ /* Use the fd as the handle for the physical memory just allocated. */
+ *Physical = (gctPHYS_ADDR) fd;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocatePagedMemory: "
+ "Bytes->0x%x, Physical->0x%x\n",
+ (gctUINT32)Bytes,
+ (gctUINT32)*Physical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_FreePagedMemory
+**
+** Free memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreePagedMemory(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes
+ )
+{
+ int rc;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_FreePagedMemory\n");
+
+ rc = close((gctINT)Physical);
+ if ( rc == -1 )
+ {
+ printf("gckOS_FreePagedMemory failed. error: %s\n", strerror( errno ) );
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_LockPages
+**
+** Lock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the address of the mapped
+** memory.
+**
+** gctSIZE_T * PageCount
+** Pointer to a variable that receives the number of pages required for
+** the page table.
+*/
+gceSTATUS gckOS_LockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctUINT32 Pid,
+ OUT gctPOINTER * Logical,
+ OUT gctSIZE_T * PageCount
+ )
+{
+ void* addr;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+ gcmkVERIFY_ARGUMENT(PageCount != NULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_LockPages\n");
+
+ /* Map this memory inside user and galcore. */
+ addr = mmap64_join(Pid,
+ 0,
+ Bytes,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ (int)Physical,
+ 0);
+
+ if (addr == MAP_FAILED)
+ {
+ printf("gckOS_LockPages: couldn't map memory of size %d, Pid: %x [errno %s]",
+ (gctUINT32)Bytes, Pid, strerror( errno ) );
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* TODO: MLOCK may or may not be needed!. */
+ mlock((void*)addr, Bytes);
+
+ *Logical = (gctPOINTER)addr;
+ *PageCount = (gcmALIGN(Bytes, __PAGESIZE)) / __PAGESIZE;
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_LockPages: "
+ "gctPHYS_ADDR->0x%x Bytes->0x%x Logical->0x%x pid->%d\n",
+ (gctUINT32)Physical,
+ (gctUINT32)Bytes,
+ (gctUINT32)*Logical,
+ Pid);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapPages
+**
+** Map paged memory into a page table.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T PageCount
+** Number of pages required for the physical address.
+**
+** gctPOINTER PageTable
+** Pointer to the page table to fill in.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_MapPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T PageCount,
+ IN gctPOINTER PageTable
+ )
+{
+ gctUINT32* table;
+ gctPOINTER addr;
+ size_t contigLen = 0;
+ off_t offset;
+ gctUINT32 bytes;
+ int rc;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(PageCount > 0);
+ gcmkVERIFY_ARGUMENT(PageTable != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_MapPages\n");
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_MapPages: "
+ "Physical->0x%x PageCount->0x%x Logical->0x%x\n",
+ (gctUINT32)Physical,
+ (gctUINT32)PageCount,
+ (gctUINT32)Logical);
+
+ addr = Logical;
+ table = (gctUINT32 *)PageTable;
+ bytes = PageCount * __PAGESIZE;
+
+ /* Try to get the user pages so DMA can happen. */
+ while (PageCount > 0)
+ {
+ /* fd should be NOFD here, to get physical address. */
+ rc = mem_offset( addr, NOFD, bytes, &offset, &contigLen);
+ if (rc == -1) {
+ printf("gckOS_MapPages: mem_offset failed: %s\n", strerror( errno ) );
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ gcmASSERT(contigLen > 0);
+
+ while(contigLen > 0)
+ {
+ *table++ = (gctUINT32) offset;
+ offset += 4096;
+ addr += 4096;
+ contigLen -= 4096;
+ bytes -= 4096;
+ PageCount--;
+ }
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnlockPages
+**
+** Unlock memory allocated from the paged pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** gctPOINTER Logical
+** Address of the mapped memory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_UnlockPages(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctUINT32 Pid,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ int rc = 0;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Physical != NULL);
+ gcmkVERIFY_ARGUMENT(Logical != NULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "in gckOS_UnlockPages\n");
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_MapPages: "
+ "Physical->0x%x Bytes->0x%x Logical->0x%x Pid->0x%x\n",
+ (gctUINT32)Physical,
+ (gctUINT32)Bytes,
+ (gctUINT32)Logical,
+ (gctUINT32)Pid);
+
+ rc = munmap((void*)Logical, Bytes);
+ if (rc == -1) {
+ printf("munmap failed: %s\n", strerror( errno ) );
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ rc = munmap_peer(Pid, (void*)Logical, Bytes);
+ if (rc == -1) {
+ printf("munmap_peer failed: %s\n", strerror( errno ) );
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_AllocateContiguous
+**
+** Allocate memory from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that receives the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that receives the physical address of the
+** memory allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that receives the logical address of the
+** memory allocation.
+*/
+gceSTATUS gckOS_AllocateContiguous(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+ /* Same as non-paged memory for now. */
+ return gckOS_AllocateNonPagedMemory(Os,
+ InUserSpace,
+ Bytes,
+ Physical,
+ Logical
+ );
+}
+
+/*******************************************************************************
+**
+** gckOS_FreeContiguous
+**
+** Free memory allocated from the contiguous pool.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of the allocation.
+**
+** gctPOINTER Logical
+** Logicval address of the allocation.
+**
+** gctSIZE_T Bytes
+** Number of bytes of the allocation.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS gckOS_FreeContiguous(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Physical,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ /* Same of non-paged memory for now. */
+ return gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical);
+}
+
+/******************************************************************************
+**
+** gckOS_GetKernelLogical
+**
+** Return the kernel logical pointer that corresponds to the specified
+** hardware address.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctUINT32 Address
+** Hardware physical address.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the pointer in kernel address space.
+*/
+gceSTATUS
+gckOS_GetKernelLogical(
+ IN gckOS Os,
+ IN gctUINT32 Address,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ gceSTATUS status;
+
+ do
+ {
+ gckGALDEVICE device;
+ gckKERNEL kernel;
+ gcePOOL pool;
+ gctUINT32 offset;
+ gctPOINTER logical;
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Os->device;
+
+ /* Kernel shortcut. */
+ kernel = device->kernel;
+
+ /* Split the memory address into a pool type and offset. */
+ gcmkERR_BREAK(gckHARDWARE_SplitMemory(
+ kernel->hardware, Address, &pool, &offset
+ ));
+
+ /* Dispatch on pool. */
+ switch (pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ logical = device->internalLogical;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ logical = device->externalLogical;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ logical = device->contiguousBase;
+ break;
+
+ default:
+ /* Invalid memory pool. */
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ /* Build logical address of specified address. */
+ * KernelPointer = ((gctUINT8_PTR) logical) + offset;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+ }
+ while (gcvFALSE);
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapUserPointer
+**
+** Map a pointer from the user process into the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be mapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be mapped.
+**
+** OUTPUT:
+**
+** gctPOINTER * KernelPointer
+** Pointer to a variable receiving the mapped pointer in kernel address
+** space.
+*/
+gceSTATUS
+gckOS_MapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * KernelPointer
+ )
+{
+ /* A pointer is assumed to be allocated from its shared memory object.
+ Which is mapped by both user and kernel at the same vitual address. */
+ /* TODO: Check if Pointer is a valid pointer? */
+ *KernelPointer = Pointer;
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserPointer
+**
+** Unmap a user process pointer from the kernel address space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Pointer
+** Pointer in user process space that needs to be unmapped.
+**
+** gctSIZE_T Size
+** Number of bytes that need to be unmapped.
+**
+** gctPOINTER KernelPointer
+** Pointer in kernel address space that needs to be unmapped.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserPointer(
+ IN gckOS Os,
+ IN gctPOINTER Pointer,
+ IN gctSIZE_T Size,
+ IN gctPOINTER KernelPointer
+ )
+{
+ /* Nothing to unmap. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapUserPhysical
+**
+** Map a physical address from the user process into the kernel address space.
+** The physical address should be obtained by user from gckOS_AllocateNonPagedMemory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** IN gctPHYS_ADDR Phys,
+** Physical address of memory that needs to be mapped.
+**
+** OUTPUT:
+**
+** gctPHYS_ADDR * KernelPointer
+** Pointer to a variable receiving the mapped pointer in kernel address
+** space.
+*/
+gceSTATUS
+gckOS_MapUserPhysical(
+ IN gckOS Os,
+ IN gctPHYS_ADDR Phys,
+ OUT gctPHYS_ADDR * KernelPointer
+ )
+{
+ /* A gctPHYS_ADDR is assumed to be allocated from physical memory pool. */
+ /* Dont call this function for pointers already in kernel space. */
+ printf("ERROR: %s Not supported.\n", __FUNCTION__);
+ *KernelPointer = (gctPHYS_ADDR)0xDEADBEEF;
+
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+
+/*******************************************************************************
+**
+** gckOS_WriteMemory
+**
+** Write data to a memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctPOINTER Address
+** Address of the memory to write to.
+**
+** gctUINT32 Data
+** Data for register.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WriteMemory(
+ IN gckOS Os,
+ IN gctPOINTER Address,
+ IN gctUINT32 Data
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_ARGUMENT(Address != NULL);
+
+ /* Write memory. */
+ *(gctUINT32 *)Address = Data;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_CreateSignal
+**
+** Create a new signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL ManualReset
+** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
+** order to set the signal to nonsignaled state.
+** If set to gcvFALSE, the signal will automatically be set to
+** nonsignaled state by gckOS_WaitSignal function.
+** Nonsignaled state in QNX is mutex acquired (not free).
+**
+** OUTPUT:
+**
+** gctSIGNAL * Signal
+** Pointer to a variable receiving the created gctSIGNAL.
+*/
+gceSTATUS
+gckOS_CreateSignal(
+ IN gckOS Os,
+ IN gctBOOL ManualReset,
+ OUT gctSIGNAL * Signal
+ )
+{
+ gcskSIGNAL_PTR signal;
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Os=0x%x ManualReset=0x%x", Os, ManualReset);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+ /* Create an event structure. */
+ signal = (gcskSIGNAL_PTR) malloc(sizeof(gcskSIGNAL));
+
+ if (signal == gcvNULL)
+ {
+ gcmFOOTER_NO();
+ return gcvSTATUS_OUT_OF_MEMORY;
+ }
+
+ signal->manualReset = ManualReset;
+
+ status = gckOS_CreateMutex(Os, (gctPOINTER *)(&signal->mutex));
+
+ if (gcmIS_ERROR(status))
+ {
+ /* Error. */
+ free(signal);
+ gcmFOOTER();
+ return status;
+ }
+
+ *Signal = (gctSIGNAL) signal;
+
+ /* Success. */
+ gcmkFOOTER_ARG("Os=0x%x Signal=0x%x", Os, Signal);
+ return gcvSTATUS_OK;
+
+}
+
+/*******************************************************************************
+**
+** gckOS_DestroySignal
+**
+** Destroy a signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_DestroySignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal
+ )
+{
+
+ gceSTATUS status = gcvSTATUS_OK;
+ gcskSIGNAL_PTR signal;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x", Os, Signal);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+ signal = (gcskSIGNAL_PTR) Signal;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != NULL);
+
+ if (signal != gcvNULL )
+ {
+ status = gckOS_DeleteMutex(Os, (gctPOINTER)(signal->mutex));
+
+ free(signal);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_Signal
+**
+** Set a state of the specified signal.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctBOOL State
+** If gcvTRUE, the signal will be set to signaled state.
+** If gcvFALSE, the signal will be set to nonsignaled state.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_Signal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctBOOL State
+ )
+{
+ gcskSIGNAL_PTR signal;
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcmkHEADER_ARG("Os=0x%x Signal=0x%x State=%d", Os, Signal, State);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcskSIGNAL_PTR) Signal;
+
+ /* Set the new state of the event. */
+ if (signal->manualReset && State)
+ {
+ /* Set the event to a signaled state. */
+ gckOS_ReleaseMutex(Os,(gctPOINTER *)(&signal->mutex));
+ }
+ else
+ {
+ gckOS_AcquireMutex(Os, (gctPOINTER *)(&signal->mutex), gcvINFINITE);
+ }
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_UserSignal
+**
+** Set the specified signal which is owned by a process to signaled state.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UserSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctINT Rcvid,
+ IN gctINT Coid
+ )
+{
+ gctINT rc;
+ struct sigevent event;
+
+ SIGEV_PULSE_INIT( &event, Coid, SIGEV_PULSE_PRIO_INHERIT, _PULSE_CODE_MINAVAIL, Signal);
+
+ rc = MsgDeliverEvent_r(Rcvid, &event);
+ if (rc != EOK)
+ {
+ gcmkTRACE(gcvLEVEL_INFO,
+ "%s(%d): Sent signal to (receive ID = %d, connect ID = %d).",
+ __FUNCTION__, __LINE__, Rcvid, Coid);
+
+ gcmkTRACE(gcvLEVEL_ERROR,
+ "%s(%d): MsgDeliverEvent failed (%d).",
+ __FUNCTION__, __LINE__, rc);
+
+;
+
+ return gcvSTATUS_GENERIC_IO;
+ }
+
+ /* Return status. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_WaitSignal
+**
+** Wait for a signal to become signaled.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to the gctSIGNAL.
+**
+** gctUINT32 Wait
+** Number of milliseconds to wait.
+** Pass the value of gcvINFINITE for an infinite wait.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_WaitSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctUINT32 Wait
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+
+ gcskSIGNAL_PTR signal;
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
+
+ signal = (gcskSIGNAL_PTR) Signal;
+
+ status = gckOS_AcquireMutex(Os, (gctPOINTER *)(&signal->mutex), Wait);
+
+ /* If manualReset is true, use gckOS_Signal to acquire mutex again. */
+ if (signal->manualReset)
+ {
+ status = gckOS_ReleaseMutex(Os, (gctPOINTER *)(&signal->mutex));
+ }
+
+ /* Return status. */
+ return status;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapSignal
+**
+** Map a signal in to the current process space.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctSIGNAL Signal
+** Pointer to tha gctSIGNAL to map.
+**
+** gctHANDLE Process
+** Handle of process owning the signal.
+**
+** OUTPUT:
+**
+** gctSIGNAL * MappedSignal
+** Pointer to a variable receiving the mapped gctSIGNAL.
+*/
+gceSTATUS
+gckOS_MapSignal(
+ IN gckOS Os,
+ IN gctSIGNAL Signal,
+ IN gctHANDLE Process,
+ OUT gctSIGNAL * MappedSignal
+ )
+{
+ printf("ERROR: %s Not supported.\n", __FUNCTION__);
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_MapUserMemory
+**
+** Lock down a user buffer and return an DMA'able address to be used by the
+** hardware to access it.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to lock down.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to lock down.
+**
+** OUTPUT:
+**
+** gctPOINTER * Info
+** Pointer to variable receiving the information record required by
+** gckOS_UnmapUserMemory.
+**
+** gctUINT32_PTR Address
+** Pointer to a variable that will receive the address DMA'able by the
+** hardware.
+*/
+gceSTATUS
+gckOS_MapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ OUT gctPOINTER * Info,
+ OUT gctUINT32_PTR Address
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Address != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] enter.\n"
+ );
+
+ printf("ERROR: %s Not supported.\n", __FUNCTION__);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_MapUserMemory] leave.\n"
+ );
+
+ /* Return the status. */
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_UnmapUserMemory
+**
+** Unlock a user buffer and that was previously locked down by
+** gckOS_MapUserMemory.
+**
+** INPUT:
+**
+** gctPOINTER Memory
+** Pointer to memory to unlock.
+**
+** gctSIZE_T Size
+** Size in bytes of the memory to unlock.
+**
+** gctPOINTER Info
+** Information record returned by gckOS_MapUserMemory.
+**
+** gctUINT32_PTR Address
+** The address returned by gckOS_MapUserMemory.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckOS_UnmapUserMemory(
+ IN gckOS Os,
+ IN gctPOINTER Memory,
+ IN gctSIZE_T Size,
+ IN gctPOINTER Info,
+ IN gctUINT32 Address
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
+ gcmkVERIFY_ARGUMENT(Size > 0);
+ gcmkVERIFY_ARGUMENT(Info != gcvNULL);
+
+ gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
+ gcvZONE_OS,
+ "[gckOS_UnmapUserMemory] enter.\n"
+ );
+
+ printf("ERROR: %s Not supported.\n", __FUNCTION__);
+
+ /* Return the status. */
+ return gcvSTATUS_NOT_SUPPORTED;
+}
+
+/*******************************************************************************
+**
+** gckOS_GetBaseAddress
+**
+** Get the base address for the physical memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to the gckOS object.
+**
+** OUTPUT:
+**
+** gctUINT32_PTR BaseAddress
+** Pointer to a variable that will receive the base address.
+*/
+gceSTATUS
+gckOS_GetBaseAddress(
+ IN gckOS Os,
+ OUT gctUINT32_PTR BaseAddress
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+ gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
+
+ /* Return base address. */
+ *BaseAddress = Os->baseAddress;
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_SuspendInterrupt(
+ IN gckOS Os
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ InterruptLock(&Os->device->isrLock);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_ResumeInterrupt(
+ IN gckOS Os
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
+
+ InterruptUnlock(&Os->device->isrLock);
+
+ return gcvSTATUS_OK;
+}
+
+gceSTATUS
+gckOS_NotifyIdle(
+ IN gckOS Os,
+ IN gctBOOL Idle
+ )
+{
+ /* TODO */
+ return gcvSTATUS_OK;
+}
+
+/* Perform a memory copy. */
+gceSTATUS
+gckOS_MemCopy(
+ IN gctPOINTER Destination,
+ IN gctCONST_POINTER Source,
+ IN gctSIZE_T Bytes
+ )
+{
+ gcmkVERIFY_ARGUMENT(Destination != NULL);
+ gcmkVERIFY_ARGUMENT(Source != NULL);
+ gcmkVERIFY_ARGUMENT(Bytes > 0);
+
+ memcpy(Destination, Source, Bytes);
+
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckOS_AllocateNonPagedMemory
+**
+** Allocate a number of pages from non-paged memory.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to an gckOS object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE if the pages need to be mapped into user space.
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that holds the number of bytes to allocate.
+**
+** OUTPUT:
+**
+** gctSIZE_T * Bytes
+** Pointer to a variable that hold the number of bytes allocated.
+**
+** gctPHYS_ADDR * Physical
+** Pointer to a variable that will hold the physical address of the
+** allocation.
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** allocation.
+*/
+gceSTATUS
+gckOS_AllocateNonPagedMemoryShmPool(
+ IN gckOS Os,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle,
+ IN OUT gctSIZE_T * Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ )
+{
+
+ if (InUserSpace)
+ {
+ *Logical = drv_shmpool_alloc_contiguous(Pid, Handle, *Bytes);
+
+ if (*Logical == gcvNULL)
+ {
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocateNonPagedMemory: Out of memory.");
+
+ *Bytes = 0;
+ return gcvSTATUS_OUT_OF_RESOURCES;
+ }
+
+ /* Used to distinguish from memory allocated in kernel space. */
+ *((gctUINT32*)Physical) = 0;
+ }
+ else
+ {
+ return gcvSTATUS_INVALID_ARGUMENT;
+ }
+
+ gcmkTRACE_ZONE(gcvLEVEL_INFO,
+ gcvZONE_OS,
+ "gckOS_AllocateNonPagedMemoryShmPool: "
+ "Bytes->0x%x, Logical->0x%x Physical->0x%x\n",
+ (gctUINT32)*Bytes,
+ *Logical,
+ *Physical);
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+int
+memmgr_peer_sendnc(pid_t pid, int coid, void *smsg, size_t sbytes, void *rmsg, size_t rbytes )
+{
+ mem_peer_t peer;
+ iov_t siov[2];
+ int rc;
+
+ peer.i.type = _MEM_PEER;
+ peer.i.peer_msg_len = sizeof(peer);
+ peer.i.pid = pid;
+
+ SETIOV(siov + 0, &peer, sizeof peer);
+ SETIOV(siov + 1, smsg, sbytes);
+
+ do {
+ rc = MsgSendvsnc(coid, siov, 2, rmsg, rbytes);
+ } while (rc == -1 && errno == EINTR);
+
+ return rc;
+}
+
+void *
+_mmap2_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off,
+ unsigned align, unsigned pre_load, void **base, size_t *size) {
+ mem_map_t msg;
+
+ msg.i.type = _MEM_MAP;
+ msg.i.zero = 0;
+ msg.i.addr = (uintptr_t)addr;
+ msg.i.len = len;
+ msg.i.prot = prot;
+ msg.i.flags = flags;
+ msg.i.fd = fd;
+ msg.i.offset = off;
+ msg.i.align = align;
+ msg.i.preload = pre_load;
+ msg.i.reserved1 = 0;
+ if (memmgr_peer_sendnc(pid, MEMMGR_COID, &msg.i, sizeof msg.i, &msg.o, sizeof msg.o) == -1) {
+ return MAP_FAILED;
+ }
+ if (base) {
+ *base = (void *)(uintptr_t)msg.o.real_addr;
+ }
+ if (size) {
+ *size = msg.o.real_size;
+ }
+ return (void *)(uintptr_t)msg.o.addr;
+}
+
+void *
+mmap64_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off) {
+ return _mmap2_peer(pid, addr, len, prot, flags, fd, off, 0, 0, 0, 0);
+}
+
+int
+munmap_flags_peer(pid_t pid, void *addr, size_t len, unsigned flags) {
+ mem_ctrl_t msg;
+
+ msg.i.type = _MEM_CTRL;
+ msg.i.subtype = _MEM_CTRL_UNMAP;
+ msg.i.addr = (uintptr_t)addr;
+ msg.i.len = len;
+ msg.i.flags = flags;
+ return memmgr_peer_sendnc(pid, MEMMGR_COID, &msg.i, sizeof msg.i, 0, 0);
+}
+
+int
+munmap_peer(pid_t pid, void *addr, size_t len) {
+ return munmap_flags_peer(pid, addr, len, 0);
+}
+
+int
+mem_offset64_peer(pid_t pid, const uintptr_t addr, size_t len,
+ off64_t *offset, size_t *contig_len) {
+ int rc;
+
+ struct _peer_mem_off {
+ struct _mem_peer peer;
+ struct _mem_offset msg;
+ };
+ typedef union {
+ struct _peer_mem_off i;
+ struct _mem_offset_reply o;
+ } memoffset_peer_t;
+ memoffset_peer_t msg;
+
+ msg.i.peer.type = _MEM_PEER;
+ msg.i.peer.peer_msg_len = sizeof(msg.i.peer);
+ msg.i.peer.pid = pid;
+ msg.i.peer.reserved1 = 0;
+
+ msg.i.msg.type = _MEM_OFFSET;
+ msg.i.msg.subtype = _MEM_OFFSET_PHYS;
+ msg.i.msg.addr = addr;
+ msg.i.msg.reserved = -1;
+ msg.i.msg.len = len;
+
+ do {
+ rc = MsgSendnc(MEMMGR_COID, &msg.i, sizeof msg.i, &msg.o, sizeof msg.o);
+ } while (rc == -1 && errno == EINTR);
+
+ if (rc == -1) {
+ return -1;
+ }
+
+ *offset = msg.o.offset;
+ *contig_len = msg.o.size;
+
+ return 0;
+}
+
+#if defined(__X86__)
+#define CPU_VADDR_SERVER_HINT 0x30000000u
+#elif defined(__ARM__)
+#define CPU_VADDR_SERVER_HINT 0x20000000u
+#else
+#error NO CPU SOUP FOR YOU!
+#endif
+
+/*
+ * map the object into both client and server at the same virtual address
+ */
+void *
+mmap64_join(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off) {
+ void *svaddr, *cvaddr = MAP_FAILED;
+ uintptr_t hint = (uintptr_t)addr;
+ uintptr_t start_hint = hint;
+
+ if ( hint == (uintptr_t)0 )
+ {
+ hint = (uintptr_t)CPU_VADDR_SERVER_HINT;
+ }
+
+ do {
+ svaddr = mmap64( (void *)hint, len, prot, flags, fd, off );
+ if ( svaddr == MAP_FAILED ) {
+ break;
+ }
+ if ( svaddr == cvaddr ) {
+ return svaddr;
+ }
+
+ cvaddr = mmap64_peer( pid, svaddr, len, prot, MAP_FIXED | flags, fd, off );
+ if ( cvaddr == MAP_FAILED ) {
+ break;
+ }
+ if ( svaddr == cvaddr ) {
+ return svaddr;
+ }
+
+ if ( munmap( svaddr, len ) == -1 ) {
+ svaddr = MAP_FAILED;
+ break;
+ }
+
+ svaddr = mmap64( cvaddr, len, prot, flags, fd, off );
+ if ( svaddr == MAP_FAILED ) {
+ break;
+ }
+ if ( svaddr == cvaddr ) {
+ return svaddr;
+ }
+
+ if ( munmap( svaddr, len ) == -1 ) {
+ svaddr = MAP_FAILED;
+ break;
+ }
+ if ( munmap_peer( pid, cvaddr, len ) == -1 ) {
+ cvaddr = MAP_FAILED;
+ break;
+ }
+ hint += __PAGESIZE;
+
+ } while(hint != start_hint); /* do we really want to wrap all the way */
+
+ if ( svaddr != MAP_FAILED ) {
+ munmap( svaddr, len );
+ }
+ if ( cvaddr != MAP_FAILED ) {
+ munmap_peer( pid, cvaddr, len );
+ }
+
+ return MAP_FAILED;
+}
+
+/*******************************************************************************
+** gckOS_CacheFlush
+**
+** Flush the cache for the specified addresses. The GPU is going to need the
+** data. If the system is allocating memory as non-cachable, this function can
+** be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctHANDLE Process
+** Process handle Logical belongs to or gcvNULL if Logical belongs to
+** the kernel.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheFlush(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** gckOS_CacheInvalidate
+**
+** Flush the cache for the specified addresses and invalidate the lines as
+** well. The GPU is going to need and modify the data. If the system is
+** allocating memory as non-cachable, this function can be ignored.
+**
+** ARGUMENTS:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gctHANDLE Process
+** Process handle Logical belongs to or gcvNULL if Logical belongs to
+** the kernel.
+**
+** gctPOINTER Logical
+** Logical address to flush.
+**
+** gctSIZE_T Bytes
+** Size of the address range in bytes to flush.
+*/
+gceSTATUS
+gckOS_CacheInvalidate(
+ IN gckOS Os,
+ IN gctHANDLE Process,
+ IN gctPOINTER Logical,
+ IN gctSIZE_T Bytes
+ )
+{
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+** Broadcast interface.
+*/
+
+gceSTATUS
+gckOS_Broadcast(
+ IN gckOS Os,
+ IN gckHARDWARE Hardware,
+ IN gceBROADCAST Reason
+ )
+{
+ return gcvSTATUS_OK;
+}
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+
+/*
+ * Os.h
+ *
+ * Created on: Feb 2, 2010
+ * Author: Tarang Vaish
+ */
+
+#ifndef __gc_hal_kernel_os_h_
+#define __gc_hal_kernel_os_h_
+
+typedef struct
+{
+ io_msg_t iomsg;
+ gcsHAL_INTERFACE iface;
+} gcsDRIVER_ARGS;
+
+struct _gckPAGE_USAGE
+{
+ gctUINT16 pageCount;
+};
+
+struct _gckSHM_POOL
+{
+ gctHANDLE Handle;
+ gctINT32 fd;
+ gctUINT32 pid;
+ gctUINT32 freePage;
+ gctUINT32 pageCount;
+ gctUINT32 pageSize;
+ pthread_mutex_t mutex;
+ gctUINT32 Logical;
+ gctUINT32 Physical;
+ struct _gckPAGE_USAGE* pageUsage;
+ struct _gckSHM_POOL* nextPool;
+};
+
+typedef struct _gckSHM_POOL* gckSHM_POOL;
+typedef struct _gckPAGE_USAGE* gckPAGE_USAGE;
+
+gceSTATUS
+drv_mempool_init();
+
+void
+drv_mempool_destroy();
+
+void
+drv_mempool_alloc_contiguous(
+ IN gctUINT32 Bytes,
+ OUT gctPHYS_ADDR * Physical,
+ OUT gctPOINTER * Logical
+ );
+
+int
+drv_mempool_free(
+ IN gctPOINTER Logical
+ );
+
+gctUINT32
+drv_mempool_get_baseAddress();
+
+gctUINT32
+drv_mempool_get_basePAddress();
+
+gctUINT32
+drv_mempool_get_page_size();
+
+gctINT
+drv_mempool_get_fileDescriptor();
+
+gceSTATUS
+drv_mempool_mem_offset(
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address);
+
+/* Shared memory pool functions. */
+gckSHM_POOL drv_shmpool_create(
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle,
+ IN gctUINT32 PoolSize,
+ IN gctUINT32 PageSize);
+void
+drv_shmpool_destroy(
+ IN gckSHM_POOL ShmPool);
+
+gckSHM_POOL
+drv_shm_acquire_pool(
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle
+ );
+
+gckSHM_POOL
+drv_shm_acquire_pool2(
+ IN gctPOINTER Logical
+ );
+
+gceSTATUS
+drv_shm_remove_pool(
+ IN gctHANDLE Handle
+ );
+
+gctUINT32
+drv_shmpool_get_BaseAddress(
+ IN gckSHM_POOL ShmPool
+ );
+
+gctUINT32
+drv_shmpool_get_page_size(
+ IN gckSHM_POOL ShmPool
+ );
+
+gceSTATUS
+drv_shmpool_mem_offset(
+ IN gctPOINTER Logical,
+ OUT gctUINT32 * Address);
+
+gctPOINTER
+drv_shmpool_alloc_contiguous(
+ IN gctUINT32 Pid,
+ IN gctHANDLE Handle,
+ IN gctUINT32 Bytes
+ );
+
+gctUINT32
+drv_shmpool_free(
+ IN gctPOINTER Logical
+ );
+
+void *
+mmap64_join(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off);
+
+int
+mem_offset64_peer(pid_t pid, const uintptr_t addr, size_t len,
+ off64_t *offset, size_t *contig_len);
+
+int
+munmap_peer(pid_t pid, void *addr, size_t len);
+
+void *
+mmap64_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off);
+
+#endif /* __gc_hal_kernel_os_h_ */
+
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#include "gc_hal_kernel_qnx.h"
+
+#define _GC_OBJ_ZONE gcvZONE_KERNEL
+
+/******************************************************************************\
+******************************* gckKERNEL API Code ******************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckKERNEL_QueryVideoMemory
+**
+** Query the amount of video memory.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** OUTPUT:
+**
+** gcsHAL_INTERFACE * Interface
+** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
+** the memory information.
+*/
+gceSTATUS
+gckKERNEL_QueryVideoMemory(
+ IN gckKERNEL Kernel,
+ OUT gcsHAL_INTERFACE * Interface
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Interface != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Get internal memory size and physical address. */
+ Interface->u.QueryVideoMemory.internalSize = device->internalSize;
+ Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysical;
+
+ /* Get external memory size and physical address. */
+ Interface->u.QueryVideoMemory.externalSize = device->externalSize;
+ Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysical;
+
+ /* Get contiguous memory size and physical address. */
+ Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
+ Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysical;
+
+ /* Success. */
+ gcmkFOOTER_NO();
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_GetVideoMemoryPool
+**
+** Get the gckVIDMEM object belonging to the specified pool.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gcePOOL Pool
+** Pool to query gckVIDMEM object for.
+**
+** OUTPUT:
+**
+** gckVIDMEM * VideoMemory
+** Pointer to a variable that will hold the pointer to the gckVIDMEM
+** object belonging to the requested pool.
+*/
+gceSTATUS
+gckKERNEL_GetVideoMemoryPool(
+ IN gckKERNEL Kernel,
+ IN gcePOOL Pool,
+ OUT gckVIDMEM * VideoMemory
+ )
+{
+ gckGALDEVICE device;
+ gckVIDMEM videoMemory;
+
+ gcmkHEADER_ARG("Kernel=0x%x Pool=0x%x", Kernel, Pool);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Dispatch on pool. */
+ switch (Pool)
+ {
+ case gcvPOOL_LOCAL_INTERNAL:
+ /* Internal memory. */
+ videoMemory = device->internalVidMem;
+ break;
+
+ case gcvPOOL_LOCAL_EXTERNAL:
+ /* External memory. */
+ videoMemory = device->externalVidMem;
+ break;
+
+ case gcvPOOL_SYSTEM:
+ /* System memory. */
+ videoMemory = device->contiguousVidMem;
+ break;
+
+ default:
+ /* Unknown pool. */
+ videoMemory = NULL;
+ }
+
+ /* Return pointer to the gckVIDMEM object. */
+ *VideoMemory = videoMemory;
+
+ /* Return status. */
+ gcmkFOOTER_ARG("*VideoMemory=0x%x", *VideoMemory);
+ return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapMemory
+**
+** Map video memory into the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the base address of the mapped
+** memory region.
+*/
+gceSTATUS
+gckKERNEL_MapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ return gckOS_MapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_UnmapMemory
+**
+** Unmap video memory from the current process space.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctPHYS_ADDR Physical
+** Physical address of video memory to map.
+**
+** gctSIZE_T Bytes
+** Number of bytes to map.
+**
+** gctPOINTER Logical
+** Base address of the mapped memory region.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapMemory(
+ IN gckKERNEL Kernel,
+ IN gctPHYS_ADDR Physical,
+ IN gctSIZE_T Bytes,
+ IN gctPOINTER Logical
+ )
+{
+ return gckOS_UnmapMemory(Kernel->os, Physical, Bytes, Logical);
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_MapVideoMemory
+**
+** Map video memory for the current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctBOOL InUserSpace
+** gcvTRUE to map the memory into the user space.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** gctUINT32 Pid
+** Process ID of the current process.
+**
+** gctUINT32 Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** gctPOINTER * Logical
+** Pointer to a variable that will hold the logical address of the
+** specified memory address.
+*/
+gceSTATUS
+gckKERNEL_MapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctBOOL InUserSpace,
+ IN gctUINT32 Address,
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes,
+ OUT gctPOINTER * Logical
+ )
+{
+ off64_t offset = (off64_t)Address - (off64_t)drv_mempool_get_basePAddress();
+
+ gcmkHEADER_ARG("Kernel=0x%x InUserSpace=%d Address=%08x",
+ Kernel, InUserSpace, Address);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ *Logical = (gctPOINTER)mmap64_peer(Pid, gcvNULL, Bytes,
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOINIT,
+ drv_mempool_get_fileDescriptor(), offset);
+ if (*Logical == MAP_FAILED) {
+ *Logical = NULL;
+ return gcvSTATUS_INVALID_ADDRESS;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_UnmapVideoMemory
+**
+** Unmap video memory for the current process.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gctUINT32 Address
+** Hardware specific memory address.
+**
+** gctUINT32 Pid
+** Process ID of the current process.
+**
+** gctUINT32 Bytes
+** Number of bytes to map.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_UnmapVideoMemory(
+ IN gckKERNEL Kernel,
+ IN gctPOINTER Logical,
+ IN gctUINT32 Pid,
+ IN gctUINT32 Bytes
+ )
+{
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ if (munmap_peer(Pid, Logical, Bytes) == -1)
+ {
+ return gcvSTATUS_INVALID_ADDRESS;
+ }
+
+ /* Success. */
+ return gcvSTATUS_OK;
+}
+
+/*******************************************************************************
+**
+** gckKERNEL_Notify
+**
+** This function is called by clients to notify the gckKERNEL object of an event.
+**
+** INPUT:
+**
+** gckKERNEL Kernel
+** Pointer to an gckKERNEL object.
+**
+** gceNOTIFY Notification
+** Notification event.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+gceSTATUS
+gckKERNEL_Notify(
+ IN gckKERNEL Kernel,
+ IN gceNOTIFY Notification,
+ IN gctBOOL Data
+ )
+{
+ gceSTATUS status;
+
+ gcmkHEADER_ARG("Kernel=0x%x Notification=%d Data=%d",
+ Kernel, Notification, Data);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+
+ /* Dispatch on notifcation. */
+ switch (Notification)
+ {
+ case gcvNOTIFY_INTERRUPT:
+ /* Process the interrupt. */
+#if COMMAND_PROCESSOR_VERSION > 1
+ status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
+#else
+ status = gckHARDWARE_Interrupt(Kernel->hardware, Data);
+#endif
+ break;
+
+ default:
+ status = gcvSTATUS_OK;
+ break;
+ }
+
+ /* Success. */
+ gcmkFOOTER();
+ return status;
+}
+
+gceSTATUS
+gckKERNEL_QuerySettings(
+ IN gckKERNEL Kernel,
+ OUT gcsKERNEL_SETTINGS * Settings
+ )
+{
+ gckGALDEVICE device;
+
+ gcmkHEADER_ARG("Kernel=0x%x", Kernel);
+
+ /* Verify the arguments. */
+ gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
+ gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
+
+ /* Extract the pointer to the gckGALDEVICE class. */
+ device = (gckGALDEVICE) Kernel->context;
+
+ /* Fill in signal. */
+ Settings->signal = -1;
+
+ /* Success. */
+ gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
+ return gcvSTATUS_OK;
+}
+
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+*
+* The material in this file is confidential and contains trade secrets
+* of Vivante Corporation. This is proprietary information owned by
+* Vivante Corporation. No part of this work may be disclosed,
+* reproduced, copied, transmitted, or used in any way for any purpose,
+* without the express written permission of Vivante Corporation.
+*
+*****************************************************************************
+*
+* Auto-generated file on 10/12/2010. Do not edit!!!
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_kernel_qnx_h_
+#define __gc_hal_kernel_qnx_h_
+
+#define _QNX_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/iofunc.h>
+#include <sys/dispatch.h>
+#include <sys/procmgr.h>
+#include <sys/memmsg.h>
+#include <fcntl.h>
+#include <sys/syspage.h>
+#include <hw/inout.h>
+#include <atomic.h>
+
+#define NTSTRSAFE_NO_CCH_FUNCTIONS
+#include "gc_hal.h"
+#include "gc_hal_driver.h"
+#include "gc_hal_kernel.h"
+#include "gc_hal_kernel_device.h"
+#include "gc_hal_kernel_os.h"
+#include "../inc/gc_hal_common_qnx.h"
+
+#define _WIDE(string) L##string
+#define WIDE(string) _WIDE(string)
+
+#define countof(a) (sizeof(a) / sizeof(a[0]))
+
+#ifndef GAL_DEV
+#define GAL_DEV "/dev/galcore"
+#endif
+
+#endif /* __gc_hal_kernel_qnx_h_ */
+
--- /dev/null
+##############################################################################
+#
+# Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+#
+# The material in this file is confidential and contains trade secrets
+# of Vivante Corporation. This is proprietary information owned by
+# Vivante Corporation. No part of this work may be disclosed,
+# reproduced, copied, transmitted, or used in any way for any purpose,
+# without the express written permission of Vivante Corporation.
+#
+##############################################################################
+#
+# Auto-generated file on 10/12/2010. Do not edit!!!
+#
+##############################################################################
+
+
+#
+# Qnx build file for kernel HAL layer.
+#
+
+################################################################################
+# Include common definitions.
+
+include $(AQROOT)/makefile.linux.def
+
+################################################################################
+# Define a shortcut for the main target.
+
+#ifeq ($(STATIC_LINK),1)
+ STATIC = 1
+#else
+ DYNAMIC = 1
+#endif
+PROGRAM := 1
+
+#ifeq ($(STATIC), 1)
+ TARGET_NAME = galcore.a
+#else
+ TARGET_NAME = galcore
+#endif
+
+################################################################################
+# Installation directory
+INSTALL_DIR := $(SDK_DIR)/drivers
+
+################################################################################
+# Supply additional include directories.
+
+INCLUDE += -I$(AQROOT)/hal/inc
+INCLUDE += -I$(AQROOT)/hal/user
+INCLUDE += -I$(AQROOT)/hal/kernel
+INCLUDE += -I$(AQARCH)/hal/kernel
+INCLUDE += -I$(AQARCH)/hal/kernel
+CFLAGS += $(INCLUDE)
+CFLAGS += -fPIC
+
+################################################################################
+# Supply necessary libraries.
+
+# Specify Vivante library paths.
+LIBS += -L $(AQARCH)/hal/kernel/$(OBJ_DIR)
+LIBS += -L $(AQROOT)/hal/kernel/$(OBJ_DIR)
+LIBS += -l halarchkernel -l halkernel
+
+################################################################################
+# Describe object files.
+
+OBJECTS = \
+ $(OBJ_DIR)/gc_hal_kernel_driver.o \
+ $(OBJ_DIR)/gc_hal_kernel_os.o \
+ $(OBJ_DIR)/gc_hal_kernel_qnx.o \
+ $(OBJ_DIR)/gc_hal_kernel_device.o \
+ $(OBJ_DIR)/gc_hal_kernel_debug.o \
+
+include $(AQROOT)/common.target
+
+
--- /dev/null
+##############################################################################
+#
+# Copyright (c) 2005 - 2010 by Vivante Corp. All rights reserved.
+#
+# The material in this file is confidential and contains trade secrets
+# of Vivante Corporation. This is proprietary information owned by
+# Vivante Corporation. No part of this work may be disclosed,
+# reproduced, copied, transmitted, or used in any way for any purpose,
+# without the express written permission of Vivante Corporation.
+#
+##############################################################################
+#
+# Auto-generated file on 10/12/2010. Do not edit!!!
+#
+##############################################################################
+
+
+#
+# QNX build file for the kernel level HAL libraries.
+#
+
+################################################################################
+# Define make command.
+MAKE = make --makefile=makefile.linux
+
+
+################################################################################
+# Define build directories.
+
+HAL_KERNEL_DRV_ARCH := $(AQARCH)/hal/kernel
+HAL_KERNEL_DRV_OS := $(AQROOT)/hal/os/qnx/kernel
+HAL_KERNEL_DRV_MAIN := $(AQROOT)/hal/kernel
+
+$(HAL_KERNEL_DRV_OS): $(HAL_KERNEL_DRV_ARCH) $(HAL_KERNEL_DRV_MAIN)
+
+MODULES := $(HAL_KERNEL_DRV_ARCH) $(HAL_KERNEL_DRV_OS) $(HAL_KERNEL_DRV_MAIN)
+MAIN_MODULE = $(HAL_KERNEL_DRV_OS)
+
+include $(AQROOT)/common.node
+
--- /dev/null
+/****************************************************************************
+*
+* Copyright (C) 2005 - 2010 by Vivante Corp.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the license, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+
+
+
+#ifndef __gc_hal_user_context_h_
+#define __gc_hal_user_context_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* gcoCONTEXT structure that hold the current context. */
+struct _gcoCONTEXT
+{
+ /* Object. */
+ gcsOBJECT object;
+
+ /* Pointer to gcoOS object. */
+ gcoOS os;
+
+ /* Pointer to gcoHARDWARE object. */
+ gcoHARDWARE hardware;
+
+ /* Context ID. */
+ gctUINT64 id;
+
+ /* State mapping. */
+ gctUINT32_PTR map;
+ gctSIZE_T stateCount;
+
+ /* State hinting. */
+ gctUINT8_PTR hint;
+ gctUINT8 hintValue;
+ gctSIZE_T hintCount;
+
+ /* Context buffer. */
+ gctUINT32_PTR buffer;
+ gctUINT32 pipe3DIndex;
+ gctUINT32 pipe2DIndex;
+ gctUINT32 linkIndex;
+ gctUINT32 inUseIndex;
+ gctSIZE_T bufferSize;
+
+ /* Context buffer used for commitment. */
+ gctSIZE_T bytes;
+ gctPHYS_ADDR physical;
+ gctPOINTER logical;
+
+ /* Pointer to final LINK command. */
+ gctPOINTER link;
+
+ /* Requested pipe select for context. */
+ gctUINT32 initialPipe;
+ gctUINT32 entryPipe;
+ gctUINT32 currentPipe;
+
+ /* Flag to specify whether PostCommit needs to be called. */
+ gctBOOL postCommit;
+
+ /* Busy flag. */
+ volatile gctBOOL * inUse;
+
+ /* Variables used for building state buffer. */
+ gctUINT32 lastAddress;
+ gctSIZE_T lastSize;
+ gctUINT32 lastIndex;
+ gctBOOL lastFixed;
+
+ /* Hint array. */
+ gctUINT32_PTR hintArray;
+ gctUINT32_PTR hintIndex;
+};
+
+struct _gcoCMDBUF
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gcoOS object. */
+ gcoOS os;
+
+ /* Pointer to gcoHARDWARE object. */
+ gcoHARDWARE hardware;
+
+ /* Physical address of command buffer. */
+ gctPHYS_ADDR physical;
+
+ /* Logical address of command buffer. */
+ gctPOINTER logical;
+
+ /* Number of bytes in command buffer. */
+ gctSIZE_T bytes;
+
+ /* Start offset into the command buffer. */
+ gctUINT32 startOffset;
+
+ /* Current offset into the command buffer. */
+ gctUINT32 offset;
+
+ /* Number of free bytes in command buffer. */
+ gctSIZE_T free;
+
+#if gcdSECURE_USER
+ /* Table of offsets that define the physical addresses to be mapped. */
+ gctUINT32_PTR hintTable;
+
+ /* Current index into map table. */
+ gctUINT32_PTR hintIndex;
+
+ /* Commit index for map table. */
+ gctUINT32_PTR hintCommit;
+#endif
+};
+
+typedef struct _gcsQUEUE * gcsQUEUE_PTR;
+
+typedef struct _gcsQUEUE
+{
+ /* Pointer to next gcsQUEUE structure. */
+ gcsQUEUE_PTR next;
+
+#ifdef __QNXNTO__
+ /* Size of this object. */
+ gctSIZE_T bytes;
+#endif
+
+ /* Event information. */
+ gcsHAL_INTERFACE iface;
+}
+gcsQUEUE;
+
+/* Event queue. */
+struct _gcoQUEUE
+{
+ /* The object. */
+ gcsOBJECT object;
+
+ /* Pointer to gcoOS object. */
+ gcoOS os;
+
+ /* Pointer to current event queue. */
+ gcsQUEUE_PTR head;
+ gcsQUEUE_PTR tail;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __gc_hal_user_context_h_ */
+