summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSE53
-rw-r--r--Readme.md6
-rwxr-xr-xsrc/Kbuild285
-rwxr-xr-xsrc/config.j670
-rwxr-xr-xsrc/hal/kernel/arch/gc_hal_kernel_context.c1108
-rwxr-xr-xsrc/hal/kernel/arch/gc_hal_kernel_context.h247
-rwxr-xr-xsrc/hal/kernel/arch/gc_hal_kernel_hardware.c7894
-rwxr-xr-xsrc/hal/kernel/arch/gc_hal_kernel_hardware.h210
-rwxr-xr-xsrc/hal/kernel/arch/gc_hal_kernel_recorder.c713
-rwxr-xr-xsrc/hal/kernel/arch/makefile57
-rwxr-xr-xsrc/hal/kernel/arch/makefile.linux88
-rwxr-xr-xsrc/hal/kernel/arch/sources71
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel.c5008
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel.h1485
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_command.c3366
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_db.c1884
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_debug.c2821
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_event.c3145
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_heap.c892
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_mmu.c2315
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_power.c381
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_precomp.h63
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_security.c62
-rwxr-xr-xsrc/hal/kernel/gc_hal_kernel_video_memory.c2761
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal.h2767
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_base.h5347
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_driver.h1203
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_dump.h123
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_eglplatform.h676
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_enum.h1650
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_kernel_buffer.h259
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_mem.h62
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_options.h1329
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_profiler.h619
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_raster.h1078
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_rename.h277
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_security_interface.h171
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_types.h976
-rwxr-xr-xsrc/hal/kernel/inc/gc_hal_version.h69
-rwxr-xr-xsrc/hal/kernel/makefile.linux97
-rwxr-xr-xsrc/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h84
-rwxr-xr-xsrc/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c353
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_allocator.c972
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_allocator.h470
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_debug.h147
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_debugfs.c1181
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_debugfs.h169
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_device.c2337
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_device.h264
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_iommu.c250
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_linux.c508
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_linux.h437
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_math.c66
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_mutex.h89
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_os.c8225
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_os.h124
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_platform.h342
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_probe.c1361
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_security_channel.c423
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_sync.c211
-rwxr-xr-xsrc/hal/os/linux/kernel/gc_hal_kernel_sync.h106
-rwxr-xr-xsrc/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c81
-rwxr-xr-xsrc/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_j6.c253
-rwxr-xr-xsrc/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_ti.c188
64 files changed, 70328 insertions, 1 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3be69f6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,53 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
diff --git a/Readme.md b/Readme.md
index 2ba0689..fd27902 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1 +1,5 @@
1master is an empty branch, checkout a relevant topic branch. 1
2# ti-gc320-driver
3
4This project hosts the kernel driver for GC320 IP available in Texas
5Instruments DRA7x based SoCs.
diff --git a/src/Kbuild b/src/Kbuild
new file mode 100755
index 0000000..f952b62
--- /dev/null
+++ b/src/Kbuild
@@ -0,0 +1,285 @@
1##############################################################################
2#
3# The MIT License (MIT)
4#
5# Copyright (c) 2014 Vivante Corporation
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25##############################################################################
26#
27# The GPL License (GPL)
28#
29# Copyright (C) 2014 Vivante Corporation
30#
31# This program is free software; you can redistribute it and/or
32# modify it under the terms of the GNU General Public License
33# as published by the Free Software Foundation; either version 2
34# of the License, or (at your option) any later version.
35#
36# This program is distributed in the hope that it will be useful,
37# but WITHOUT ANY WARRANTY; without even the implied warranty of
38# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39# GNU General Public License for more details.
40#
41# You should have received a copy of the GNU General Public License
42# along with this program; if not, write to the Free Software Foundation,
43# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44#
45##############################################################################
46#
47# Note: This software is released under dual MIT and GPL licenses. A
48# recipient may use this file under the terms of either the MIT license or
49# GPL License. If you wish to use only one license not the other, you can
50# indicate your decision by deleting one of the above license notices in your
51# version of this file.
52#
53##############################################################################
54
55
56#
57# Linux build file for kernel HAL driver.
58#
59
60include $(AQROOT)/config.j6
61
62KERNEL_DIR ?= $(TOOL_DIR)/kernel
63
64OS_KERNEL_DIR := hal/os/linux/kernel
65ARCH_KERNEL_DIR := hal/kernel/arch
66ARCH_VG_KERNEL_DIR := hal/kernel/archvg
67HAL_KERNEL_DIR := hal/kernel
68HOST := $(shell hostname)
69
70# Check and include platform config.
71ifneq ($(PLATFORM),)
72
73# Get platform config path.
74PLATFORM_CONFIG ?= $(AQROOT)/$(OS_KERNEL_DIR)/platform/$(PLATFORM).config
75
76# Check whether it exists.
77PLATFORM_CONFIG := $(wildcard $(PLATFORM_CONFIG))
78
79# Include it if exists.
80ifneq ($(PLATFORM_CONFIG),)
81include $(PLATFORM_CONFIG)
82endif
83
84endif
85
86MODULE_NAME ?= galcore
87CUSTOMER_ALLOCATOR_OBJS ?=
88ALLOCATOR_ARRAY_H_LOCATION ?= $(OS_KERNEL_DIR)/allocator/default/
89
90EXTRA_CFLAGS += -Werror
91
92OBJS := $(OS_KERNEL_DIR)/gc_hal_kernel_device.o \
93 $(OS_KERNEL_DIR)/gc_hal_kernel_linux.o \
94 $(OS_KERNEL_DIR)/gc_hal_kernel_math.o \
95 $(OS_KERNEL_DIR)/gc_hal_kernel_os.o \
96 $(OS_KERNEL_DIR)/gc_hal_kernel_debugfs.o \
97 $(OS_KERNEL_DIR)/gc_hal_kernel_allocator.o \
98
99ifneq ($(CONFIG_DMA_SHARED_BUFFER),)
100OBJS += $(OS_KERNEL_DIR)/allocator/default/gc_hal_kernel_allocator_dmabuf.o
101endif
102
103ifneq ($(CONFIG_IOMMU_SUPPORT),)
104OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_iommu.o
105endif
106
107ifneq ($(PLATFORM),)
108OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_probe.o
109OBJS += $(OS_KERNEL_DIR)/platform/$(PLATFORM).o
110else
111OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_driver.o
112endif
113
114OBJS += $(HAL_KERNEL_DIR)/gc_hal_kernel.o \
115 $(HAL_KERNEL_DIR)/gc_hal_kernel_command.o \
116 $(HAL_KERNEL_DIR)/gc_hal_kernel_db.o \
117 $(HAL_KERNEL_DIR)/gc_hal_kernel_debug.o \
118 $(HAL_KERNEL_DIR)/gc_hal_kernel_event.o \
119 $(HAL_KERNEL_DIR)/gc_hal_kernel_heap.o \
120 $(HAL_KERNEL_DIR)/gc_hal_kernel_mmu.o \
121 $(HAL_KERNEL_DIR)/gc_hal_kernel_video_memory.o \
122 $(HAL_KERNEL_DIR)/gc_hal_kernel_power.o
123
124OBJS += $(ARCH_KERNEL_DIR)/gc_hal_kernel_context.o \
125 $(ARCH_KERNEL_DIR)/gc_hal_kernel_hardware.o
126
127
128
129ifneq ($(CONFIG_SYNC),)
130EXTRA_CFLAGS += -Idrivers/staging/android
131
132OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_sync.o
133endif
134
135ifeq ($(SECURITY), 1)
136OBJS += $(OS_KERNEL_DIR)/gc_hal_kernel_security_channel.o \
137 $(HAL_KERNEL_DIR)/gc_hal_kernel_security.o
138endif
139
140ifneq ($(CUSTOMER_ALLOCATOR_OBJS),)
141OBJS += $(CUSTOMER_ALLOCATOR_OBJS)
142endif
143
144ifeq ($(KERNELRELEASE), )
145
146.PHONY: all clean install
147
148# Define targets.
149all:
150 @$(MAKE) V=$(V) ARCH=$(ARCH_TYPE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
151
152clean:
153 @rm -rf $(OBJS)
154 @rm -rf modules.order Module.symvers .tmp_versions
155 @find $(AQROOT) -name ".gc_*.cmd" | xargs rm -f
156
157install: all
158 @mkdir -p $(SDK_DIR)/drivers
159 @cp $(MODULE_NAME).ko $(SDK_DIR)/drivers
160
161else
162
163
164EXTRA_CFLAGS += -DLINUX -DDRIVER
165
166ifeq ($(FLAREON),1)
167EXTRA_CFLAGS += -DFLAREON
168endif
169
170ifeq ($(DEBUG), 1)
171EXTRA_CFLAGS += -DDBG=1 -DDEBUG -D_DEBUG
172else
173EXTRA_CFLAGS += -DDBG=0
174endif
175
176ifeq ($(NO_DMA_COHERENT), 1)
177EXTRA_CFLAGS += -DNO_DMA_COHERENT
178endif
179
180ifeq ($(CONFIG_DOVE_GPU), 1)
181EXTRA_CFLAGS += -DCONFIG_DOVE_GPU=1
182endif
183
184ifneq ($(USE_PLATFORM_DRIVER), 0)
185EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=1
186else
187EXTRA_CFLAGS += -DUSE_PLATFORM_DRIVER=0
188endif
189
190EXTRA_CFLAGS += -DVIVANTE_PROFILER=1
191EXTRA_CFLAGS += -DVIVANTE_PROFILER_CONTEXT=1
192
193ifeq ($(ENABLE_GPU_CLOCK_BY_DRIVER), 1)
194EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=1
195else
196EXTRA_CFLAGS += -DENABLE_GPU_CLOCK_BY_DRIVER=0
197endif
198
199ifeq ($(USE_NEW_LINUX_SIGNAL), 1)
200EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=1
201else
202EXTRA_CFLAGS += -DUSE_NEW_LINUX_SIGNAL=0
203endif
204
205ifeq ($(FORCE_ALL_VIDEO_MEMORY_CACHED), 1)
206EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=1
207else
208EXTRA_CFLAGS += -DgcdPAGED_MEMORY_CACHEABLE=0
209endif
210
211ifeq ($(NONPAGED_MEMORY_CACHEABLE), 1)
212EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=1
213else
214EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_CACHEABLE=0
215endif
216
217ifeq ($(NONPAGED_MEMORY_BUFFERABLE), 1)
218EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=1
219else
220EXTRA_CFLAGS += -DgcdNONPAGED_MEMORY_BUFFERABLE=0
221endif
222
223ifeq ($(CACHE_FUNCTION_UNIMPLEMENTED), 1)
224EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=1
225else
226EXTRA_CFLAGS += -DgcdCACHE_FUNCTION_UNIMPLEMENTED=0
227endif
228
229ifeq ($(CONFIG_SMP), y)
230EXTRA_CFLAGS += -DgcdSMP=1
231else
232EXTRA_CFLAGS += -DgcdSMP=0
233endif
234
235EXTRA_CFLAGS += -DgcdENABLE_3D=0
236
237EXTRA_CFLAGS += -DgcdENABLE_2D=1
238
239EXTRA_CFLAGS += -DgcdENABLE_VG=0
240
241ifeq ($(ENABLE_OUTER_CACHE_PATCH), 1)
242EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=1
243else
244EXTRA_CFLAGS += -DgcdENABLE_OUTER_CACHE_PATCH=0
245endif
246
247ifeq ($(USE_BANK_ALIGNMENT), 1)
248 EXTRA_CFLAGS += -DgcdENABLE_BANK_ALIGNMENT=1
249 ifneq ($(BANK_BIT_START), 0)
250 ifneq ($(BANK_BIT_END), 0)
251 EXTRA_CFLAGS += -DgcdBANK_BIT_START=$(BANK_BIT_START)
252 EXTRA_CFLAGS += -DgcdBANK_BIT_END=$(BANK_BIT_END)
253 endif
254 endif
255
256 ifneq ($(BANK_CHANNEL_BIT), 0)
257 EXTRA_CFLAGS += -DgcdBANK_CHANNEL_BIT=$(BANK_CHANNEL_BIT)
258 endif
259endif
260
261ifeq ($(gcdFPGA_BUILD), 1)
262EXTRA_CFLAGS += -DgcdFPGA_BUILD=1
263else
264EXTRA_CFLAGS += -DgcdFPGA_BUILD=0
265endif
266
267ifeq ($(SECURITY), 1)
268EXTRA_CFLAGS += -DgcdSECURITY=1
269endif
270
271EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
272EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel
273EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/arch
274EXTRA_CFLAGS += -I$(AQROOT)/hal/kernel/inc
275EXTRA_CFLAGS += -I$(AQROOT)/hal/os/linux/kernel
276EXTRA_CFLAGS += -I$(AQROOT)/$(ALLOCATOR_ARRAY_H_LOCATION)
277
278
279EXTRA_CFLAGS += -DHOST=\"$(HOST)\"
280
281obj-m = $(MODULE_NAME).o
282
283$(MODULE_NAME)-objs = $(OBJS)
284
285endif
diff --git a/src/config.j6 b/src/config.j6
new file mode 100755
index 0000000..0ff6b09
--- /dev/null
+++ b/src/config.j6
@@ -0,0 +1,70 @@
1##############################################################################
2#
3# The MIT License (MIT)
4#
5# Copyright (c) 2014 Vivante Corporation
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25##############################################################################
26#
27# The GPL License (GPL)
28#
29# Copyright (C) 2014 Vivante Corporation
30#
31# This program is free software; you can redistribute it and/or
32# modify it under the terms of the GNU General Public License
33# as published by the Free Software Foundation; either version 2
34# of the License, or (at your option) any later version.
35#
36# This program is distributed in the hope that it will be useful,
37# but WITHOUT ANY WARRANTY; without even the implied warranty of
38# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39# GNU General Public License for more details.
40#
41# You should have received a copy of the GNU General Public License
42# along with this program; if not, write to the Free Software Foundation,
43# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44#
45##############################################################################
46#
47# Note: This software is released under dual MIT and GPL licenses. A
48# recipient may use this file under the terms of either the MIT license or
49# GPL License. If you wish to use only one license not the other, you can
50# indicate your decision by deleting one of the above license notices in your
51# version of this file.
52#
53##############################################################################
54
55
56ARCH_TYPE ?= arm
57SDK_DIR ?= $(AQROOT)/build/sdk
58VIVANTE_ENABLE_3D ?=0
59VIVANTE_ENABLE_2D ?=1
60VIVANTE_ENABLE_VG ?=0
61FORCE_ALL_VIDEO_MEMORY_CACHED ?= 0
62NONPAGED_MEMORY_CACHEABLE ?= 0
63NONPAGED_MEMORY_BUFFERABLE ?= 1
64CACHE_FUNCTION_UNIMPLEMENTED ?= 0
65ENABLE_OUTER_CACHE_PATCH ?= 1
66USE_BANK_ALIGNMENT ?= 0
67BANK_BIT_START ?= 0
68BANK_BIT_END ?= 0
69BANK_CHANNEL_BIT ?= 0
70PLATFORM ?= ti/gc_hal_kernel_platform_j6
diff --git a/src/hal/kernel/arch/gc_hal_kernel_context.c b/src/hal/kernel/arch/gc_hal_kernel_context.c
new file mode 100755
index 0000000..91e4c6b
--- /dev/null
+++ b/src/hal/kernel/arch/gc_hal_kernel_context.c
@@ -0,0 +1,1108 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal.h"
57#include "gc_hal_kernel.h"
58#include "gc_hal_kernel_context.h"
59#include "gc_hal_kernel_buffer.h"
60
61/******************************************************************************\
62******************************** Debugging Macro *******************************
63\******************************************************************************/
64
65/* Zone used for header/footer. */
66#define _GC_OBJ_ZONE gcvZONE_HARDWARE
67
68
69/******************************************************************************\
70************************** Context State Buffer Helpers ************************
71\******************************************************************************/
72
73#define _STATE(reg) \
74 _State(\
75 Context, index, \
76 reg ## _Address >> 2, \
77 reg ## _ResetValue, \
78 reg ## _Count, \
79 gcvFALSE, gcvFALSE \
80 )
81
82#define _STATE_COUNT(reg, count) \
83 _State(\
84 Context, index, \
85 reg ## _Address >> 2, \
86 reg ## _ResetValue, \
87 count, \
88 gcvFALSE, gcvFALSE \
89 )
90
91#define _STATE_COUNT_OFFSET(reg, offset, count) \
92 _State(\
93 Context, index, \
94 (reg ## _Address >> 2) + offset, \
95 reg ## _ResetValue, \
96 count, \
97 gcvFALSE, gcvFALSE \
98 )
99
100#define _STATE_MIRROR_COUNT(reg, mirror, count) \
101 _StateMirror(\
102 Context, \
103 reg ## _Address >> 2, \
104 count, \
105 mirror ## _Address >> 2 \
106 )
107
108#define _STATE_HINT(reg) \
109 _State(\
110 Context, index, \
111 reg ## _Address >> 2, \
112 reg ## _ResetValue, \
113 reg ## _Count, \
114 gcvFALSE, gcvTRUE \
115 )
116
117#define _STATE_HINT_BLOCK(reg, block, count) \
118 _State(\
119 Context, index, \
120 (reg ## _Address >> 2) + (block << reg ## _BLK), \
121 reg ## _ResetValue, \
122 count, \
123 gcvFALSE, gcvTRUE \
124 )
125
126#define _STATE_COUNT_OFFSET_HINT(reg, offset, count) \
127 _State(\
128 Context, index, \
129 (reg ## _Address >> 2) + offset, \
130 reg ## _ResetValue, \
131 count, \
132 gcvFALSE, gcvTRUE \
133 )
134
135#define _STATE_X(reg) \
136 _State(\
137 Context, index, \
138 reg ## _Address >> 2, \
139 reg ## _ResetValue, \
140 reg ## _Count, \
141 gcvTRUE, gcvFALSE \
142 )
143
144#define _STATE_INIT_VALUE(reg, value) \
145 _State(\
146 Context, index, \
147 reg ## _Address >> 2, \
148 value, \
149 reg ## _Count, \
150 gcvFALSE, gcvFALSE \
151 )
152
153#define _CLOSE_RANGE() \
154 _TerminateStateBlock(Context, index)
155
156#define _ENABLE(reg, field) \
157 do \
158 { \
159 if (gcmVERIFYFIELDVALUE(data, reg, MASK_ ## field, ENABLED)) \
160 { \
161 enable |= gcmFIELDMASK(reg, field); \
162 } \
163 } \
164 while (gcvFALSE)
165
166#define _BLOCK_COUNT(reg) \
167 ((reg ## _Count) >> (reg ## _BLK))
168
169
170/******************************************************************************\
171*********************** Support Functions and Definitions **********************
172\******************************************************************************/
173
174#define gcdSTATE_MASK \
175 (gcmSETFIELDVALUE(0, AQ_COMMAND_NOP_COMMAND, OPCODE, NOP) | 0xC0FFEE)
176
177
178
179static gctUINT32
180_FlushPipe(
181 IN gckCONTEXT Context,
182 IN gctUINT32 Index,
183 IN gcePIPE_SELECT Pipe
184 )
185{
186 gctUINT32 flushSlots;
187 gctBOOL txCacheFix;
188 gctBOOL fcFlushStall;
189 gctBOOL iCacheInvalidate;
190
191 txCacheFix
192 = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX);
193
194 fcFlushStall
195 = gckHARDWARE_IsFeatureAvailable(Context->hardware, gcvFEATURE_FC_FLUSH_STALL);
196
197 iCacheInvalidate
198 = ((((gctUINT32) (Context->hardware->identity.chipMinorFeatures3)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
199
200 flushSlots = 6;
201
202 if (Pipe == gcvPIPE_3D)
203 {
204 if (!txCacheFix)
205 {
206 /* Semaphore stall */
207 flushSlots += 4;
208 }
209
210 /* VST cache */
211 flushSlots += 2;
212 }
213
214 if (fcFlushStall)
215 {
216 /* Flush tile status cache. */
217 flushSlots += 6;
218 }
219
220 if (iCacheInvalidate)
221 {
222 flushSlots += 12;
223 }
224
225 if (Context->buffer != gcvNULL)
226 {
227 gctUINT32_PTR buffer;
228
229 /* Address correct index. */
230 buffer = Context->buffer->logical + Index;
231
232 if (Pipe == gcvPIPE_3D && !txCacheFix)
233 {
234 /* Semaphore from FE to PE. */
235 *buffer++
236 = ((((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)))
237 | ((((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)))
238 | ((((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)));
239
240 *buffer++
241 = ((((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)))
242 | ((((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)));
243
244 /* Stall from FE to PE. */
245 *buffer++
246 = ((((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)));
247
248 *buffer++
249 = ((((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)))
250 | ((((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)));
251 }
252
253 /* Flush the current pipe. */
254 *buffer++
255 = ((((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)))
256 | ((((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)))
257 | ((((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)));
258
259 *buffer++
260 = (Pipe == gcvPIPE_2D)
261 ? ((((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)))
262 : ((((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)))
263 | ((((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)))
264 | ((((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)))
265 | ((((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)));
266
267 /* Flush VST in separate cmd. */
268 if (Pipe == gcvPIPE_3D)
269 {
270 *buffer++
271 = ((((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)))
272 | ((((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)))
273 | ((((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)));
274
275 *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
276 }
277
278 /* Semaphore from FE to PE. */
279 *buffer++
280 = ((((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)))
281 | ((((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)))
282 | ((((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)));
283
284 *buffer++
285 = ((((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)))
286 | ((((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)));
287
288 /* Stall from FE to PE. */
289 *buffer++
290 = ((((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)));
291
292 *buffer++
293 = ((((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)))
294 | ((((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)));
295
296 if (fcFlushStall)
297 {
298 *buffer++
299 = ((((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)))
300 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
301 | ((((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)));
302
303 *buffer++
304 = ((((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)));
305
306 /* Semaphore from FE to PE. */
307 *buffer++
308 = ((((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)))
309 | ((((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)))
310 | ((((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)));
311
312 *buffer++
313 = ((((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)))
314 | ((((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)));
315
316 /* Stall from FE to PE. */
317 *buffer++
318 = ((((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)));
319
320 *buffer++
321 = ((((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)))
322 | ((((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)));
323 }
324
325 if (iCacheInvalidate)
326 {
327 /* Invalidate I$ after pipe is stalled */
328 *buffer++
329 = ((((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)))
330 | ((((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)))
331 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0218) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
332
333 *buffer++
334 = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
335
336 *buffer++
337 = ((((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)))
338 | ((((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)))
339 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x021A) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
340
341 *buffer++
342 = ((((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)))
343 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
344
345 *buffer++
346 = ((((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)))
347 | ((((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)))
348 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0218) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
349
350 *buffer++
351 = ((((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)));
352
353 *buffer++
354 = ((((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)))
355 | ((((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)))
356 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x021A) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
357
358 *buffer++
359 = ((((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)))
360 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
361
362 /* Semaphore from FE to PE. */
363 *buffer++
364 = ((((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)))
365 | ((((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)))
366 | ((((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)));
367
368 *buffer++
369 = ((((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)))
370 | ((((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)));
371
372 /* Stall from FE to PE. */
373 *buffer++
374 = ((((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)));
375
376 *buffer++
377 = ((((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)))
378 | ((((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)));
379 }
380 }
381
382 /* Number of slots taken by flushing pipe. */
383 return flushSlots;
384}
385
386
387static gctUINT32
388_SwitchPipe(
389 IN gckCONTEXT Context,
390 IN gctUINT32 Index,
391 IN gcePIPE_SELECT Pipe
392 )
393{
394 gctUINT32 slots = 6;
395
396 if (Context->buffer != gcvNULL)
397 {
398 gctUINT32_PTR buffer;
399
400 /* Address correct index. */
401 buffer = Context->buffer->logical + Index;
402
403 /* LoadState(AQPipeSelect, 1), pipe. */
404 *buffer++
405 = ((((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)))
406 | ((((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)))
407 | ((((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)));
408
409 *buffer++
410 = (Pipe == gcvPIPE_2D)
411 ? 0x1
412 : 0x0;
413
414 /* Semaphore from FE to PE. */
415 *buffer++
416 = ((((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)))
417 | ((((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)))
418 | ((((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)));
419
420 *buffer++
421 = ((((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)))
422 | ((((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)));
423
424 /* Stall from FE to PE. */
425 *buffer++
426 = ((((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)));
427
428 *buffer++
429 = ((((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)))
430 | ((((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)));
431 }
432
433 Context->pipeSelectBytes = slots * gcmSIZEOF(gctUINT32);
434
435 return slots;
436}
437
438
439static gceSTATUS
440_InitializeContextBuffer(
441 IN gckCONTEXT Context
442 )
443{
444 gctUINT32_PTR buffer;
445 gctUINT32 index;
446
447
448 /* Reset the buffer index. */
449 index = 0;
450
451 /* Reset the last state address. */
452 Context->lastAddress = ~0U;
453
454 /* Get the buffer pointer. */
455 buffer = (Context->buffer == gcvNULL)
456 ? gcvNULL
457 : Context->buffer->logical;
458
459
460 /**************************************************************************/
461 /* Build 2D states. *******************************************************/
462
463
464
465 /**************************************************************************/
466 /* Link to another address. ***********************************************/
467
468 Context->linkIndex3D = (gctUINT)index;
469
470 if (buffer != gcvNULL)
471 {
472 buffer[index + 0]
473 = ((((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)))
474 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
475
476 buffer[index + 1]
477 = 0;
478 }
479
480 index += 2;
481
482 /* Store the end of the context buffer. */
483 Context->bufferSize = index * gcmSIZEOF(gctUINT32);
484
485
486 /**************************************************************************/
487 /* Pipe switch for the case where neither 2D nor 3D are used. *************/
488
489 /* Store the 3D entry index. */
490 Context->entryOffsetXDFrom2D = (gctUINT)index * gcmSIZEOF(gctUINT32);
491
492 /* Flush 2D pipe. */
493 index += _FlushPipe(Context, index, gcvPIPE_2D);
494
495 /* Switch to 3D pipe. */
496 index += _SwitchPipe(Context, index, gcvPIPE_3D);
497
498 /* Store the location of the link. */
499 Context->linkIndexXD = (gctUINT)index;
500
501 if (buffer != gcvNULL)
502 {
503 buffer[index + 0]
504 = ((((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)))
505 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
506
507 buffer[index + 1]
508 = 0;
509 }
510
511 index += 2;
512
513
514 /**************************************************************************/
515 /* Save size for buffer. **************************************************/
516
517 Context->totalSize = index * gcmSIZEOF(gctUINT32);
518
519
520 /* Success. */
521 return gcvSTATUS_OK;
522}
523
524static gceSTATUS
525_DestroyContext(
526 IN gckCONTEXT Context
527 )
528{
529 gceSTATUS status = gcvSTATUS_OK;
530
531 if (Context != gcvNULL)
532 {
533 gcsCONTEXT_PTR bufferHead;
534
535 /* Free context buffers. */
536 for (bufferHead = Context->buffer; Context->buffer != gcvNULL;)
537 {
538 /* Get a shortcut to the current buffer. */
539 gcsCONTEXT_PTR buffer = Context->buffer;
540
541 /* Get the next buffer. */
542 gcsCONTEXT_PTR next = buffer->next;
543
544 /* Last item? */
545 if (next == bufferHead)
546 {
547 next = gcvNULL;
548 }
549
550 /* Destroy the signal. */
551 if (buffer->signal != gcvNULL)
552 {
553 gcmkONERROR(gckOS_DestroySignal(
554 Context->os, buffer->signal
555 ));
556
557 buffer->signal = gcvNULL;
558 }
559
560 /* Free state delta map. */
561 if (buffer->logical != gcvNULL)
562 {
563 if (Context->hardware->kernel->virtualCommandBuffer)
564 {
565 gcmkONERROR(gckEVENT_DestroyVirtualCommandBuffer(
566 Context->hardware->kernel->eventObj,
567 Context->totalSize,
568 buffer->physical,
569 buffer->logical,
570 gcvKERNEL_PIXEL
571 ));
572 }
573 else
574 {
575 gcmkONERROR(gckEVENT_FreeContiguousMemory(
576 Context->hardware->kernel->eventObj,
577 Context->totalSize,
578 buffer->physical,
579 buffer->logical,
580 gcvKERNEL_PIXEL
581 ));
582 }
583
584 buffer->logical = gcvNULL;
585 }
586
587 /* Free context buffer. */
588 gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, buffer));
589
590 /* Remove from the list. */
591 Context->buffer = next;
592 }
593
594#if gcdSECURE_USER
595 /* Free the hint array. */
596 if (Context->hint != gcvNULL)
597 {
598 gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->hint));
599 }
600#endif
601 /* Free record array copy. */
602#if REMOVE_DUPLICATED_COPY_FROM_USER
603 if (Context->recordArrayMap != gcvNULL)
604 {
605 gcsRECORD_ARRAY_MAP_PTR map = Context->recordArrayMap;
606
607 do
608 {
609 /* Free record array. */
610 gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, map->kData));
611 map = map->next;
612 }
613 while (map != Context->recordArrayMap);
614
615 gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->recordArrayMap));
616 }
617#else
618 if (Context->recordArray != gcvNULL)
619 {
620 gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context->recordArray));
621 }
622#endif
623
624 /* Mark the gckCONTEXT object as unknown. */
625 Context->object.type = gcvOBJ_UNKNOWN;
626
627 /* Free the gckCONTEXT object. */
628 gcmkONERROR(gcmkOS_SAFE_FREE(Context->os, Context));
629 }
630
631OnError:
632 return status;
633}
634
635
636/******************************************************************************\
637**************************** Context Management API ****************************
638\******************************************************************************/
639
640/******************************************************************************\
641**
642** gckCONTEXT_Construct
643**
644** Construct a new gckCONTEXT object.
645**
646** INPUT:
647**
648** gckOS Os
649** Pointer to gckOS object.
650**
651** gctUINT32 ProcessID
652** Current process ID.
653**
654** gckHARDWARE Hardware
655** Pointer to gckHARDWARE object.
656**
657** OUTPUT:
658**
659** gckCONTEXT * Context
660** Pointer to a variable thet will receive the gckCONTEXT object
661** pointer.
662*/
663gceSTATUS
664gckCONTEXT_Construct(
665 IN gckOS Os,
666 IN gckHARDWARE Hardware,
667 IN gctUINT32 ProcessID,
668 OUT gckCONTEXT * Context
669 )
670{
671 gceSTATUS status;
672 gckCONTEXT context = gcvNULL;
673 gctUINT32 allocationSize;
674 gctUINT i;
675 gctPOINTER pointer = gcvNULL;
676 gctUINT32 address;
677
678 gcmkHEADER_ARG("Os=0x%08X Hardware=0x%08X", Os, Hardware);
679
680 /* Verify the arguments. */
681 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
682 gcmkVERIFY_ARGUMENT(Context != gcvNULL);
683
684
685 /**************************************************************************/
686 /* Allocate and initialize basic fields of gckCONTEXT. ********************/
687
688 /* The context object size. */
689 allocationSize = gcmSIZEOF(struct _gckCONTEXT);
690
691 /* Allocate the object. */
692 gcmkONERROR(gckOS_Allocate(
693 Os, allocationSize, &pointer
694 ));
695
696 context = pointer;
697
698 /* Reset the entire object. */
699 gcmkONERROR(gckOS_ZeroMemory(context, allocationSize));
700
701 /* Initialize the gckCONTEXT object. */
702 context->object.type = gcvOBJ_CONTEXT;
703 context->os = Os;
704 context->hardware = Hardware;
705
706
707 context->entryPipe = gcvPIPE_2D;
708 context->exitPipe = gcvPIPE_2D;
709
710 /* Get the command buffer requirements. */
711 gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
712 Hardware,
713 &context->alignment,
714 &context->reservedHead,
715 &context->reservedTail
716 ));
717
718 /* Mark the context as dirty to force loading of the entire state table
719 the first time. */
720 context->dirty = gcvTRUE;
721
722
723 /**************************************************************************/
724 /* Get the size of the context buffer. ************************************/
725
726 gcmkONERROR(_InitializeContextBuffer(context));
727
728
729 /**************************************************************************/
730 /* Compute the size of the record array. **********************************/
731
732 context->recordArraySize
733#ifdef DISABLE_RECORD_ARRAY_SIZE_OPTIMIZATION
734 = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * (gctUINT)context->maxState;
735#else
736 = gcmSIZEOF(gcsSTATE_DELTA_RECORD) * (gctUINT)context->numStates;
737#endif
738
739
740 if (context->maxState > 0)
741 {
742 /**************************************************************************/
743 /* Allocate and reset the state mapping table. ****************************/
744 if (context->hardware->kernel->command->stateMap == gcvNULL)
745 {
746 /* Allocate the state mapping table. */
747 gcmkONERROR(gckOS_Allocate(
748 Os,
749 gcmSIZEOF(gcsSTATE_MAP) * context->maxState,
750 &pointer
751 ));
752
753 context->map = pointer;
754
755 /* Zero the state mapping table. */
756 gcmkONERROR(gckOS_ZeroMemory(
757 context->map, gcmSIZEOF(gcsSTATE_MAP) * context->maxState
758 ));
759
760 context->hardware->kernel->command->stateMap = pointer;
761 }
762 else
763 {
764 context->map = context->hardware->kernel->command->stateMap;
765 }
766
767 /**************************************************************************/
768 /* Allocate the hint array. ***********************************************/
769
770#if gcdSECURE_USER
771 /* Allocate hints. */
772 gcmkONERROR(gckOS_Allocate(
773 Os,
774 gcmSIZEOF(gctBOOL) * context->maxState,
775 &pointer
776 ));
777
778 context->hint = pointer;
779#endif
780 }
781
782 /**************************************************************************/
783 /* Allocate the context and state delta buffers. **************************/
784
785 for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i += 1)
786 {
787 /* Allocate a context buffer. */
788 gcsCONTEXT_PTR buffer;
789
790 gctSIZE_T totalSize = context->totalSize;
791
792 /* Allocate the context buffer structure. */
793 gcmkONERROR(gckOS_Allocate(
794 Os,
795 gcmSIZEOF(gcsCONTEXT),
796 &pointer
797 ));
798
799 buffer = pointer;
800
801 /* Reset the context buffer structure. */
802 gcmkVERIFY_OK(gckOS_ZeroMemory(
803 buffer, gcmSIZEOF(gcsCONTEXT)
804 ));
805
806 /* Append to the list. */
807 if (context->buffer == gcvNULL)
808 {
809 buffer->next = buffer;
810 context->buffer = buffer;
811 }
812 else
813 {
814 buffer->next = context->buffer->next;
815 context->buffer->next = buffer;
816 }
817
818 /* Set the number of delta in the order of creation. */
819#if gcmIS_DEBUG(gcdDEBUG_CODE)
820 buffer->num = i;
821#endif
822
823 /* Create the busy signal. */
824 gcmkONERROR(gckOS_CreateSignal(
825 Os, gcvFALSE, &buffer->signal
826 ));
827
828 /* Set the signal, buffer is currently not busy. */
829 gcmkONERROR(gckOS_Signal(
830 Os, buffer->signal, gcvTRUE
831 ));
832
833 /* Create a new physical context buffer. */
834 if (context->hardware->kernel->virtualCommandBuffer)
835 {
836 gcmkONERROR(gckKERNEL_AllocateVirtualCommandBuffer(
837 context->hardware->kernel,
838 gcvFALSE,
839 &totalSize,
840 &buffer->physical,
841 &pointer
842 ));
843
844 gcmkONERROR(gckKERNEL_GetGPUAddress(
845 context->hardware->kernel,
846 pointer,
847 gcvFALSE,
848 buffer->physical,
849 &address
850 ));
851 }
852 else
853 {
854 gcmkONERROR(gckOS_AllocateContiguous(
855 Os,
856 gcvFALSE,
857 &totalSize,
858 &buffer->physical,
859 &pointer
860 ));
861
862 gcmkONERROR(gckHARDWARE_ConvertLogical(
863 context->hardware,
864 pointer,
865 gcvFALSE,
866 &address
867 ));
868 }
869
870 buffer->logical = pointer;
871 buffer->address = address;
872
873 /* Set gckEVENT object pointer. */
874 buffer->eventObj = Hardware->kernel->eventObj;
875
876 /* Set the pointers to the LINK commands. */
877 if (context->linkIndex2D != 0)
878 {
879 buffer->link2D = &buffer->logical[context->linkIndex2D];
880 }
881
882 if (context->linkIndex3D != 0)
883 {
884 buffer->link3D = &buffer->logical[context->linkIndex3D];
885 }
886
887 if (context->linkIndexXD != 0)
888 {
889 gctPOINTER xdLink;
890 gctUINT32 xdEntryAddress;
891 gctUINT32 xdEntrySize;
892 gctUINT32 linkBytes;
893
894 /* Determine LINK parameters. */
895 xdLink
896 = &buffer->logical[context->linkIndexXD];
897
898 xdEntryAddress
899 = buffer->address
900 + context->entryOffsetXDFrom3D;
901
902 xdEntrySize
903 = context->bufferSize
904 - context->entryOffsetXDFrom3D;
905
906 /* Query LINK size. */
907 gcmkONERROR(gckHARDWARE_Link(
908 Hardware, gcvNULL, 0, 0, &linkBytes, gcvNULL, gcvNULL
909 ));
910
911 /* Generate a LINK. */
912 gcmkONERROR(gckHARDWARE_Link(
913 Hardware,
914 xdLink,
915 xdEntryAddress,
916 xdEntrySize,
917 &linkBytes,
918 gcvNULL,
919 gcvNULL
920 ));
921 }
922 }
923
924
925 /**************************************************************************/
926 /* Initialize the context buffers. ****************************************/
927
928 /* Initialize the current context buffer. */
929 gcmkONERROR(_InitializeContextBuffer(context));
930
931 /* Make all created contexts equal. */
932 {
933 gcsCONTEXT_PTR currContext, tempContext;
934
935 /* Set the current context buffer. */
936 currContext = context->buffer;
937
938 /* Get the next context buffer. */
939 tempContext = currContext->next;
940
941 /* Loop through all buffers. */
942 while (tempContext != currContext)
943 {
944 if (tempContext == gcvNULL)
945 {
946 gcmkONERROR(gcvSTATUS_NOT_FOUND);
947 }
948
949 /* Copy the current context. */
950 gckOS_MemCopy(
951 tempContext->logical,
952 currContext->logical,
953 context->totalSize
954 );
955
956 /* Get the next context buffer. */
957 tempContext = tempContext->next;
958 }
959 }
960
961 /* Return pointer to the gckCONTEXT object. */
962 *Context = context;
963
964 /* Success. */
965 gcmkFOOTER_ARG("*Context=0x%08X", *Context);
966 return gcvSTATUS_OK;
967
968OnError:
969 /* Roll back on error. */
970 gcmkVERIFY_OK(_DestroyContext(context));
971
972 /* Return the status. */
973 gcmkFOOTER();
974 return status;
975}
976
977/******************************************************************************\
978**
979** gckCONTEXT_Destroy
980**
981** Destroy a gckCONTEXT object.
982**
983** INPUT:
984**
985** gckCONTEXT Context
986** Pointer to an gckCONTEXT object.
987**
988** OUTPUT:
989**
990** Nothing.
991*/
992gceSTATUS
993gckCONTEXT_Destroy(
994 IN gckCONTEXT Context
995 )
996{
997 gceSTATUS status;
998
999 gcmkHEADER_ARG("Context=0x%08X", Context);
1000
1001 /* Verify the arguments. */
1002 gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
1003
1004 /* Destroy the context and all related objects. */
1005 status = _DestroyContext(Context);
1006
1007 /* Success. */
1008 gcmkFOOTER_NO();
1009 return status;
1010}
1011
1012/******************************************************************************\
1013**
1014** gckCONTEXT_Update
1015**
1016** Merge all pending state delta buffers into the current context buffer.
1017**
1018** INPUT:
1019**
1020** gckCONTEXT Context
1021** Pointer to an gckCONTEXT object.
1022**
1023** gctUINT32 ProcessID
1024** Current process ID.
1025**
1026** gcsSTATE_DELTA_PTR StateDelta
1027** Pointer to the state delta.
1028**
1029** OUTPUT:
1030**
1031** Nothing.
1032*/
1033gceSTATUS
1034gckCONTEXT_Update(
1035 IN gckCONTEXT Context,
1036 IN gctUINT32 ProcessID,
1037 IN gcsSTATE_DELTA_PTR StateDelta
1038 )
1039{
1040 return gcvSTATUS_OK;
1041}
1042
1043gceSTATUS
1044gckCONTEXT_MapBuffer(
1045 IN gckCONTEXT Context,
1046 OUT gctUINT32 *Physicals,
1047 OUT gctUINT64 *Logicals,
1048 OUT gctUINT32 *Bytes
1049 )
1050{
1051 gceSTATUS status;
1052 int i = 0;
1053 gctSIZE_T pageCount;
1054 gckVIRTUAL_COMMAND_BUFFER_PTR commandBuffer;
1055 gckKERNEL kernel = Context->hardware->kernel;
1056 gctPOINTER logical;
1057 gctPHYS_ADDR physical;
1058
1059 gcsCONTEXT_PTR buffer;
1060
1061 gcmkHEADER();
1062
1063 gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
1064
1065 buffer = Context->buffer;
1066
1067 for (i = 0; i < gcdCONTEXT_BUFFER_COUNT; i++)
1068 {
1069 if (kernel->virtualCommandBuffer)
1070 {
1071 commandBuffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)buffer->physical;
1072 physical = commandBuffer->physical;
1073
1074 gcmkONERROR(gckOS_CreateUserVirtualMapping(
1075 kernel->os,
1076 physical,
1077 Context->totalSize,
1078 &logical,
1079 &pageCount));
1080 }
1081 else
1082 {
1083 physical = buffer->physical;
1084
1085 gcmkONERROR(gckOS_MapMemory(
1086 kernel->os,
1087 physical,
1088 Context->totalSize,
1089 &logical));
1090 }
1091
1092 Physicals[i] = gcmPTR_TO_NAME(physical);
1093
1094 Logicals[i] = gcmPTR_TO_UINT64(logical);
1095
1096 buffer = buffer->next;
1097 }
1098
1099 *Bytes = (gctUINT)Context->totalSize;
1100
1101 gcmkFOOTER_NO();
1102 return gcvSTATUS_OK;
1103
1104OnError:
1105 gcmkFOOTER();
1106 return status;
1107}
1108
diff --git a/src/hal/kernel/arch/gc_hal_kernel_context.h b/src/hal/kernel/arch/gc_hal_kernel_context.h
new file mode 100755
index 0000000..b02878b
--- /dev/null
+++ b/src/hal/kernel/arch/gc_hal_kernel_context.h
@@ -0,0 +1,247 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_context_h_
57#define __gc_hal_kernel_context_h_
58
59#include "gc_hal_kernel_buffer.h"
60
61/* Exprimental optimization. */
62#define REMOVE_DUPLICATED_COPY_FROM_USER 1
63
64#ifdef __cplusplus
65extern "C" {
66#endif
67
68/* Maps state locations within the context buffer. */
69typedef struct _gcsSTATE_MAP * gcsSTATE_MAP_PTR;
70typedef struct _gcsSTATE_MAP
71{
72 /* Index of the state in the context buffer. */
73 gctUINT index;
74
75 /* State mask. */
76 gctUINT32 mask;
77}
78gcsSTATE_MAP;
79
80/* Context buffer. */
81typedef struct _gcsCONTEXT * gcsCONTEXT_PTR;
82typedef struct _gcsCONTEXT
83{
84 /* For debugging: the number of context buffer in the order of creation. */
85#if gcmIS_DEBUG(gcdDEBUG_CODE)
86 gctUINT num;
87#endif
88
89 /* Pointer to gckEVENT object. */
90 gckEVENT eventObj;
91
92 /* Context busy signal. */
93 gctSIGNAL signal;
94
95 /* Physical address of the context buffer. */
96 gctPHYS_ADDR physical;
97
98 /* Logical address of the context buffer. */
99 gctUINT32_PTR logical;
100
101 /* Hardware address of the context buffer. */
102 gctUINT32 address;
103
104 /* Pointer to the LINK commands. */
105 gctPOINTER link2D;
106 gctPOINTER link3D;
107
108 /* The number of pending state deltas. */
109 gctUINT deltaCount;
110
111 /* Pointer to the first delta to be applied. */
112 gcsSTATE_DELTA_PTR delta;
113
114 /* Next context buffer. */
115 gcsCONTEXT_PTR next;
116}
117gcsCONTEXT;
118
119typedef struct _gcsRECORD_ARRAY_MAP * gcsRECORD_ARRAY_MAP_PTR;
120struct _gcsRECORD_ARRAY_MAP
121{
122 /* User pointer key. */
123 gctUINT64 key;
124
125 /* Kernel memory buffer. */
126 gcsSTATE_DELTA_RECORD_PTR kData;
127
128 /* Next map. */
129 gcsRECORD_ARRAY_MAP_PTR next;
130
131};
132
133#define USE_SW_RESET 1
134
135/* gckCONTEXT structure that hold the current context. */
136struct _gckCONTEXT
137{
138 /* Object. */
139 gcsOBJECT object;
140
141 /* Pointer to gckOS object. */
142 gckOS os;
143
144 /* Pointer to gckHARDWARE object. */
145 gckHARDWARE hardware;
146
147 /* Command buffer alignment. */
148 gctUINT32 alignment;
149 gctUINT32 reservedHead;
150 gctUINT32 reservedTail;
151
152 /* Context buffer metrics. */
153 gctSIZE_T maxState;
154 gctUINT32 numStates;
155 gctUINT32 totalSize;
156 gctUINT32 bufferSize;
157 gctUINT32 linkIndex2D;
158 gctUINT32 linkIndex3D;
159 gctUINT32 linkIndexXD;
160 gctUINT32 entryOffset3D;
161 gctUINT32 entryOffsetXDFrom2D;
162 gctUINT32 entryOffsetXDFrom3D;
163
164 /* Dirty flags. */
165 gctBOOL dirty;
166 gctBOOL dirty2D;
167 gctBOOL dirty3D;
168 gcsCONTEXT_PTR dirtyBuffer;
169
170 /* State mapping. */
171 gcsSTATE_MAP_PTR map;
172
173 /* List of context buffers. */
174 gcsCONTEXT_PTR buffer;
175
176 /* A copy of the user record array. */
177 gctUINT recordArraySize;
178#if REMOVE_DUPLICATED_COPY_FROM_USER
179 gcsRECORD_ARRAY_MAP_PTR recordArrayMap;
180#else
181 gcsSTATE_DELTA_RECORD_PTR recordArray;
182#endif
183
184 /* Requested pipe select for context. */
185 gcePIPE_SELECT entryPipe;
186 gcePIPE_SELECT exitPipe;
187
188 /* Variables used for building state buffer. */
189 gctUINT32 lastAddress;
190 gctSIZE_T lastSize;
191 gctUINT32 lastIndex;
192 gctBOOL lastFixed;
193
194 gctUINT32 pipeSelectBytes;
195
196 /* Hint array. */
197#if gcdSECURE_USER
198 gctBOOL_PTR hint;
199#endif
200
201#if VIVANTE_PROFILER_CONTEXT
202 gcsPROFILER_COUNTERS latestProfiler;
203 gcsPROFILER_COUNTERS histroyProfiler;
204
205#if USE_SW_RESET
206 /* RA */
207 gctUINT32 prevRaValidPixelCount;
208 gctUINT32 prevRaTotalQuadCount;
209 gctUINT32 prevRaValidQuadCountAfterEarlyZ;
210 gctUINT32 prevRaTotalPrimitiveCount;
211 gctUINT32 prevRaPipeCacheMissCounter;
212 gctUINT32 prevRaPrefetchCacheMissCounter;
213
214 /* PE */
215 gctUINT32 prevPePixelCountKilledByColorPipe;
216 gctUINT32 prevPePixelCountKilledByDepthPipe;
217 gctUINT32 prevPePixelCountDrawnByColorPipe;
218 gctUINT32 prevPePixelCountDrawnByDepthPipe;
219
220 /* PA */
221 gctUINT32 prevPaInputVtxCounter;
222 gctUINT32 prevPaInputPrimCounter;
223 gctUINT32 prevPaOutputPrimCounter;
224 gctUINT32 prevPaDepthClippedCounter;
225 gctUINT32 prevPaTrivialRejectedCounter;
226 gctUINT32 prevPaCulledCounter;
227
228 /* SH */
229 gctUINT32 prevVSInstCount;
230 gctUINT32 prevVSBranchInstCount;
231 gctUINT32 prevVSTexInstCount;
232 gctUINT32 prevVSVertexCount;
233 gctUINT32 prevPSInstCount;
234 gctUINT32 prevPSBranchInstCount;
235 gctUINT32 prevPSTexInstCount;
236 gctUINT32 prevPSPixelCount;
237#endif
238
239#endif
240};
241
242#ifdef __cplusplus
243}
244#endif
245
246#endif /* __gc_hal_kernel_context_h_ */
247
diff --git a/src/hal/kernel/arch/gc_hal_kernel_hardware.c b/src/hal/kernel/arch/gc_hal_kernel_hardware.c
new file mode 100755
index 0000000..10ea1e8
--- /dev/null
+++ b/src/hal/kernel/arch/gc_hal_kernel_hardware.c
@@ -0,0 +1,7894 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal.h"
57#include "gc_hal_kernel.h"
58#if VIVANTE_PROFILER_CONTEXT
59#include "gc_hal_kernel_context.h"
60#endif
61
62#define gcdDISABLE_FE_L2 1
63
64#define _GC_OBJ_ZONE gcvZONE_HARDWARE
65
66#define gcmSEMAPHORESTALL(buffer) \
67 do \
68 { \
69 /* Arm the PE-FE Semaphore. */ \
70 *buffer++ \
71 = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
72 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, 1) \
73 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, 0x0E02); \
74 \
75 *buffer++ \
76 = gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END) \
77 | gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE);\
78 \
79 /* STALL FE until PE is done flushing. */ \
80 *buffer++ \
81 = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
82 \
83 *buffer++ \
84 = gcmSETFIELDVALUE(0, STALL_STALL, SOURCE, FRONT_END) \
85 | gcmSETFIELDVALUE(0, STALL_STALL, DESTINATION, PIXEL_ENGINE); \
86 } while(0)
87
88typedef struct _gcsiDEBUG_REGISTERS * gcsiDEBUG_REGISTERS_PTR;
89typedef struct _gcsiDEBUG_REGISTERS
90{
91 gctSTRING module;
92 gctUINT index;
93 gctUINT shift;
94 gctUINT data;
95 gctUINT count;
96 gctUINT32 signature;
97}
98gcsiDEBUG_REGISTERS;
99
100/******************************************************************************\
101********************************* Support Code *********************************
102\******************************************************************************/
103static gctBOOL
104_IsHardwareMatch(
105 IN gckHARDWARE Hardware,
106 IN gctINT32 ChipModel,
107 IN gctUINT32 ChipRevision
108 )
109{
110 return ((Hardware->identity.chipModel == ChipModel) &&
111 (Hardware->identity.chipRevision == ChipRevision));
112}
113
114static gceSTATUS
115_ResetGPU(
116 IN gckHARDWARE Hardware,
117 IN gckOS Os,
118 IN gceCORE Core
119 );
120
121static gceSTATUS
122_IdentifyHardware(
123 IN gckOS Os,
124 IN gceCORE Core,
125 OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
126 )
127{
128 gceSTATUS status;
129
130 gctUINT32 chipIdentity;
131
132 gctUINT32 streamCount = 0;
133 gctUINT32 registerMax = 0;
134 gctUINT32 threadCount = 0;
135 gctUINT32 shaderCoreCount = 0;
136 gctUINT32 vertexCacheSize = 0;
137 gctUINT32 vertexOutputBufferSize = 0;
138 gctUINT32 pixelPipes = 0;
139 gctUINT32 instructionCount = 0;
140 gctUINT32 numConstants = 0;
141 gctUINT32 bufferSize = 0;
142 gctUINT32 varyingsCount = 0;
143 gctUINT32 debugControl0 = 0;
144
145 gcmkHEADER_ARG("Os=0x%x", Os);
146
147 /***************************************************************************
148 ** Get chip ID and revision.
149 */
150
151 /* Read chip identity register. */
152 gcmkONERROR(
153 gckOS_ReadRegisterEx(Os, Core,
154 0x00018,
155 &chipIdentity));
156
157 /* Special case for older graphic cores. */
158 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))))))))
159 {
160 Identity->chipModel = gcv500;
161 Identity->chipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
162 }
163
164 else
165 {
166 /* Read chip identity register. */
167 gcmkONERROR(
168 gckOS_ReadRegisterEx(Os, Core,
169 0x00020,
170 (gctUINT32_PTR) &Identity->chipModel));
171
172 if (((Identity->chipModel & 0xFF00) == 0x0400)
173 && (Identity->chipModel != 0x0420)
174 && (Identity->chipModel != 0x0428))
175 {
176 Identity->chipModel = (gceCHIPMODEL) (Identity->chipModel & 0x0400);
177 }
178
179 /* Read CHIP_REV register. */
180 gcmkONERROR(
181 gckOS_ReadRegisterEx(Os, Core,
182 0x00024,
183 &Identity->chipRevision));
184
185 if ((Identity->chipModel == gcv2000) && (Identity->chipRevision & 0xffff0000) == 0xffff0000)
186 {
187 Identity->chipModel = gcv3000;
188 Identity->chipRevision &= 0xffff;
189 Identity->chipFlags |= gcvCHIP_FLAG_GC2000_R2;
190 }
191
192 if ((Identity->chipModel == gcv300)
193 && (Identity->chipRevision == 0x2201)
194 )
195 {
196 gctUINT32 chipDate;
197 gctUINT32 chipTime;
198
199 /* Read date and time registers. */
200 gcmkONERROR(
201 gckOS_ReadRegisterEx(Os, Core,
202 0x00028,
203 &chipDate));
204
205 gcmkONERROR(
206 gckOS_ReadRegisterEx(Os, Core,
207 0x0002C,
208 &chipTime));
209
210 if ((chipDate == 0x20080814) && (chipTime == 0x12051100))
211 {
212 /* This IP has an ECO; put the correct revision in it. */
213 Identity->chipRevision = 0x1051;
214 }
215 }
216
217 gcmkONERROR(
218 gckOS_ReadRegisterEx(Os, Core,
219 0x000A8,
220 &Identity->productID));
221 }
222
223 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
224 "Identity: chipModel=%X",
225 Identity->chipModel);
226
227 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
228 "Identity: chipRevision=%X",
229 Identity->chipRevision);
230
231
232 /***************************************************************************
233 ** Get chip features.
234 */
235
236 /* Read chip feature register. */
237 gcmkONERROR(
238 gckOS_ReadRegisterEx(Os, Core,
239 0x0001C,
240 &Identity->chipFeatures));
241
242
243 if (((Identity->chipModel == gcv500) && (Identity->chipRevision < 2))
244 || ((Identity->chipModel == gcv300) && (Identity->chipRevision < 0x2000))
245 )
246 {
247 /* GC500 rev 1.x and GC300 rev < 2.0 doesn't have these registers. */
248 Identity->chipMinorFeatures = 0;
249 Identity->chipMinorFeatures1 = 0;
250 Identity->chipMinorFeatures2 = 0;
251 Identity->chipMinorFeatures3 = 0;
252 Identity->chipMinorFeatures4 = 0;
253 Identity->chipMinorFeatures5 = 0;
254 Identity->chipMinorFeatures6 = 0;
255 }
256 else
257 {
258 /* Read chip minor feature register #0. */
259 gcmkONERROR(
260 gckOS_ReadRegisterEx(Os, Core,
261 0x00034,
262 &Identity->chipMinorFeatures));
263
264 if (((((gctUINT32) (Identity->chipMinorFeatures)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))))
265 )
266 {
267 /* Read chip minor featuress register #1. */
268 gcmkONERROR(
269 gckOS_ReadRegisterEx(Os, Core,
270 0x00074,
271 &Identity->chipMinorFeatures1));
272
273 /* Read chip minor featuress register #2. */
274 gcmkONERROR(
275 gckOS_ReadRegisterEx(Os, Core,
276 0x00084,
277 &Identity->chipMinorFeatures2));
278
279 /*Identity->chipMinorFeatures2 &= ~(0x1 << 3);*/
280
281 /* Read chip minor featuress register #1. */
282 gcmkONERROR(
283 gckOS_ReadRegisterEx(Os, Core,
284 0x00088,
285 &Identity->chipMinorFeatures3));
286
287
288 /* Read chip minor featuress register #4. */
289 gcmkONERROR(
290 gckOS_ReadRegisterEx(Os, Core,
291 0x00094,
292 &Identity->chipMinorFeatures4));
293
294 /* Read chip minor featuress register #5. */
295 gcmkONERROR(
296 gckOS_ReadRegisterEx(Os, Core,
297 0x000A0,
298 &Identity->chipMinorFeatures5));
299
300 /* Read chip minor featuress register #6. */
301 gcmkONERROR(
302 gckOS_ReadRegisterEx(Os, Core,
303 0x000DC,
304 &Identity->chipMinorFeatures6));
305 }
306 else
307 {
308 /* Chip doesn't has minor features register #1 or 2 or 3 or 4. */
309 Identity->chipMinorFeatures1 = 0;
310 Identity->chipMinorFeatures2 = 0;
311 Identity->chipMinorFeatures3 = 0;
312 Identity->chipMinorFeatures4 = 0;
313 Identity->chipMinorFeatures5 = 0;
314 Identity->chipMinorFeatures6 = 0;
315 }
316 }
317
318 /* Get the Supertile layout in the hardware. */
319 if (((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))))
320 || ((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))))
321 {
322 Identity->superTileMode = 2;
323 }
324 else if (((((gctUINT32) (Identity->chipMinorFeatures)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))))
325 {
326 Identity->superTileMode = 1;
327 }
328 else
329 {
330 Identity->superTileMode = 0;
331 }
332
333 /* Exception for GC1000, revision 5035 & GC800, revision 4612 */
334 if (((Identity->chipModel == gcv1000) && ((Identity->chipRevision == 0x5035)
335 || (Identity->chipRevision == 0x5036)
336 || (Identity->chipRevision == 0x5037)
337 || (Identity->chipRevision == 0x5039)
338 || (Identity->chipRevision >= 0x5040)))
339 || ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4612))
340 || ((Identity->chipModel == gcv600) && (Identity->chipRevision >= 0x4650))
341 || ((Identity->chipModel == gcv860) && (Identity->chipRevision == 0x4647))
342 || ((Identity->chipModel == gcv400) && (Identity->chipRevision >= 0x4633)))
343 {
344 Identity->superTileMode = 1;
345 }
346
347 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
348 "Identity: chipFeatures=0x%08X",
349 Identity->chipFeatures);
350
351 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
352 "Identity: chipMinorFeatures=0x%08X",
353 Identity->chipMinorFeatures);
354
355 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
356 "Identity: chipMinorFeatures1=0x%08X",
357 Identity->chipMinorFeatures1);
358
359 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
360 "Identity: chipMinorFeatures2=0x%08X",
361 Identity->chipMinorFeatures2);
362
363 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
364 "Identity: chipMinorFeatures3=0x%08X",
365 Identity->chipMinorFeatures3);
366
367 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
368 "Identity: chipMinorFeatures4=0x%08X",
369 Identity->chipMinorFeatures4);
370
371 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
372 "Identity: chipMinorFeatures5=0x%08X",
373 Identity->chipMinorFeatures5);
374
375 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
376 "Identity: chipMinorFeatures6=0x%08X",
377 Identity->chipMinorFeatures6);
378
379 /***************************************************************************
380 ** Get chip specs.
381 */
382
383 if (((((gctUINT32) (Identity->chipMinorFeatures)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
384 {
385 gctUINT32 specs, specs2, specs3, specs4;
386
387 /* Read gcChipSpecs register. */
388 gcmkONERROR(
389 gckOS_ReadRegisterEx(Os, Core,
390 0x00048,
391 &specs));
392
393 /* Extract the fields. */
394 registerMax = (((((gctUINT32) (specs)) >> (0 ? 7:4)) & ((gctUINT32) ((((1 ? 7:4) - (0 ? 7:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:4) - (0 ? 7:4) + 1)))))) );
395 threadCount = (((((gctUINT32) (specs)) >> (0 ? 11:8)) & ((gctUINT32) ((((1 ? 11:8) - (0 ? 11:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:8) - (0 ? 11:8) + 1)))))) );
396 shaderCoreCount = (((((gctUINT32) (specs)) >> (0 ? 24:20)) & ((gctUINT32) ((((1 ? 24:20) - (0 ? 24:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 24:20) - (0 ? 24:20) + 1)))))) );
397 vertexCacheSize = (((((gctUINT32) (specs)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
398 vertexOutputBufferSize = (((((gctUINT32) (specs)) >> (0 ? 31:28)) & ((gctUINT32) ((((1 ? 31:28) - (0 ? 31:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:28) - (0 ? 31:28) + 1)))))) );
399 pixelPipes = (((((gctUINT32) (specs)) >> (0 ? 27:25)) & ((gctUINT32) ((((1 ? 27:25) - (0 ? 27:25) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:25) - (0 ? 27:25) + 1)))))) );
400
401 /* Read gcChipSpecs2 register. */
402 gcmkONERROR(
403 gckOS_ReadRegisterEx(Os, Core,
404 0x00080,
405 &specs2));
406
407 instructionCount = (((((gctUINT32) (specs2)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
408 numConstants = (((((gctUINT32) (specs2)) >> (0 ? 31:16)) & ((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1)))))) );
409 bufferSize = (((((gctUINT32) (specs2)) >> (0 ? 7:0)) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1)))))) );
410
411 /* Read gcChipSpecs3 register. */
412 gcmkONERROR(
413 gckOS_ReadRegisterEx(Os, Core,
414 0x0008C,
415 &specs3));
416
417 varyingsCount = (((((gctUINT32) (specs3)) >> (0 ? 8:4)) & ((gctUINT32) ((((1 ? 8:4) - (0 ? 8:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:4) - (0 ? 8:4) + 1)))))) );
418
419 /* Read gcChipSpecs4 register. */
420 gcmkONERROR(
421 gckOS_ReadRegisterEx(Os, Core,
422 0x0009C,
423 &specs4));
424
425
426 streamCount = (((((gctUINT32) (specs4)) >> (0 ? 16:12)) & ((gctUINT32) ((((1 ? 16:12) - (0 ? 16:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:12) - (0 ? 16:12) + 1)))))) );
427 if (streamCount == 0)
428 {
429 /* Extract stream count from older register. */
430 streamCount = (((((gctUINT32) (specs)) >> (0 ? 3:0)) & ((gctUINT32) ((((1 ? 3:0) - (0 ? 3:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:0) - (0 ? 3:0) + 1)))))) );
431 }
432
433 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
434 "Identity: chipSpecs1=0x%08X",
435 specs);
436
437 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
438 "Identity: chipSpecs2=0x%08X",
439 specs2);
440
441 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
442 "Identity: chipSpecs3=0x%08X",
443 specs3);
444
445 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
446 "Identity: chipSpecs4=0x%08X",
447 specs4);
448 }
449
450 /* Get the number of pixel pipes. */
451 Identity->pixelPipes = gcmMAX(pixelPipes, 1);
452
453 /* Get the stream count. */
454 Identity->streamCount = (streamCount != 0)
455 ? streamCount
456 : (Identity->chipModel >= gcv1000) ? 4 : 1;
457
458 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
459 "Specs: streamCount=%u%s",
460 Identity->streamCount,
461 (streamCount == 0) ? " (default)" : "");
462
463 /* Get the vertex output buffer size. */
464 Identity->vertexOutputBufferSize = (vertexOutputBufferSize != 0)
465 ? 1 << vertexOutputBufferSize
466 : (Identity->chipModel == gcv400)
467 ? (Identity->chipRevision < 0x4000) ? 512
468 : (Identity->chipRevision < 0x4200) ? 256
469 : 128
470 : (Identity->chipModel == gcv530)
471 ? (Identity->chipRevision < 0x4200) ? 512
472 : 128
473 : 512;
474
475 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
476 "Specs: vertexOutputBufferSize=%u%s",
477 Identity->vertexOutputBufferSize,
478 (vertexOutputBufferSize == 0) ? " (default)" : "");
479
480 /* Get the maximum number of threads. */
481 Identity->threadCount = (threadCount != 0)
482 ? 1 << threadCount
483 : (Identity->chipModel == gcv400) ? 64
484 : (Identity->chipModel == gcv500) ? 128
485 : (Identity->chipModel == gcv530) ? 128
486 : 256;
487
488 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
489 "Specs: threadCount=%u%s",
490 Identity->threadCount,
491 (threadCount == 0) ? " (default)" : "");
492
493 /* Get the number of shader cores. */
494 Identity->shaderCoreCount = (shaderCoreCount != 0)
495 ? shaderCoreCount
496 : (Identity->chipModel >= gcv1000) ? 2
497 : 1;
498 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
499 "Specs: shaderCoreCount=%u%s",
500 Identity->shaderCoreCount,
501 (shaderCoreCount == 0) ? " (default)" : "");
502
503 /* Get the vertex cache size. */
504 Identity->vertexCacheSize = (vertexCacheSize != 0)
505 ? vertexCacheSize
506 : 8;
507 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
508 "Specs: vertexCacheSize=%u%s",
509 Identity->vertexCacheSize,
510 (vertexCacheSize == 0) ? " (default)" : "");
511
512 /* Get the maximum number of temporary registers. */
513 Identity->registerMax = (registerMax != 0)
514 /* Maximum of registerMax/4 registers are accessible to 1 shader */
515 ? 1 << registerMax
516 : (Identity->chipModel == gcv400) ? 32
517 : 64;
518 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
519 "Specs: registerMax=%u%s",
520 Identity->registerMax,
521 (registerMax == 0) ? " (default)" : "");
522
523 /* Get the instruction count. */
524 Identity->instructionCount = (instructionCount == 0) ? 256
525 : (instructionCount == 1) ? 1024
526 : (instructionCount == 2) ? 2048
527 : (instructionCount == 0xFF) ? 512
528 : 256;
529
530 if (Identity->instructionCount == 256)
531 {
532 if ((Identity->chipModel == gcv2000 && Identity->chipRevision == 0x5108)
533 || Identity->chipModel == gcv880)
534 {
535 Identity->instructionCount = 512;
536 }
537 else if (((((gctUINT32) (Identity->chipMinorFeatures3)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))))
538 {
539 Identity->instructionCount = 512;
540 }
541 }
542
543 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
544 "Specs: instructionCount=%u%s",
545 Identity->instructionCount,
546 (instructionCount == 0) ? " (default)" : "");
547
548 /* Get the number of constants. */
549 Identity->numConstants = (numConstants == 0) ? 168 : numConstants;
550
551 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
552 "Specs: numConstants=%u%s",
553 Identity->numConstants,
554 (numConstants == 0) ? " (default)" : "");
555
556 /* Get the buffer size. */
557 Identity->bufferSize = bufferSize;
558
559 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
560 "Specs: bufferSize=%u%s",
561 Identity->bufferSize,
562 (bufferSize == 0) ? " (default)" : "");
563
564
565 if (varyingsCount != 0)
566 {
567 Identity->varyingsCount = varyingsCount;
568 }
569 else if (((((gctUINT32) (Identity->chipMinorFeatures1)) >> (0 ? 23:23) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))))
570 {
571 Identity->varyingsCount = 12;
572 }
573 else
574 {
575 Identity->varyingsCount = 8;
576 }
577
578 /* For some cores, it consumes two varying for position, so the max varying vectors should minus one. */
579 if ((Identity->chipModel == gcv5000 && Identity->chipRevision == 0x5434) ||
580 (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5222) ||
581 (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5208) ||
582 (Identity->chipModel == gcv4000 && Identity->chipRevision == 0x5245) ||
583 (Identity->chipModel == gcv3000 && Identity->chipRevision == 0x5435) ||
584 (Identity->chipModel == gcv2200 && Identity->chipRevision == 0x5244) ||
585 (Identity->chipModel == gcv1500 && Identity->chipRevision == 0x5246) ||
586 ((Identity->chipModel == gcv2100 || Identity->chipModel == gcv2000) && Identity->chipRevision == 0x5108) ||
587 (Identity->chipModel == gcv880 && (Identity->chipRevision == 0x5107 || Identity->chipRevision == 0x5106)))
588 {
589 Identity->varyingsCount -= 1;
590 }
591
592 Identity->chip2DControl = 0;
593 if (Identity->chipModel == gcv320)
594 {
595 gctUINT32 data;
596
597 gcmkONERROR(
598 gckOS_ReadRegisterEx(Os,
599 Core,
600 0x0002C,
601 &data));
602
603 if ((data != 33956864) &&
604 ((Identity->chipRevision == 0x5007) ||
605 (Identity->chipRevision == 0x5220)))
606 {
607 Identity->chip2DControl |= 0xFF &
608 (Identity->chipRevision == 0x5220 ? 8 :
609 (Identity->chipRevision == 0x5007 ? 12 : 0));
610 }
611
612 if (Identity->chipRevision == 0x5007)
613 {
614 /* Disable splitting rectangle. */
615 Identity->chip2DControl |= 0x100;
616
617 /* Enable 2D Flush. */
618 Identity->chip2DControl |= 0x200;
619 }
620 }
621
622
623 gcmkONERROR(
624 gckOS_ReadRegisterEx(Os, Core,
625 0x00470,
626 &debugControl0));
627
628 if (debugControl0 & (1 << 16))
629 {
630 Identity->chipFlags |= gcvCHIP_FLAG_MSAA_COHERENCEY_ECO_FIX;
631 }
632
633 /* Success. */
634 gcmkFOOTER();
635 return gcvSTATUS_OK;
636
637OnError:
638 /* Return the status. */
639 gcmkFOOTER();
640 return status;
641}
642
643#define gcdDEBUG_MODULE_CLOCK_GATING 0
644#define gcdDISABLE_MODULE_CLOCK_GATING 0
645#define gcdDISABLE_FE_CLOCK_GATING 0
646#define gcdDISABLE_PE_CLOCK_GATING 0
647#define gcdDISABLE_SH_CLOCK_GATING 0
648#define gcdDISABLE_PA_CLOCK_GATING 0
649#define gcdDISABLE_SE_CLOCK_GATING 0
650#define gcdDISABLE_RA_CLOCK_GATING 0
651#define gcdDISABLE_RA_EZ_CLOCK_GATING 0
652#define gcdDISABLE_RA_HZ_CLOCK_GATING 0
653#define gcdDISABLE_TX_CLOCK_GATING 0
654
655#if gcdDEBUG_MODULE_CLOCK_GATING
656gceSTATUS
657_ConfigureModuleLevelClockGating(
658 gckHARDWARE Hardware
659 )
660{
661 gctUINT32 data;
662
663 gcmkVERIFY_OK(
664 gckOS_ReadRegisterEx(Hardware->os,
665 Hardware->core,
666 Hardware->powerBaseAddress
667 + 0x00104,
668 &data));
669
670#if gcdDISABLE_FE_CLOCK_GATING
671 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)));
672#endif
673
674#if gcdDISABLE_PE_CLOCK_GATING
675 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)));
676#endif
677
678#if gcdDISABLE_SH_CLOCK_GATING
679 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
680#endif
681
682#if gcdDISABLE_PA_CLOCK_GATING
683 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
684#endif
685
686#if gcdDISABLE_SE_CLOCK_GATING
687 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)));
688#endif
689
690#if gcdDISABLE_RA_CLOCK_GATING
691 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
692#endif
693
694#if gcdDISABLE_TX_CLOCK_GATING
695 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
696#endif
697
698#if gcdDISABLE_RA_EZ_CLOCK_GATING
699 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
700#endif
701
702#if gcdDISABLE_RA_HZ_CLOCK_GATING
703 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)));
704#endif
705
706 gcmkVERIFY_OK(
707 gckOS_WriteRegisterEx(Hardware->os,
708 Hardware->core,
709 Hardware->powerBaseAddress
710 + 0x00104,
711 data));
712
713#if gcdDISABLE_MODULE_CLOCK_GATING
714 gcmkVERIFY_OK(
715 gckOS_ReadRegisterEx(Hardware->os,
716 Hardware->core,
717 Hardware->powerBaseAddress +
718 0x00100,
719 &data));
720
721 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
722
723
724 gcmkVERIFY_OK(
725 gckOS_WriteRegisterEx(Hardware->os,
726 Hardware->core,
727 Hardware->powerBaseAddress
728 + 0x00100,
729 data));
730#endif
731
732 return gcvSTATUS_OK;
733}
734#endif
735
736#if gcdPOWEROFF_TIMEOUT
737void
738_PowerTimerFunction(
739 gctPOINTER Data
740 )
741{
742 gckHARDWARE hardware = (gckHARDWARE)Data;
743 gcmkVERIFY_OK(
744 gckHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
745}
746#endif
747
748static gceSTATUS
749_VerifyDMA(
750 IN gckOS Os,
751 IN gceCORE Core,
752 gctUINT32_PTR Address1,
753 gctUINT32_PTR Address2,
754 gctUINT32_PTR State1,
755 gctUINT32_PTR State2
756 )
757{
758 gceSTATUS status;
759 gctUINT32 i;
760
761 gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State1));
762 gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address1));
763
764 for (i = 0; i < 500; i += 1)
765 {
766 gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x660, State2));
767 gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x664, Address2));
768
769 if (*Address1 != *Address2)
770 {
771 break;
772 }
773
774 if (*State1 != *State2)
775 {
776 break;
777 }
778 }
779
780OnError:
781 return status;
782}
783
784static gceSTATUS
785_DumpDebugRegisters(
786 IN gckOS Os,
787 IN gceCORE Core,
788 IN gcsiDEBUG_REGISTERS_PTR Descriptor
789 )
790{
791 gceSTATUS status = gcvSTATUS_OK;
792 gctUINT32 select;
793 gctUINT32 data = 0;
794 gctUINT i;
795
796 gcmkHEADER_ARG("Os=0x%X Descriptor=0x%X", Os, Descriptor);
797
798 gcmkPRINT_N(4, " %s debug registers:\n", Descriptor->module);
799
800 for (i = 0; i < Descriptor->count; i += 1)
801 {
802 select = i << Descriptor->shift;
803
804 gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, select));
805#if gcdFPGA_BUILD
806 gcmkONERROR(gckOS_Delay(Os, 1000));
807#endif
808 gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &data));
809
810 gcmkPRINT_N(12, " [0x%02X] 0x%08X\n", i, data);
811 }
812
813 select = 0xF << Descriptor->shift;
814
815 for (i = 0; i < 500; i += 1)
816 {
817 gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, Descriptor->index, select));
818#if gcdFPGA_BUILD
819 gcmkONERROR(gckOS_Delay(Os, 1000));
820#endif
821 gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, Descriptor->data, &data));
822
823 if (data == Descriptor->signature)
824 {
825 break;
826 }
827 }
828
829 if (i == 500)
830 {
831 gcmkPRINT_N(4, " failed to obtain the signature (read 0x%08X).\n", data);
832 }
833 else
834 {
835 gcmkPRINT_N(8, " signature = 0x%08X (%d read attempt(s))\n", data, i + 1);
836 }
837
838OnError:
839 /* Return the error. */
840 gcmkFOOTER();
841 return status;
842}
843
844static gceSTATUS
845_IsGPUPresent(
846 IN gckHARDWARE Hardware
847 )
848{
849 gceSTATUS status;
850 gcsHAL_QUERY_CHIP_IDENTITY identity;
851 gctUINT32 control;
852
853 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
854
855 /* Verify the arguments. */
856 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
857
858 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
859 Hardware->core,
860 0x00000,
861 &control));
862
863 control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)));
864 control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
865
866 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
867 Hardware->core,
868 0x00000,
869 control));
870
871 /* Identify the hardware. */
872 gcmkONERROR(_IdentifyHardware(Hardware->os,
873 Hardware->core,
874 &identity));
875
876 /* Check if these are the same values as saved before. */
877 if ((Hardware->identity.chipModel != identity.chipModel)
878 || (Hardware->identity.chipRevision != identity.chipRevision)
879 || (Hardware->identity.chipFeatures != identity.chipFeatures)
880 || (Hardware->identity.chipMinorFeatures != identity.chipMinorFeatures)
881 || (Hardware->identity.chipMinorFeatures1 != identity.chipMinorFeatures1)
882 || (Hardware->identity.chipMinorFeatures2 != identity.chipMinorFeatures2)
883 )
884 {
885 gcmkPRINT("[galcore]: GPU is not present.");
886 gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
887 }
888
889 /* Success. */
890 gcmkFOOTER_NO();
891 return gcvSTATUS_OK;
892
893OnError:
894 /* Return the error. */
895 gcmkFOOTER();
896 return status;
897}
898
899gceSTATUS
900_FlushCache(
901 gckHARDWARE Hardware,
902 gckCOMMAND Command
903 )
904{
905 gceSTATUS status;
906 gctUINT32 bytes, requested;
907 gctPOINTER buffer;
908
909 /* Get the size of the flush command. */
910 gcmkONERROR(gckHARDWARE_Flush(Hardware,
911 gcvFLUSH_ALL,
912 gcvNULL,
913 &requested));
914
915 /* Reserve space in the command queue. */
916 gcmkONERROR(gckCOMMAND_Reserve(Command,
917 requested,
918 &buffer,
919 &bytes));
920
921 /* Append a flush. */
922 gcmkONERROR(gckHARDWARE_Flush(
923 Hardware, gcvFLUSH_ALL, buffer, &bytes
924 ));
925
926 /* Execute the command queue. */
927 gcmkONERROR(gckCOMMAND_Execute(Command, requested));
928
929 return gcvSTATUS_OK;
930
931OnError:
932 return status;
933}
934
935gctBOOL
936_IsGPUIdle(
937 IN gctUINT32 Idle
938 )
939{
940 return (((((gctUINT32) (Idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) )
941 && (((((gctUINT32) (Idle)) >> (0 ? 1:1)) & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1)))))) )
942 && (((((gctUINT32) (Idle)) >> (0 ? 3:3)) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) )
943 && (((((gctUINT32) (Idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) )
944 && (((((gctUINT32) (Idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) )
945 && (((((gctUINT32) (Idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) )
946 && (((((gctUINT32) (Idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) )
947 && (((((gctUINT32) (Idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) )
948 ;
949}
950
951/*
952* State timer helper must be called with powerMutex held.
953*/
954void
955gckSTATETIMER_Reset(
956 IN gcsSTATETIMER * StateTimer,
957 IN gctUINT64 Start
958 )
959{
960 gctUINT64 now;
961
962 if (Start)
963 {
964 now = Start;
965 }
966 else
967 {
968 gckOS_GetProfileTick(&now);
969 }
970
971 StateTimer->recent = StateTimer->start = now;
972
973 gckOS_ZeroMemory(StateTimer->elapse, gcmSIZEOF(StateTimer->elapse));
974}
975
976void
977gckSTATETIMER_Accumulate(
978 IN gcsSTATETIMER * StateTimer,
979 IN gceCHIPPOWERSTATE OldState
980 )
981{
982 gctUINT64 now;
983 gctUINT64 elapse;
984
985 gckOS_GetProfileTick(&now);
986
987 elapse = now - StateTimer->recent;
988
989 StateTimer->recent = now;
990
991 StateTimer->elapse[OldState] += elapse;
992}
993
994void
995gckSTATETIMER_Query(
996 IN gcsSTATETIMER * StateTimer,
997 IN gceCHIPPOWERSTATE State,
998 OUT gctUINT64_PTR Start,
999 OUT gctUINT64_PTR End,
1000 OUT gctUINT64_PTR On,
1001 OUT gctUINT64_PTR Off,
1002 OUT gctUINT64_PTR Idle,
1003 OUT gctUINT64_PTR Suspend
1004 )
1005{
1006 *Start = StateTimer->start;
1007
1008 gckSTATETIMER_Accumulate(StateTimer, State);
1009
1010 *End = StateTimer->recent;
1011
1012 *On = StateTimer->elapse[gcvPOWER_ON];
1013 *Off = StateTimer->elapse[gcvPOWER_OFF];
1014 *Idle = StateTimer->elapse[gcvPOWER_IDLE];
1015 *Suspend = StateTimer->elapse[gcvPOWER_SUSPEND];
1016
1017 gckSTATETIMER_Reset(StateTimer, StateTimer->recent);
1018}
1019
1020/******************************************************************************\
1021****************************** gckHARDWARE API code *****************************
1022\******************************************************************************/
1023
1024/*******************************************************************************
1025**
1026** gckHARDWARE_Construct
1027**
1028** Construct a new gckHARDWARE object.
1029**
1030** INPUT:
1031**
1032** gckOS Os
1033** Pointer to an initialized gckOS object.
1034**
1035** gceCORE Core
1036** Specified core.
1037**
1038** OUTPUT:
1039**
1040** gckHARDWARE * Hardware
1041** Pointer to a variable that will hold the pointer to the gckHARDWARE
1042** object.
1043*/
1044gceSTATUS
1045gckHARDWARE_Construct(
1046 IN gckOS Os,
1047 IN gceCORE Core,
1048 OUT gckHARDWARE * Hardware
1049 )
1050{
1051 gceSTATUS status;
1052 gckHARDWARE hardware = gcvNULL;
1053 gctUINT16 data = 0xff00;
1054 gctPOINTER pointer = gcvNULL;
1055#if gcdMULTI_GPU_AFFINITY
1056 gctUINT32 control;
1057#endif
1058
1059 gcmkHEADER_ARG("Os=0x%x", Os);
1060
1061 /* Verify the arguments. */
1062 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1063 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
1064
1065 /* Enable the GPU. */
1066 gcmkONERROR(gckOS_SetGPUPower(Os, Core, gcvTRUE, gcvTRUE));
1067 gcmkONERROR(gckOS_WriteRegisterEx(Os,
1068 Core,
1069 0x00000,
1070 0x00000900));
1071
1072 /* Allocate the gckHARDWARE object. */
1073 gcmkONERROR(gckOS_Allocate(Os,
1074 gcmSIZEOF(struct _gckHARDWARE),
1075 &pointer));
1076
1077 gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckHARDWARE));
1078
1079 hardware = (gckHARDWARE) pointer;
1080
1081 /* Initialize the gckHARDWARE object. */
1082 hardware->object.type = gcvOBJ_HARDWARE;
1083 hardware->os = Os;
1084 hardware->core = Core;
1085
1086 /* Identify the hardware. */
1087 gcmkONERROR(_IdentifyHardware(Os, Core, &hardware->identity));
1088
1089 /* Determine the hardware type */
1090 switch (hardware->identity.chipModel)
1091 {
1092 case gcv350:
1093 case gcv355:
1094 hardware->type = gcvHARDWARE_VG;
1095 break;
1096
1097 case gcv200:
1098 case gcv300:
1099 case gcv320:
1100 case gcv328:
1101 case gcv420:
1102 case gcv428:
1103 case gcv520:
1104 hardware->type = gcvHARDWARE_2D;
1105 break;
1106
1107 default:
1108#if gcdMULTI_GPU_AFFINITY
1109 hardware->type = (Core == gcvCORE_MAJOR) ? gcvHARDWARE_3D : gcvHARDWARE_OCL;
1110#else
1111 hardware->type = gcvHARDWARE_3D;
1112#endif
1113
1114 if(hardware->identity.chipModel == gcv880 && hardware->identity.chipRevision == 0x5107)
1115 {
1116 /*set outstanding limit*/
1117 gctUINT32 axi_ot;
1118 gcmkONERROR(gckOS_ReadRegisterEx(Os, Core, 0x00414, &axi_ot));
1119 axi_ot = (axi_ot & (~0xFF)) | 0x00010;
1120 gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00414, axi_ot));
1121 }
1122
1123
1124 if ((((((gctUINT32) (hardware->identity.chipFeatures)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ))
1125 {
1126 hardware->type = (gceHARDWARE_TYPE) (hardware->type | gcvHARDWARE_2D);
1127 }
1128 }
1129
1130 hardware->powerBaseAddress
1131 = ((hardware->identity.chipModel == gcv300)
1132 && (hardware->identity.chipRevision < 0x2000))
1133 ? 0x0100
1134 : 0x0000;
1135
1136 /* _ResetGPU need powerBaseAddress. */
1137 status = _ResetGPU(hardware, Os, Core);
1138
1139 if (status != gcvSTATUS_OK)
1140 {
1141 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
1142 "_ResetGPU failed: status=%d\n", status);
1143 }
1144
1145#if gcdENABLE_DEC_COMPRESSION && !gcdDEC_ENABLE_AHB
1146 gcmkONERROR(gckOS_WriteRegisterEx(Os, gcvCORE_DEC, 0x18180, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22)))));
1147#endif
1148
1149#if gcdMULTI_GPU_AFFINITY
1150 control = ((((gctUINT32) (0x00FF0A05)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1))))))) << (0 ? 27:27)));
1151
1152 gcmkONERROR(gckOS_WriteRegisterEx(Os,
1153 Core,
1154 0x0055C,
1155 control));
1156#endif
1157
1158 hardware->powerMutex = gcvNULL;
1159
1160 hardware->mmuVersion
1161 = (((((gctUINT32) (hardware->identity.chipMinorFeatures1)) >> (0 ? 28:28)) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) );
1162
1163 /* Determine whether bug fixes #1 are present. */
1164 hardware->extraEventStates = ((((gctUINT32) (hardware->identity.chipMinorFeatures1)) >> (0 ? 3:3) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))));
1165
1166 /* Check if big endian */
1167 hardware->bigEndian = (*(gctUINT8 *)&data == 0xff);
1168
1169 /* Initialize the fast clear. */
1170 gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
1171
1172#if !gcdENABLE_128B_MERGE
1173
1174 if (((((gctUINT32) (hardware->identity.chipMinorFeatures2)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
1175 {
1176 /* 128B merge is turned on by default. Disable it. */
1177 gcmkONERROR(gckOS_WriteRegisterEx(Os, Core, 0x00558, 0));
1178 }
1179
1180#endif
1181
1182 /* Set power state to ON. */
1183 hardware->chipPowerState = gcvPOWER_ON;
1184 hardware->clockState = gcvTRUE;
1185 hardware->powerState = gcvTRUE;
1186 hardware->lastWaitLink = ~0U;
1187 hardware->lastEnd = ~0U;
1188 hardware->globalSemaphore = gcvNULL;
1189#if gcdENABLE_FSCALE_VAL_ADJUST
1190 hardware->powerOnFscaleVal = 64;
1191#endif
1192
1193 gcmkONERROR(gckOS_CreateMutex(Os, &hardware->powerMutex));
1194 gcmkONERROR(gckOS_CreateSemaphore(Os, &hardware->globalSemaphore));
1195 hardware->startIsr = gcvNULL;
1196 hardware->stopIsr = gcvNULL;
1197
1198#if gcdPOWEROFF_TIMEOUT
1199 hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
1200
1201 gcmkVERIFY_OK(gckOS_CreateTimer(Os,
1202 _PowerTimerFunction,
1203 (gctPOINTER)hardware,
1204 &hardware->powerOffTimer));
1205#endif
1206
1207 gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
1208 gcmkONERROR(gckOS_AtomConstruct(Os, &hardware->pendingEvent));
1209
1210#if gcdLINK_QUEUE_SIZE
1211 hardware->linkQueue.front = 0;
1212 hardware->linkQueue.rear = 0;
1213 hardware->linkQueue.count = 0;
1214#endif
1215
1216 /* Enable power management by default. */
1217 hardware->powerManagement = gcvTRUE;
1218
1219 /* Disable profiler by default */
1220 hardware->gpuProfiler = gcvFALSE;
1221
1222#if defined(LINUX) || defined(__QNXNTO__) || defined(UNDERCE)
1223 if (hardware->mmuVersion)
1224 {
1225 hardware->endAfterFlushMmuCache = gcvTRUE;
1226 }
1227 else
1228#endif
1229 {
1230 hardware->endAfterFlushMmuCache = gcvFALSE;
1231 }
1232
1233 gcmkONERROR(gckOS_QueryOption(Os, "mmu", (gctUINT32_PTR)&hardware->enableMMU));
1234
1235 hardware->minFscaleValue = 1;
1236
1237 gckSTATETIMER_Reset(&hardware->powerStateTimer, 0);
1238
1239 /* Return pointer to the gckHARDWARE object. */
1240 *Hardware = hardware;
1241
1242 /* Success. */
1243 gcmkFOOTER_ARG("*Hardware=0x%x", *Hardware);
1244 return gcvSTATUS_OK;
1245
1246OnError:
1247 /* Roll back. */
1248 if (hardware != gcvNULL)
1249 {
1250 /* Turn off the power. */
1251 gcmkVERIFY_OK(gckOS_SetGPUPower(Os, Core, gcvFALSE, gcvFALSE));
1252
1253 if (hardware->globalSemaphore != gcvNULL)
1254 {
1255 /* Destroy the global semaphore. */
1256 gcmkVERIFY_OK(gckOS_DestroySemaphore(Os,
1257 hardware->globalSemaphore));
1258 }
1259
1260 if (hardware->powerMutex != gcvNULL)
1261 {
1262 /* Destroy the power mutex. */
1263 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, hardware->powerMutex));
1264 }
1265
1266#if gcdPOWEROFF_TIMEOUT
1267 if (hardware->powerOffTimer != gcvNULL)
1268 {
1269 gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
1270 gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
1271 }
1272#endif
1273
1274 if (hardware->pageTableDirty != gcvNULL)
1275 {
1276 gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
1277 }
1278
1279 if (hardware->pendingEvent != gcvNULL)
1280 {
1281 gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pendingEvent));
1282 }
1283
1284 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, hardware));
1285 }
1286
1287 /* Return the status. */
1288 gcmkFOOTER();
1289 return status;
1290}
1291
1292/*******************************************************************************
1293**
1294** gckHARDWARE_Destroy
1295**
1296** Destroy an gckHARDWARE object.
1297**
1298** INPUT:
1299**
1300** gckHARDWARE Hardware
1301** Pointer to the gckHARDWARE object that needs to be destroyed.
1302**
1303** OUTPUT:
1304**
1305** Nothing.
1306*/
1307gceSTATUS
1308gckHARDWARE_Destroy(
1309 IN gckHARDWARE Hardware
1310 )
1311{
1312 gceSTATUS status;
1313
1314 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1315
1316 /* Verify the arguments. */
1317 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1318
1319 /* Destroy the power semaphore. */
1320 gcmkVERIFY_OK(gckOS_DestroySemaphore(Hardware->os,
1321 Hardware->globalSemaphore));
1322
1323 /* Destroy the power mutex. */
1324 gcmkVERIFY_OK(gckOS_DeleteMutex(Hardware->os, Hardware->powerMutex));
1325
1326#if gcdPOWEROFF_TIMEOUT
1327 gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
1328 gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
1329#endif
1330
1331 gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
1332
1333 gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pendingEvent));
1334
1335 gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
1336 Hardware->os,
1337 Hardware->functionBytes,
1338 Hardware->functionPhysical,
1339 Hardware->functionLogical
1340 ));
1341
1342 /* Mark the object as unknown. */
1343 Hardware->object.type = gcvOBJ_UNKNOWN;
1344
1345 /* Free the object. */
1346 gcmkONERROR(gcmkOS_SAFE_FREE(Hardware->os, Hardware));
1347
1348 /* Success. */
1349 gcmkFOOTER_NO();
1350 return gcvSTATUS_OK;
1351
1352OnError:
1353 gcmkFOOTER();
1354 return status;
1355}
1356
1357/*******************************************************************************
1358**
1359** gckHARDWARE_GetType
1360**
1361** Get the hardware type.
1362**
1363** INPUT:
1364**
1365** gckHARDWARE Harwdare
1366** Pointer to an gckHARDWARE object.
1367**
1368** OUTPUT:
1369**
1370** gceHARDWARE_TYPE * Type
1371** Pointer to a variable that receives the type of hardware object.
1372*/
1373gceSTATUS
1374gckHARDWARE_GetType(
1375 IN gckHARDWARE Hardware,
1376 OUT gceHARDWARE_TYPE * Type
1377 )
1378{
1379 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1380 gcmkVERIFY_ARGUMENT(Type != gcvNULL);
1381
1382 *Type = Hardware->type;
1383
1384 gcmkFOOTER_ARG("*Type=%d", *Type);
1385 return gcvSTATUS_OK;
1386}
1387
1388/*******************************************************************************
1389**
1390** gckHARDWARE_InitializeHardware
1391**
1392** Initialize the hardware.
1393**
1394** INPUT:
1395**
1396** gckHARDWARE Hardware
1397** Pointer to the gckHARDWARE object.
1398**
1399** OUTPUT:
1400**
1401** Nothing.
1402*/
1403gceSTATUS
1404gckHARDWARE_InitializeHardware(
1405 IN gckHARDWARE Hardware
1406 )
1407{
1408 gceSTATUS status;
1409 gctUINT32 baseAddress;
1410 gctUINT32 chipRev;
1411 gctUINT32 control;
1412 gctUINT32 data;
1413 gctUINT32 regPMC = 0;
1414
1415 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1416
1417 /* Verify the arguments. */
1418 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1419
1420 /* Read the chip revision register. */
1421 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
1422 Hardware->core,
1423 0x00024,
1424 &chipRev));
1425
1426 chipRev &= 0xffff;
1427
1428 if (chipRev != Hardware->identity.chipRevision)
1429 {
1430 /* Chip is not there! */
1431 gcmkONERROR(gcvSTATUS_CONTEXT_LOSSED);
1432 }
1433
1434 /* Disable isolate GPU bit. */
1435 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1436 Hardware->core,
1437 0x00000,
1438 ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)))));
1439
1440 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
1441 Hardware->core,
1442 0x00000,
1443 &control));
1444
1445 /* Enable debug register. */
1446 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1447 Hardware->core,
1448 0x00000,
1449 ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11)))));
1450
1451 /* Reset memory counters. */
1452 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1453 Hardware->core,
1454 0x0003C,
1455 ~0U));
1456
1457 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1458 Hardware->core,
1459 0x0003C,
1460 0));
1461
1462 /* Get the system's physical base address. */
1463 gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
1464
1465 /* Program the base addesses. */
1466 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1467 Hardware->core,
1468 0x0041C,
1469 baseAddress));
1470
1471 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1472 Hardware->core,
1473 0x00418,
1474 baseAddress));
1475
1476 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1477 Hardware->core,
1478 0x00428,
1479 baseAddress));
1480
1481 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1482 Hardware->core,
1483 0x00420,
1484 baseAddress));
1485
1486 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1487 Hardware->core,
1488 0x00424,
1489 baseAddress));
1490
1491 {
1492 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
1493 Hardware->core,
1494 Hardware->powerBaseAddress +
1495 0x00100,
1496 &data));
1497
1498 /* Enable clock gating. */
1499 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)));
1500
1501 if ((Hardware->identity.chipRevision == 0x4301)
1502 || (Hardware->identity.chipRevision == 0x4302)
1503 )
1504 {
1505 /* Disable stall module level clock gating for 4.3.0.1 and 4.3.0.2
1506 ** revisions. */
1507 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)));
1508 }
1509
1510 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1511 Hardware->core,
1512 Hardware->powerBaseAddress
1513 + 0x00100,
1514 data));
1515
1516 }
1517
1518 if (Hardware->identity.chipModel == gcv4000 &&
1519 ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
1520 {
1521 gcmkONERROR(
1522 gckOS_WriteRegisterEx(Hardware->os,
1523 Hardware->core,
1524 0x0010C,
1525 ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23)))));
1526 }
1527
1528 if (Hardware->identity.chipModel == gcv1000 &&
1529 (Hardware->identity.chipRevision == 0x5039 ||
1530 Hardware->identity.chipRevision == 0x5040))
1531 {
1532 gctUINT32 pulseEater;
1533
1534 pulseEater = ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
1535
1536 gcmkONERROR(
1537 gckOS_WriteRegisterEx(Hardware->os,
1538 Hardware->core,
1539 0x0010C,
1540 ((((gctUINT32) (pulseEater)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)))));
1541 }
1542
1543 if ((gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_HALTI2) == gcvSTATUS_FALSE)
1544 || (Hardware->identity.chipRevision < 0x5422)
1545 )
1546 {
1547 if (regPMC == 0)
1548 {
1549 gcmkONERROR(
1550 gckOS_ReadRegisterEx(Hardware->os,
1551 Hardware->core,
1552 Hardware->powerBaseAddress
1553 + 0x00104,
1554 &regPMC));
1555 }
1556
1557 regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) << (0 ? 15:15)));
1558 }
1559
1560 if (_IsHardwareMatch(Hardware, gcv2000, 0x5108))
1561 {
1562 gcmkONERROR(
1563 gckOS_ReadRegisterEx(Hardware->os,
1564 Hardware->core,
1565 0x00480,
1566 &data));
1567
1568 /* Set FE bus to one, TX bus to zero */
1569 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)));
1570 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
1571
1572 gcmkONERROR(
1573 gckOS_WriteRegisterEx(Hardware->os,
1574 Hardware->core,
1575 0x00480,
1576 data));
1577 }
1578
1579 gcmkONERROR(
1580 gckHARDWARE_SetMMU(Hardware,
1581 Hardware->kernel->mmu->pageTableLogical));
1582
1583 if (Hardware->identity.chipModel >= gcv400
1584 && Hardware->identity.chipModel != gcv420
1585 && (((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 15:15) & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 15:15) - (0 ? 15:15) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:15) - (0 ? 15:15) + 1))))))) != gcvTRUE)
1586 )
1587 {
1588 if (regPMC == 0)
1589 {
1590 gcmkONERROR(
1591 gckOS_ReadRegisterEx(Hardware->os,
1592 Hardware->core,
1593 Hardware->powerBaseAddress
1594 + 0x00104,
1595 &regPMC));
1596 }
1597
1598 /* Disable PA clock gating. */
1599 regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
1600 }
1601
1602 /* Limit 2D outstanding request. */
1603 if (_IsHardwareMatch(Hardware, gcv880, 0x5107))
1604 {
1605 gctUINT32 axi_ot;
1606 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00414, &axi_ot));
1607 axi_ot = (axi_ot & (~0xFF)) | 0x00010;
1608 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00414, axi_ot));
1609 }
1610
1611 if (Hardware->identity.chip2DControl & 0xFF)
1612 {
1613 gctUINT32 data;
1614
1615 gcmkONERROR(
1616 gckOS_ReadRegisterEx(Hardware->os,
1617 Hardware->core,
1618 0x00414,
1619 &data));
1620
1621 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (Hardware->identity.chip2DControl & 0xFF) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)));
1622
1623 gcmkONERROR(
1624 gckOS_WriteRegisterEx(Hardware->os,
1625 Hardware->core,
1626 0x00414,
1627 data));
1628 }
1629
1630 if (_IsHardwareMatch(Hardware, gcv1000, 0x5035))
1631 {
1632 gcmkONERROR(
1633 gckOS_ReadRegisterEx(Hardware->os,
1634 Hardware->core,
1635 0x00414,
1636 &data));
1637
1638 /* Disable HZ-L2. */
1639 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)));
1640
1641 gcmkONERROR(
1642 gckOS_WriteRegisterEx(Hardware->os,
1643 Hardware->core,
1644 0x00414,
1645 data));
1646 }
1647
1648 if (_IsHardwareMatch(Hardware, gcv4000, 0x5222)
1649 || _IsHardwareMatch(Hardware, gcv2000, 0x5108)
1650 )
1651 {
1652 if (regPMC == 0)
1653 {
1654 gcmkONERROR(
1655 gckOS_ReadRegisterEx(Hardware->os,
1656 Hardware->core,
1657 Hardware->powerBaseAddress
1658 + 0x00104,
1659 &regPMC));
1660 }
1661
1662 /* Disable TX clock gating. */
1663 regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)));
1664 }
1665
1666 if (_IsHardwareMatch(Hardware, gcv880, 0x5106))
1667 {
1668 Hardware->kernel->timeOut = 140 * 1000;
1669 }
1670
1671 if (regPMC == 0)
1672 {
1673 gcmkONERROR(
1674 gckOS_ReadRegisterEx(Hardware->os,
1675 Hardware->core,
1676 Hardware->powerBaseAddress
1677 + 0x00104,
1678 &regPMC));
1679 }
1680
1681 /* Disable RA HZ clock gating. */
1682 regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)));
1683
1684 /* Disable RA EZ clock gating. */
1685 regPMC = ((((gctUINT32) (regPMC)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
1686
1687 if (regPMC != 0)
1688 {
1689 gcmkONERROR(
1690 gckOS_WriteRegisterEx(Hardware->os,
1691 Hardware->core,
1692 Hardware->powerBaseAddress
1693 + 0x00104,
1694 regPMC));
1695 }
1696
1697 if (_IsHardwareMatch(Hardware, gcv2000, 0x5108)
1698 || (_IsHardwareMatch(Hardware, gcv3000, 0x5450) && (Hardware->identity.chipFlags & gcvCHIP_FLAG_GC2000_R2))
1699 || _IsHardwareMatch(Hardware, gcv320, 0x5007)
1700 || _IsHardwareMatch(Hardware, gcv320, 0x5303)
1701 || _IsHardwareMatch(Hardware, gcv880, 0x5106)
1702 || _IsHardwareMatch(Hardware, gcv400, 0x4645)
1703 )
1704 {
1705 /* Update GPU AXI cache atttribute. */
1706 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1707 Hardware->core,
1708 0x00008,
1709 0x00002200));
1710 }
1711
1712
1713 if ((Hardware->identity.chipRevision > 0x5420)
1714 && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_3D))
1715 {
1716 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
1717 Hardware->core,
1718 0x0010C,
1719 &data));
1720
1721 /* Disable internal DFS. */
1722 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18)));
1723
1724 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
1725 Hardware->core,
1726 0x0010C,
1727 data));
1728 }
1729
1730#if gcdDEBUG_MODULE_CLOCK_GATING
1731 _ConfigureModuleLevelClockGating(Hardware);
1732#endif
1733
1734 /* Success. */
1735 gcmkFOOTER_NO();
1736 return gcvSTATUS_OK;
1737
1738OnError:
1739 /* Return the error. */
1740 gcmkFOOTER();
1741 return status;
1742}
1743
1744/*******************************************************************************
1745**
1746** gckHARDWARE_QueryMemory
1747**
1748** Query the amount of memory available on the hardware.
1749**
1750** INPUT:
1751**
1752** gckHARDWARE Hardware
1753** Pointer to the gckHARDWARE object.
1754**
1755** OUTPUT:
1756**
1757** gctSIZE_T * InternalSize
1758** Pointer to a variable that will hold the size of the internal video
1759** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
1760** internal memory will be returned.
1761**
1762** gctUINT32 * InternalBaseAddress
1763** Pointer to a variable that will hold the hardware's base address for
1764** the internal video memory. This pointer cannot be gcvNULL if
1765** 'InternalSize' is also non-gcvNULL.
1766**
1767** gctUINT32 * InternalAlignment
1768** Pointer to a variable that will hold the hardware's base address for
1769** the internal video memory. This pointer cannot be gcvNULL if
1770** 'InternalSize' is also non-gcvNULL.
1771**
1772** gctSIZE_T * ExternalSize
1773** Pointer to a variable that will hold the size of the external video
1774** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
1775** external memory will be returned.
1776**
1777** gctUINT32 * ExternalBaseAddress
1778** Pointer to a variable that will hold the hardware's base address for
1779** the external video memory. This pointer cannot be gcvNULL if
1780** 'ExternalSize' is also non-gcvNULL.
1781**
1782** gctUINT32 * ExternalAlignment
1783** Pointer to a variable that will hold the hardware's base address for
1784** the external video memory. This pointer cannot be gcvNULL if
1785** 'ExternalSize' is also non-gcvNULL.
1786**
1787** gctUINT32 * HorizontalTileSize
1788** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
1789** gcvNULL, no horizontal pixel per tile will be returned.
1790**
1791** gctUINT32 * VerticalTileSize
1792** Number of vertical pixels per tile. If 'VerticalTileSize' is
1793** gcvNULL, no vertical pixel per tile will be returned.
1794*/
1795gceSTATUS
1796gckHARDWARE_QueryMemory(
1797 IN gckHARDWARE Hardware,
1798 OUT gctSIZE_T * InternalSize,
1799 OUT gctUINT32 * InternalBaseAddress,
1800 OUT gctUINT32 * InternalAlignment,
1801 OUT gctSIZE_T * ExternalSize,
1802 OUT gctUINT32 * ExternalBaseAddress,
1803 OUT gctUINT32 * ExternalAlignment,
1804 OUT gctUINT32 * HorizontalTileSize,
1805 OUT gctUINT32 * VerticalTileSize
1806 )
1807{
1808 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1809
1810 /* Verify the arguments. */
1811 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1812
1813 if (InternalSize != gcvNULL)
1814 {
1815 /* No internal memory. */
1816 *InternalSize = 0;
1817 }
1818
1819 if (ExternalSize != gcvNULL)
1820 {
1821 /* No external memory. */
1822 *ExternalSize = 0;
1823 }
1824
1825 if (HorizontalTileSize != gcvNULL)
1826 {
1827 /* 4x4 tiles. */
1828 *HorizontalTileSize = 4;
1829 }
1830
1831 if (VerticalTileSize != gcvNULL)
1832 {
1833 /* 4x4 tiles. */
1834 *VerticalTileSize = 4;
1835 }
1836
1837 /* Success. */
1838 gcmkFOOTER_ARG("*InternalSize=%lu *InternalBaseAddress=0x%08x "
1839 "*InternalAlignment=0x%08x *ExternalSize=%lu "
1840 "*ExternalBaseAddress=0x%08x *ExtenalAlignment=0x%08x "
1841 "*HorizontalTileSize=%u *VerticalTileSize=%u",
1842 gcmOPT_VALUE(InternalSize),
1843 gcmOPT_VALUE(InternalBaseAddress),
1844 gcmOPT_VALUE(InternalAlignment),
1845 gcmOPT_VALUE(ExternalSize),
1846 gcmOPT_VALUE(ExternalBaseAddress),
1847 gcmOPT_VALUE(ExternalAlignment),
1848 gcmOPT_VALUE(HorizontalTileSize),
1849 gcmOPT_VALUE(VerticalTileSize));
1850 return gcvSTATUS_OK;
1851}
1852
1853/*******************************************************************************
1854**
1855** gckHARDWARE_QueryChipIdentity
1856**
1857** Query the identity of the hardware.
1858**
1859** INPUT:
1860**
1861** gckHARDWARE Hardware
1862** Pointer to the gckHARDWARE object.
1863**
1864** OUTPUT:
1865**
1866** gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
1867** Pointer to the identity structure.
1868**
1869*/
1870gceSTATUS
1871gckHARDWARE_QueryChipIdentity(
1872 IN gckHARDWARE Hardware,
1873 OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
1874 )
1875{
1876 gctUINT32 features;
1877
1878 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1879
1880 /* Verify the arguments. */
1881 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1882 gcmkVERIFY_ARGUMENT(Identity != gcvNULL);
1883
1884 /* Return chip model and revision. */
1885 Identity->chipModel = Hardware->identity.chipModel;
1886 Identity->chipRevision = Hardware->identity.chipRevision;
1887
1888 /* Return feature set. */
1889 features = Hardware->identity.chipFeatures;
1890
1891 if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
1892 {
1893 /* Override fast clear by command line. */
1894 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)));
1895 }
1896
1897 if ((((((gctUINT32) (features)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ))
1898 {
1899 /* Override compression by command line. */
1900 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)));
1901 }
1902
1903 /* Mark 2D pipe as available for GC500.0 through GC500.2 and GC300,
1904 ** since they did not have this bit. */
1905 if (((Hardware->identity.chipModel == gcv500) && (Hardware->identity.chipRevision <= 2))
1906 || (Hardware->identity.chipModel == gcv300)
1907 )
1908 {
1909 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)));
1910 }
1911
1912 Identity->chipFeatures = features;
1913
1914 /* Return minor features. */
1915 Identity->chipMinorFeatures = Hardware->identity.chipMinorFeatures;
1916 Identity->chipMinorFeatures1 = Hardware->identity.chipMinorFeatures1;
1917 Identity->chipMinorFeatures2 = Hardware->identity.chipMinorFeatures2;
1918 Identity->chipMinorFeatures3 = Hardware->identity.chipMinorFeatures3;
1919 Identity->chipMinorFeatures4 = Hardware->identity.chipMinorFeatures4;
1920 Identity->chipMinorFeatures5 = Hardware->identity.chipMinorFeatures5;
1921 Identity->chipMinorFeatures6 = Hardware->identity.chipMinorFeatures6;
1922
1923 /* Return chip specs. */
1924 Identity->streamCount = Hardware->identity.streamCount;
1925 Identity->registerMax = Hardware->identity.registerMax;
1926 Identity->threadCount = Hardware->identity.threadCount;
1927 Identity->shaderCoreCount = Hardware->identity.shaderCoreCount;
1928 Identity->vertexCacheSize = Hardware->identity.vertexCacheSize;
1929 Identity->vertexOutputBufferSize = Hardware->identity.vertexOutputBufferSize;
1930 Identity->pixelPipes = Hardware->identity.pixelPipes;
1931 Identity->instructionCount = Hardware->identity.instructionCount;
1932 Identity->numConstants = Hardware->identity.numConstants;
1933 Identity->bufferSize = Hardware->identity.bufferSize;
1934 Identity->varyingsCount = Hardware->identity.varyingsCount;
1935 Identity->superTileMode = Hardware->identity.superTileMode;
1936 Identity->chip2DControl = Hardware->identity.chip2DControl;
1937
1938 Identity->productID = Hardware->identity.productID;
1939 Identity->chipFlags = Hardware->identity.chipFlags;
1940
1941 /* Success. */
1942 gcmkFOOTER_NO();
1943 return gcvSTATUS_OK;
1944}
1945
1946/*******************************************************************************
1947**
1948** gckHARDWARE_SplitMemory
1949**
1950** Split a hardware specific memory address into a pool and offset.
1951**
1952** INPUT:
1953**
1954** gckHARDWARE Hardware
1955** Pointer to the gckHARDWARE object.
1956**
1957** gctUINT32 Address
1958** Address in hardware specific format.
1959**
1960** OUTPUT:
1961**
1962** gcePOOL * Pool
1963** Pointer to a variable that will hold the pool type for the address.
1964**
1965** gctUINT32 * Offset
1966** Pointer to a variable that will hold the offset for the address.
1967*/
1968gceSTATUS
1969gckHARDWARE_SplitMemory(
1970 IN gckHARDWARE Hardware,
1971 IN gctUINT32 Address,
1972 OUT gcePOOL * Pool,
1973 OUT gctUINT32 * Offset
1974 )
1975{
1976 gcmkHEADER_ARG("Hardware=0x%x Addres=0x%08x", Hardware, Address);
1977
1978 /* Verify the arguments. */
1979 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1980 gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
1981 gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
1982
1983 if (Hardware->mmuVersion == 0)
1984 {
1985 /* Dispatch on memory type. */
1986 switch ((((((gctUINT32) (Address)) >> (0 ? 31:31)) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) ))
1987 {
1988 case 0x0:
1989 /* System memory. */
1990 *Pool = gcvPOOL_SYSTEM;
1991 break;
1992
1993 case 0x1:
1994 /* Virtual memory. */
1995 *Pool = gcvPOOL_VIRTUAL;
1996 break;
1997
1998 default:
1999 /* Invalid memory type. */
2000 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
2001 return gcvSTATUS_INVALID_ARGUMENT;
2002 }
2003
2004 /* Return offset of address. */
2005 *Offset = (((((gctUINT32) (Address)) >> (0 ? 30:0)) & ((gctUINT32) ((((1 ? 30:0) - (0 ? 30:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 30:0) - (0 ? 30:0) + 1)))))) );
2006 }
2007 else
2008 {
2009 *Pool = gcvPOOL_SYSTEM;
2010 *Offset = Address;
2011 }
2012
2013 /* Success. */
2014 gcmkFOOTER_ARG("*Pool=%d *Offset=0x%08x", *Pool, *Offset);
2015 return gcvSTATUS_OK;
2016}
2017
2018/*******************************************************************************
2019**
2020** gckHARDWARE_Execute
2021**
2022** Kickstart the hardware's command processor with an initialized command
2023** buffer.
2024**
2025** INPUT:
2026**
2027** gckHARDWARE Hardware
2028** Pointer to the gckHARDWARE object.
2029**
2030** gctUINT32 Address
2031** Hardware address of command buffer.
2032**
2033** gctSIZE_T Bytes
2034** Number of bytes for the prefetch unit (until after the first LINK).
2035**
2036** OUTPUT:
2037**
2038** Nothing.
2039*/
2040gceSTATUS
2041gckHARDWARE_Execute(
2042 IN gckHARDWARE Hardware,
2043 IN gctUINT32 Address,
2044 IN gctSIZE_T Bytes
2045 )
2046{
2047 gceSTATUS status;
2048 gctUINT32 control;
2049
2050 gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Bytes=%lu",
2051 Hardware, Address, Bytes);
2052
2053 /* Verify the arguments. */
2054 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2055
2056 /* Enable all events. */
2057 gcmkONERROR(
2058 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00014, ~0U));
2059
2060 /* Write address register. */
2061 gcmkONERROR(
2062 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00654, Address));
2063
2064 /* Build control register. */
2065 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)))
2066 | ((((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)));
2067
2068 /* Set big endian */
2069 if (Hardware->bigEndian)
2070 {
2071 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)));
2072 }
2073
2074 /* Write control register. */
2075 gcmkONERROR(
2076 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00658, control));
2077
2078 /* Increase execute count. */
2079 Hardware->executeCount++;
2080
2081 /* Record last execute address. */
2082 Hardware->lastExecuteAddress = Address;
2083
2084 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
2085 "Started command buffer @ 0x%08x",
2086 Address);
2087
2088 /* Success. */
2089 gcmkFOOTER_NO();
2090 return gcvSTATUS_OK;
2091
2092OnError:
2093 /* Return the status. */
2094 gcmkFOOTER();
2095 return status;
2096}
2097
2098/*******************************************************************************
2099**
2100** gckHARDWARE_WaitLink
2101**
2102** Append a WAIT/LINK command sequence at the specified location in the command
2103** queue.
2104**
2105** INPUT:
2106**
2107** gckHARDWARE Hardware
2108** Pointer to an gckHARDWARE object.
2109**
2110** gctPOINTER Logical
2111** Pointer to the current location inside the command queue to append
2112** WAIT/LINK command sequence at or gcvNULL just to query the size of the
2113** WAIT/LINK command sequence.
2114**
2115** gctUINT32 Offset
2116** Offset into command buffer required for alignment.
2117**
2118** gctSIZE_T * Bytes
2119** Pointer to the number of bytes available for the WAIT/LINK command
2120** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
2121**
2122** OUTPUT:
2123**
2124** gctSIZE_T * Bytes
2125** Pointer to a variable that will receive the number of bytes required
2126** by the WAIT/LINK command sequence. If 'Bytes' is gcvNULL, nothing will
2127** be returned.
2128**
2129** gctUINT32 * WaitOffset
2130** Pointer to a variable that will receive the offset of the WAIT command
2131** from the specified logcial pointer.
2132** If 'WaitOffset' is gcvNULL nothing will be returned.
2133**
2134** gctSIZE_T * WaitSize
2135** Pointer to a variable that will receive the number of bytes used by
2136** the WAIT command. If 'LinkSize' is gcvNULL nothing will be returned.
2137*/
2138gceSTATUS
2139gckHARDWARE_WaitLink(
2140 IN gckHARDWARE Hardware,
2141 IN gctPOINTER Logical,
2142 IN gctUINT32 Offset,
2143 IN OUT gctUINT32 * Bytes,
2144 OUT gctUINT32 * WaitOffset,
2145 OUT gctUINT32 * WaitSize
2146 )
2147{
2148 static const gctUINT waitCount = 200;
2149
2150 gceSTATUS status;
2151 gctUINT32 address;
2152 gctUINT32_PTR logical;
2153 gctUINT32 bytes;
2154
2155 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x *Bytes=%lu",
2156 Hardware, Logical, Offset, gcmOPT_VALUE(Bytes));
2157
2158 /* Verify the arguments. */
2159 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2160 gcmkVERIFY_ARGUMENT((Logical != gcvNULL) || (Bytes != gcvNULL));
2161
2162 /* Compute number of bytes required. */
2163 bytes = gcmALIGN(Offset + 16, 8) - Offset;
2164 /* Cast the input pointer. */
2165 logical = (gctUINT32_PTR) Logical;
2166
2167 if (logical != gcvNULL)
2168 {
2169 /* Not enough space? */
2170 if (*Bytes < bytes)
2171 {
2172 /* Command queue too small. */
2173 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
2174 }
2175
2176 /* Convert logical into hardware specific address. */
2177 gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, gcvFALSE, &address));
2178
2179 /* Store the WAIT/LINK address. */
2180 Hardware->lastWaitLink = address;
2181
2182 /* Append WAIT(count). */
2183 logical[0]
2184 = ((((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)))
2185 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (waitCount) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
2186
2187
2188 /* Append LINK(2, address). */
2189 logical[2]
2190 = ((((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)))
2191 | ((((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)));
2192
2193 logical[3] = address;
2194
2195 gcmkTRACE_ZONE(
2196 gcvLEVEL_INFO, gcvZONE_HARDWARE,
2197 "0x%08x: WAIT %u", address, waitCount
2198 );
2199
2200 gcmkTRACE_ZONE(
2201 gcvLEVEL_INFO, gcvZONE_HARDWARE,
2202 "0x%08x: LINK 0x%08x, #%lu",
2203 address + 8, address, bytes
2204 );
2205 if (WaitOffset != gcvNULL)
2206 {
2207 /* Return the offset pointer to WAIT command. */
2208 *WaitOffset = 0;
2209 }
2210
2211 if (WaitSize != gcvNULL)
2212 {
2213 /* Return number of bytes used by the WAIT command. */
2214 *WaitSize = 8;
2215 }
2216 }
2217
2218 if (Bytes != gcvNULL)
2219 {
2220 /* Return number of bytes required by the WAIT/LINK command
2221 ** sequence. */
2222 *Bytes = bytes;
2223 }
2224
2225 /* Success. */
2226 gcmkFOOTER_ARG("*Bytes=%lu *WaitOffset=0x%x *WaitSize=%lu",
2227 gcmOPT_VALUE(Bytes), gcmOPT_VALUE(WaitOffset),
2228 gcmOPT_VALUE(WaitSize));
2229 return gcvSTATUS_OK;
2230
2231OnError:
2232 /* Return the status. */
2233 gcmkFOOTER();
2234 return status;
2235}
2236
2237/*******************************************************************************
2238**
2239** gckHARDWARE_End
2240**
2241** Append an END command at the specified location in the command queue.
2242**
2243** INPUT:
2244**
2245** gckHARDWARE Hardware
2246** Pointer to an gckHARDWARE object.
2247**
2248** gctPOINTER Logical
2249** Pointer to the current location inside the command queue to append
2250** END command at or gcvNULL just to query the size of the END command.
2251**
2252** gctSIZE_T * Bytes
2253** Pointer to the number of bytes available for the END command. If
2254** 'Logical' is gcvNULL, this argument will be ignored.
2255**
2256** OUTPUT:
2257**
2258** gctSIZE_T * Bytes
2259** Pointer to a variable that will receive the number of bytes required
2260** for the END command. If 'Bytes' is gcvNULL, nothing will be returned.
2261*/
2262gceSTATUS
2263gckHARDWARE_End(
2264 IN gckHARDWARE Hardware,
2265 IN gctPOINTER Logical,
2266 IN OUT gctUINT32 * Bytes
2267 )
2268{
2269 gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
2270 gctUINT32 address;
2271 gceSTATUS status;
2272
2273 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
2274 Hardware, Logical, gcmOPT_VALUE(Bytes));
2275
2276 /* Verify the arguments. */
2277 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2278 gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
2279
2280 if (Logical != gcvNULL)
2281 {
2282 if (*Bytes < 8)
2283 {
2284 /* Command queue too small. */
2285 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
2286 }
2287
2288 /* Append END. */
2289 logical[0] =
2290 ((((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)));
2291
2292 /* Record the count of execution which is finised by this END. */
2293 logical[1] =
2294 Hardware->executeCount;
2295
2296 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: END", Logical);
2297
2298 /* Make sure the CPU writes out the data to memory. */
2299 gcmkONERROR(
2300 gckOS_MemoryBarrier(Hardware->os, Logical));
2301
2302 gcmkONERROR(gckHARDWARE_ConvertLogical(Hardware, logical, gcvFALSE, &address));
2303
2304 Hardware->lastEnd = address;
2305 }
2306
2307 if (Bytes != gcvNULL)
2308 {
2309 /* Return number of bytes required by the END command. */
2310 *Bytes = 8;
2311 }
2312
2313 /* Success. */
2314 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
2315 return gcvSTATUS_OK;
2316
2317OnError:
2318 /* Return the status. */
2319 gcmkFOOTER();
2320 return status;
2321}
2322
2323
2324/*******************************************************************************
2325**
2326** gckHARDWARE_Nop
2327**
2328** Append a NOP command at the specified location in the command queue.
2329**
2330** INPUT:
2331**
2332** gckHARDWARE Hardware
2333** Pointer to an gckHARDWARE object.
2334**
2335** gctPOINTER Logical
2336** Pointer to the current location inside the command queue to append
2337** NOP command at or gcvNULL just to query the size of the NOP command.
2338**
2339** gctSIZE_T * Bytes
2340** Pointer to the number of bytes available for the NOP command. If
2341** 'Logical' is gcvNULL, this argument will be ignored.
2342**
2343** OUTPUT:
2344**
2345** gctSIZE_T * Bytes
2346** Pointer to a variable that will receive the number of bytes required
2347** for the NOP command. If 'Bytes' is gcvNULL, nothing will be returned.
2348*/
2349gceSTATUS
2350gckHARDWARE_Nop(
2351 IN gckHARDWARE Hardware,
2352 IN gctPOINTER Logical,
2353 IN OUT gctSIZE_T * Bytes
2354 )
2355{
2356 gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
2357 gceSTATUS status;
2358
2359 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x *Bytes=%lu",
2360 Hardware, Logical, gcmOPT_VALUE(Bytes));
2361
2362 /* Verify the arguments. */
2363 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2364 gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
2365
2366 if (Logical != gcvNULL)
2367 {
2368 if (*Bytes < 8)
2369 {
2370 /* Command queue too small. */
2371 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
2372 }
2373
2374 /* Append NOP. */
2375 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)));
2376
2377 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: NOP", Logical);
2378 }
2379
2380 if (Bytes != gcvNULL)
2381 {
2382 /* Return number of bytes required by the NOP command. */
2383 *Bytes = 8;
2384 }
2385
2386 /* Success. */
2387 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
2388 return gcvSTATUS_OK;
2389
2390OnError:
2391 /* Return the status. */
2392 gcmkFOOTER();
2393 return status;
2394}
2395
2396/*******************************************************************************
2397**
2398** gckHARDWARE_Event
2399**
2400** Append an EVENT command at the specified location in the command queue.
2401**
2402** INPUT:
2403**
2404** gckHARDWARE Hardware
2405** Pointer to an gckHARDWARE object.
2406**
2407** gctPOINTER Logical
2408** Pointer to the current location inside the command queue to append
2409** the EVENT command at or gcvNULL just to query the size of the EVENT
2410** command.
2411**
2412** gctUINT8 Event
2413** Event ID to program.
2414**
2415** gceKERNEL_WHERE FromWhere
2416** Location of the pipe to send the event.
2417**
2418** gctSIZE_T * Bytes
2419** Pointer to the number of bytes available for the EVENT command. If
2420** 'Logical' is gcvNULL, this argument will be ignored.
2421**
2422** OUTPUT:
2423**
2424** gctSIZE_T * Bytes
2425** Pointer to a variable that will receive the number of bytes required
2426** for the EVENT command. If 'Bytes' is gcvNULL, nothing will be
2427** returned.
2428*/
2429gceSTATUS
2430gckHARDWARE_Event(
2431 IN gckHARDWARE Hardware,
2432 IN gctPOINTER Logical,
2433 IN gctUINT8 Event,
2434 IN gceKERNEL_WHERE FromWhere,
2435 IN OUT gctUINT32 * Bytes
2436 )
2437{
2438 gctUINT size;
2439 gctUINT32 destination = 0;
2440 gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
2441 gceSTATUS status;
2442
2443 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Event=%u FromWhere=%d *Bytes=%lu",
2444 Hardware, Logical, Event, FromWhere, gcmOPT_VALUE(Bytes));
2445
2446 /* Verify the arguments. */
2447 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2448 gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
2449 gcmkVERIFY_ARGUMENT(Event < 32);
2450
2451
2452 /* Determine the size of the command. */
2453
2454 size = (Hardware->extraEventStates && (FromWhere == gcvKERNEL_PIXEL))
2455 ? gcmALIGN(8 + (1 + 5) * 4, 8) /* EVENT + 5 STATES */
2456 : 8;
2457
2458 if (Logical != gcvNULL)
2459 {
2460 if (*Bytes < size)
2461 {
2462 /* Command queue too small. */
2463 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
2464 }
2465
2466 switch (FromWhere)
2467 {
2468 case gcvKERNEL_COMMAND:
2469 /* From command processor. */
2470 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)));
2471 break;
2472
2473 case gcvKERNEL_PIXEL:
2474 /* From pixel engine. */
2475 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)));
2476 break;
2477
2478 default:
2479 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
2480 }
2481
2482 /* Append EVENT(Event, destiantion). */
2483 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)))
2484 | ((((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)))
2485 | ((((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)));
2486
2487 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)));
2488
2489 /* Make sure the event ID gets written out before GPU can access it. */
2490 gcmkONERROR(
2491 gckOS_MemoryBarrier(Hardware->os, logical + 1));
2492
2493#if gcmIS_DEBUG(gcdDEBUG_TRACE)
2494 {
2495 gctPHYS_ADDR_T phys;
2496 gckOS_GetPhysicalAddress(Hardware->os, Logical, &phys);
2497 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
2498 "0x%08x: EVENT %d", phys, Event);
2499 }
2500#endif
2501
2502 /* Append the extra states. These are needed for the chips that do not
2503 ** support back-to-back events due to the async interface. The extra
2504 ** states add the necessary delay to ensure that event IDs do not
2505 ** collide. */
2506 if (size > 8)
2507 {
2508 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)))
2509 | ((((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)))
2510 | ((((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)));
2511 logical[3] = 0;
2512 logical[4] = 0;
2513 logical[5] = 0;
2514 logical[6] = 0;
2515 logical[7] = 0;
2516 }
2517
2518#if gcdINTERRUPT_STATISTIC
2519 if (Event < gcmCOUNTOF(Hardware->kernel->eventObj->queues))
2520 {
2521 gckOS_AtomSetMask(Hardware->pendingEvent, 1 << Event);
2522 }
2523#endif
2524 }
2525
2526 if (Bytes != gcvNULL)
2527 {
2528 /* Return number of bytes required by the EVENT command. */
2529 *Bytes = size;
2530 }
2531
2532 /* Success. */
2533 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
2534 return gcvSTATUS_OK;
2535
2536OnError:
2537 /* Return the status. */
2538 gcmkFOOTER();
2539 return status;
2540}
2541
2542/*******************************************************************************
2543**
2544** gckHARDWARE_PipeSelect
2545**
2546** Append a PIPESELECT command at the specified location in the command queue.
2547**
2548** INPUT:
2549**
2550** gckHARDWARE Hardware
2551** Pointer to an gckHARDWARE object.
2552**
2553** gctPOINTER Logical
2554** Pointer to the current location inside the command queue to append
2555** the PIPESELECT command at or gcvNULL just to query the size of the
2556** PIPESELECT command.
2557**
2558** gcePIPE_SELECT Pipe
2559** Pipe value to select.
2560**
2561** gctSIZE_T * Bytes
2562** Pointer to the number of bytes available for the PIPESELECT command.
2563** If 'Logical' is gcvNULL, this argument will be ignored.
2564**
2565** OUTPUT:
2566**
2567** gctSIZE_T * Bytes
2568** Pointer to a variable that will receive the number of bytes required
2569** for the PIPESELECT command. If 'Bytes' is gcvNULL, nothing will be
2570** returned.
2571*/
2572gceSTATUS
2573gckHARDWARE_PipeSelect(
2574 IN gckHARDWARE Hardware,
2575 IN gctPOINTER Logical,
2576 IN gcePIPE_SELECT Pipe,
2577 IN OUT gctUINT32 * Bytes
2578 )
2579{
2580 gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
2581 gceSTATUS status;
2582
2583 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Pipe=%d *Bytes=%lu",
2584 Hardware, Logical, Pipe, gcmOPT_VALUE(Bytes));
2585
2586 /* Verify the arguments. */
2587 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2588 gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
2589
2590 /* Append a PipeSelect. */
2591 if (Logical != gcvNULL)
2592 {
2593 gctUINT32 flush, stall;
2594
2595 if (*Bytes < 32)
2596 {
2597 /* Command queue too small. */
2598 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
2599 }
2600
2601 flush = (Pipe == gcvPIPE_2D)
2602 ? ((((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)))
2603 | ((((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)))
2604 : ((((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)));
2605
2606 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)))
2607 | ((((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)));
2608
2609 /* LoadState(AQFlush, 1), flush. */
2610 logical[0]
2611 = ((((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)))
2612 | ((((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)))
2613 | ((((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)));
2614
2615 logical[1]
2616 = flush;
2617
2618 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
2619 "0x%x: FLUSH 0x%x", logical, flush);
2620
2621 /* LoadState(AQSempahore, 1), stall. */
2622 logical[2]
2623 = ((((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)))
2624 | ((((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)))
2625 | ((((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)));
2626
2627 logical[3]
2628 = stall;
2629
2630 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
2631 "0x%x: SEMAPHORE 0x%x", logical + 2, stall);
2632
2633 /* Stall, stall. */
2634 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)));
2635 logical[5] = stall;
2636
2637 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
2638 "0x%x: STALL 0x%x", logical + 4, stall);
2639
2640 /* LoadState(AQPipeSelect, 1), pipe. */
2641 logical[6]
2642 = ((((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)))
2643 | ((((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)))
2644 | ((((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)));
2645
2646 logical[7] = (Pipe == gcvPIPE_2D)
2647 ? 0x1
2648 : 0x0;
2649
2650 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
2651 "0x%x: PIPE %d", logical + 6, Pipe);
2652 }
2653
2654 if (Bytes != gcvNULL)
2655 {
2656 /* Return number of bytes required by the PIPESELECT command. */
2657 *Bytes = 32;
2658 }
2659
2660 /* Success. */
2661 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
2662 return gcvSTATUS_OK;
2663
2664OnError:
2665 /* Return the status. */
2666 gcmkFOOTER();
2667 return status;
2668}
2669
2670/*******************************************************************************
2671**
2672** gckHARDWARE_Link
2673**
2674** Append a LINK command at the specified location in the command queue.
2675**
2676** INPUT:
2677**
2678** gckHARDWARE Hardware
2679** Pointer to an gckHARDWARE object.
2680**
2681** gctPOINTER Logical
2682** Pointer to the current location inside the command queue to append
2683** the LINK command at or gcvNULL just to query the size of the LINK
2684** command.
2685**
2686** gctUINT32 FetchAddress
2687** Hardware address of destination of LINK.
2688**
2689** gctSIZE_T FetchSize
2690** Number of bytes in destination of LINK.
2691**
2692** gctSIZE_T * Bytes
2693** Pointer to the number of bytes available for the LINK command. If
2694** 'Logical' is gcvNULL, this argument will be ignored.
2695**
2696** OUTPUT:
2697**
2698** gctSIZE_T * Bytes
2699** Pointer to a variable that will receive the number of bytes required
2700** for the LINK command. If 'Bytes' is gcvNULL, nothing will be returned.
2701*/
2702gceSTATUS
2703gckHARDWARE_Link(
2704 IN gckHARDWARE Hardware,
2705 IN gctPOINTER Logical,
2706 IN gctUINT32 FetchAddress,
2707 IN gctUINT32 FetchSize,
2708 IN OUT gctUINT32 * Bytes,
2709 OUT gctUINT32 * Low,
2710 OUT gctUINT32 * High
2711 )
2712{
2713 gceSTATUS status;
2714 gctSIZE_T bytes;
2715 gctUINT32 link;
2716 gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
2717
2718 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x FetchAddress=0x%x FetchSize=%lu "
2719 "*Bytes=%lu",
2720 Hardware, Logical, FetchAddress, FetchSize,
2721 gcmOPT_VALUE(Bytes));
2722
2723 /* Verify the arguments. */
2724 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2725 gcmkVERIFY_ARGUMENT((Logical == gcvNULL) || (Bytes != gcvNULL));
2726
2727 if (Logical != gcvNULL)
2728 {
2729 if (*Bytes < 8)
2730 {
2731 /* Command queue too small. */
2732 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
2733 }
2734
2735 gcmkONERROR(
2736 gckOS_WriteMemory(Hardware->os, logical + 1, FetchAddress));
2737
2738 if (High)
2739 {
2740 *High = FetchAddress;
2741 }
2742
2743 /* Make sure the address got written before the LINK command. */
2744 gcmkONERROR(
2745 gckOS_MemoryBarrier(Hardware->os, logical + 1));
2746
2747 /* Compute number of 64-byte aligned bytes to fetch. */
2748 bytes = gcmALIGN(FetchAddress + FetchSize, 64) - FetchAddress;
2749
2750 /* Append LINK(bytes / 8), FetchAddress. */
2751 link = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
2752 | ((((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)));
2753
2754 gcmkONERROR(
2755 gckOS_WriteMemory(Hardware->os, logical, link));
2756
2757 if (Low)
2758 {
2759 *Low = link;
2760 }
2761
2762 /* Memory barrier. */
2763 gcmkONERROR(
2764 gckOS_MemoryBarrier(Hardware->os, logical));
2765 }
2766
2767 if (Bytes != gcvNULL)
2768 {
2769 /* Return number of bytes required by the LINK command. */
2770 *Bytes = 8;
2771 }
2772
2773 /* Success. */
2774 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
2775 return gcvSTATUS_OK;
2776
2777OnError:
2778 /* Return the status. */
2779 gcmkFOOTER();
2780 return status;
2781}
2782
2783/*******************************************************************************
2784**
2785** gckHARDWARE_UpdateQueueTail
2786**
2787** Update the tail of the command queue.
2788**
2789** INPUT:
2790**
2791** gckHARDWARE Hardware
2792** Pointer to an gckHARDWARE object.
2793**
2794** gctPOINTER Logical
2795** Logical address of the start of the command queue.
2796**
2797** gctUINT32 Offset
2798** Offset into the command queue of the tail (last command).
2799**
2800** OUTPUT:
2801**
2802** Nothing.
2803*/
2804gceSTATUS
2805gckHARDWARE_UpdateQueueTail(
2806 IN gckHARDWARE Hardware,
2807 IN gctPOINTER Logical,
2808 IN gctUINT32 Offset
2809 )
2810{
2811 gceSTATUS status;
2812
2813 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Offset=0x%08x",
2814 Hardware, Logical, Offset);
2815
2816 /* Verify the hardware. */
2817 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2818
2819 /* Force a barrier. */
2820 gcmkONERROR(
2821 gckOS_MemoryBarrier(Hardware->os, Logical));
2822
2823 /* Notify gckKERNEL object of change. */
2824 gcmkONERROR(
2825 gckKERNEL_Notify(Hardware->kernel,
2826 gcvNOTIFY_COMMAND_QUEUE,
2827 gcvFALSE));
2828
2829 if (status == gcvSTATUS_CHIP_NOT_READY)
2830 {
2831 gcmkONERROR(gcvSTATUS_DEVICE);
2832 }
2833
2834 /* Success. */
2835 gcmkFOOTER_NO();
2836 return gcvSTATUS_OK;
2837
2838OnError:
2839 /* Return the status. */
2840 gcmkFOOTER();
2841 return status;
2842}
2843
2844/*******************************************************************************
2845**
2846** gckHARDWARE_ConvertLogical
2847**
2848** Convert a logical system address into a hardware specific address.
2849**
2850** INPUT:
2851**
2852** gckHARDWARE Hardware
2853** Pointer to an gckHARDWARE object.
2854**
2855** gctPOINTER Logical
2856** Logical address to convert.
2857**
2858** gctBOOL InUserSpace
2859** gcvTRUE if the memory in user space.
2860**
2861** gctUINT32* Address
2862** Return hardware specific address.
2863**
2864** OUTPUT:
2865**
2866** Nothing.
2867*/
2868gceSTATUS
2869gckHARDWARE_ConvertLogical(
2870 IN gckHARDWARE Hardware,
2871 IN gctPOINTER Logical,
2872 IN gctBOOL InUserSpace,
2873 OUT gctUINT32 * Address
2874 )
2875{
2876 gctUINT32 address;
2877 gceSTATUS status;
2878 gctUINT32 baseAddress;
2879 gctPHYS_ADDR_T physical;
2880
2881 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d",
2882 Hardware, Logical, InUserSpace);
2883
2884 /* Verify the arguments. */
2885 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2886 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2887 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2888
2889 /* Convert logical address into a physical address. */
2890 if (InUserSpace)
2891 {
2892 gcmkONERROR(gckOS_UserLogicalToPhysical(Hardware->os, Logical, &physical));
2893 }
2894 else
2895 {
2896 gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &physical));
2897 }
2898
2899 gcmkSAFECASTPHYSADDRT(address, physical);
2900
2901 /* For old MMU, get GPU address according to baseAddress. */
2902 if (Hardware->mmuVersion == 0)
2903 {
2904 gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, &baseAddress));
2905
2906 /* Subtract base address to get a GPU address. */
2907 gcmkASSERT(address >= baseAddress);
2908 address -= baseAddress;
2909 }
2910
2911 /* Return hardware specific address. */
2912 *Address = (Hardware->mmuVersion == 0)
2913 ? ((((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)))
2914 | ((((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)))
2915 : address;
2916
2917 /* Success. */
2918 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2919 return gcvSTATUS_OK;
2920
2921OnError:
2922 /* Return the status. */
2923 gcmkFOOTER();
2924 return status;
2925}
2926
2927/*******************************************************************************
2928**
2929** gckHARDWARE_Interrupt
2930**
2931** Process an interrupt.
2932**
2933** INPUT:
2934**
2935** gckHARDWARE Hardware
2936** Pointer to an gckHARDWARE object.
2937**
2938** gctBOOL InterruptValid
2939** If gcvTRUE, this function will read the interrupt acknowledge
2940** register, stores the data, and return whether or not the interrupt
2941** is ours or not. If gcvFALSE, this functions will read the interrupt
2942** acknowledge register and combine it with any stored value to handle
2943** the event notifications.
2944**
2945** OUTPUT:
2946**
2947** Nothing.
2948*/
2949gceSTATUS
2950gckHARDWARE_Interrupt(
2951 IN gckHARDWARE Hardware,
2952 IN gctBOOL InterruptValid
2953 )
2954{
2955 gckEVENT eventObj;
2956 gctUINT32 data = 0;
2957 gceSTATUS status;
2958
2959 gcmkHEADER_ARG("Hardware=0x%x InterruptValid=%d", Hardware, InterruptValid);
2960
2961 /* Verify the arguments. */
2962 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2963
2964 /* Extract gckEVENT object. */
2965 eventObj = Hardware->kernel->eventObj;
2966 gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
2967
2968 if (InterruptValid)
2969 {
2970 /* Read AQIntrAcknowledge register. */
2971 gcmkONERROR(
2972 gckOS_ReadRegisterEx(Hardware->os,
2973 Hardware->core,
2974 0x00010,
2975 &data));
2976
2977 if (data == 0)
2978 {
2979 /* Not our interrupt. */
2980 status = gcvSTATUS_NOT_OUR_INTERRUPT;
2981 }
2982 else
2983 {
2984
2985#if gcdINTERRUPT_STATISTIC
2986 gckOS_AtomClearMask(Hardware->pendingEvent, data);
2987#endif
2988
2989 /* Inform gckEVENT of the interrupt. */
2990 status = gckEVENT_Interrupt(eventObj,
2991 data);
2992 }
2993 }
2994 else
2995 {
2996 /* Handle events. */
2997 status = gckEVENT_Notify(eventObj, 0);
2998 }
2999
3000OnError:
3001 /* Return the status. */
3002 gcmkFOOTER();
3003 return status;
3004}
3005
3006/*******************************************************************************
3007**
3008** gckHARDWARE_QueryCommandBuffer
3009**
3010** Query the command buffer alignment and number of reserved bytes.
3011**
3012** INPUT:
3013**
3014** gckHARDWARE Harwdare
3015** Pointer to an gckHARDWARE object.
3016**
3017** OUTPUT:
3018**
3019** gctSIZE_T * Alignment
3020** Pointer to a variable receiving the alignment for each command.
3021**
3022** gctSIZE_T * ReservedHead
3023** Pointer to a variable receiving the number of reserved bytes at the
3024** head of each command buffer.
3025**
3026** gctSIZE_T * ReservedTail
3027** Pointer to a variable receiving the number of bytes reserved at the
3028** tail of each command buffer.
3029*/
3030gceSTATUS
3031gckHARDWARE_QueryCommandBuffer(
3032 IN gckHARDWARE Hardware,
3033 OUT gctUINT32 * Alignment,
3034 OUT gctUINT32 * ReservedHead,
3035 OUT gctUINT32 * ReservedTail
3036 )
3037{
3038 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
3039
3040 /* Verify the arguments. */
3041 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
3042
3043 if (Alignment != gcvNULL)
3044 {
3045 /* Align every 8 bytes. */
3046 *Alignment = 8;
3047 }
3048
3049 if (ReservedHead != gcvNULL)
3050 {
3051 /* Reserve space for SelectPipe(). */
3052 *ReservedHead = 32;
3053 }
3054
3055 if (ReservedTail != gcvNULL)
3056 {
3057 /* Reserve space for Link(). */
3058 *ReservedTail = 8;
3059 }
3060
3061 /* Success. */
3062 gcmkFOOTER_ARG("*Alignment=%lu *ReservedHead=%lu *ReservedTail=%lu",
3063 gcmOPT_VALUE(Alignment), gcmOPT_VALUE(ReservedHead),
3064 gcmOPT_VALUE(ReservedTail));
3065 return gcvSTATUS_OK;
3066}
3067
3068/*******************************************************************************
3069**
3070** gckHARDWARE_QuerySystemMemory
3071**
3072** Query the command buffer alignment and number of reserved bytes.
3073**
3074** INPUT:
3075**
3076** gckHARDWARE Harwdare
3077** Pointer to an gckHARDWARE object.
3078**
3079** OUTPUT:
3080**
3081** gctSIZE_T * SystemSize
3082** Pointer to a variable that receives the maximum size of the system
3083** memory.
3084**
3085** gctUINT32 * SystemBaseAddress
3086** Poinetr to a variable that receives the base address for system
3087** memory.
3088*/
3089gceSTATUS
3090gckHARDWARE_QuerySystemMemory(
3091 IN gckHARDWARE Hardware,
3092 OUT gctSIZE_T * SystemSize,
3093 OUT gctUINT32 * SystemBaseAddress
3094 )
3095{
3096 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
3097
3098 /* Verify the arguments. */
3099 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
3100
3101 if (SystemSize != gcvNULL)
3102 {
3103 /* Maximum system memory can be 2GB. */
3104 *SystemSize = 1U << 31;
3105 }
3106
3107 if (SystemBaseAddress != gcvNULL)
3108 {
3109 /* Set system memory base address. */
3110 *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)));
3111 }
3112
3113 /* Success. */
3114 gcmkFOOTER_ARG("*SystemSize=%lu *SystemBaseAddress=%lu",
3115 gcmOPT_VALUE(SystemSize), gcmOPT_VALUE(SystemBaseAddress));
3116 return gcvSTATUS_OK;
3117}
3118
3119
3120/*******************************************************************************
3121**
3122** gckHARDWARE_SetMMU
3123**
3124** Set the page table base address.
3125**
3126** INPUT:
3127**
3128** gckHARDWARE Harwdare
3129** Pointer to an gckHARDWARE object.
3130**
3131** gctPOINTER Logical
3132** Logical address of the page table.
3133**
3134** OUTPUT:
3135**
3136** Nothing.
3137*/
3138gceSTATUS
3139gckHARDWARE_SetMMU(
3140 IN gckHARDWARE Hardware,
3141 IN gctPOINTER Logical
3142 )
3143{
3144 gceSTATUS status;
3145 gctUINT32 address = 0;
3146 gctUINT32 idle;
3147 gctUINT32 timer = 0, delay = 1;
3148 gctPHYS_ADDR_T physical;
3149
3150 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x", Hardware, Logical);
3151
3152 /* Verify the arguments. */
3153 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
3154
3155 if (Hardware->mmuVersion == 0)
3156 {
3157 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
3158
3159 /* Convert the logical address into physical address. */
3160 gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, Logical, &physical));
3161
3162 gcmkSAFECASTPHYSADDRT(address, physical);
3163
3164 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
3165 "Setting page table to 0x%08X",
3166 address);
3167
3168 /* Write the AQMemoryFePageTable register. */
3169 gcmkONERROR(
3170 gckOS_WriteRegisterEx(Hardware->os,
3171 Hardware->core,
3172 0x00400,
3173 address));
3174
3175 /* Write the AQMemoryRaPageTable register. */
3176 gcmkONERROR(
3177 gckOS_WriteRegisterEx(Hardware->os,
3178 Hardware->core,
3179 0x00410,
3180 address));
3181
3182 /* Write the AQMemoryTxPageTable register. */
3183 gcmkONERROR(
3184 gckOS_WriteRegisterEx(Hardware->os,
3185 Hardware->core,
3186 0x00404,
3187 address));
3188
3189
3190 /* Write the AQMemoryPePageTable register. */
3191 gcmkONERROR(
3192 gckOS_WriteRegisterEx(Hardware->os,
3193 Hardware->core,
3194 0x00408,
3195 address));
3196
3197 /* Write the AQMemoryPezPageTable register. */
3198 gcmkONERROR(
3199 gckOS_WriteRegisterEx(Hardware->os,
3200 Hardware->core,
3201 0x0040C,
3202 address));
3203 }
3204 else if (Hardware->enableMMU == gcvTRUE)
3205 {
3206 /* Prepared command sequence contains an END,
3207 ** so update lastEnd and store executeCount to END command.
3208 */
3209 gcsHARDWARE_FUNCTION *function = &Hardware->functions[gcvHARDWARE_FUNCTION_MMU];
3210 gctUINT32_PTR endLogical = (gctUINT32_PTR)function->endLogical;
3211
3212 Hardware->lastEnd = function->endAddress;
3213
3214 *(endLogical + 1) = Hardware->executeCount + 1;
3215
3216 /* Execute prepared command sequence. */
3217 gcmkONERROR(gckHARDWARE_Execute(
3218 Hardware,
3219 function->address,
3220 function->bytes
3221 ));
3222
3223#if gcdLINK_QUEUE_SIZE
3224 gckLINKQUEUE_Enqueue(
3225 &Hardware->linkQueue,
3226 function->address,
3227 function->address + function->bytes,
3228 0,
3229 0
3230 );
3231#endif
3232
3233 /* Wait until MMU configure finishes. */
3234 do
3235 {
3236 gckOS_Delay(Hardware->os, delay);
3237
3238 gcmkONERROR(gckOS_ReadRegisterEx(
3239 Hardware->os,
3240 Hardware->core,
3241 0x00004,
3242 &idle));
3243
3244 timer += delay;
3245 delay *= 2;
3246
3247#if gcdGPU_TIMEOUT
3248 if (timer >= Hardware->kernel->timeOut)
3249 {
3250 gckHARDWARE_DumpGPUState(Hardware);
3251 gckCOMMAND_DumpExecutingBuffer(Hardware->kernel->command);
3252
3253 /* Even if hardware is not reset correctly, let software
3254 ** continue to avoid software stuck. Software will timeout again
3255 ** and try to recover GPU in next timeout.
3256 */
3257 gcmkONERROR(gcvSTATUS_DEVICE);
3258 }
3259#endif
3260 }
3261 while (!(((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ));
3262
3263 /* Enable MMU. */
3264 gcmkONERROR(gckOS_WriteRegisterEx(
3265 Hardware->os,
3266 Hardware->core,
3267 0x0018C,
3268 ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (gcvTRUE) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
3269 ));
3270 }
3271
3272 /* Return the status. */
3273 gcmkFOOTER_NO();
3274 return gcvSTATUS_OK;
3275
3276OnError:
3277 /* Return the status. */
3278 gcmkFOOTER();
3279 return status;
3280}
3281
3282/*******************************************************************************
3283**
3284** gckHARDWARE_FlushMMU
3285**
3286** Flush the page table.
3287**
3288** INPUT:
3289**
3290** gckHARDWARE Harwdare
3291** Pointer to an gckHARDWARE object.
3292**
3293** OUTPUT:
3294**
3295** Nothing.
3296*/
3297gceSTATUS
3298gckHARDWARE_FlushMMU(
3299 IN gckHARDWARE Hardware
3300 )
3301{
3302 gceSTATUS status;
3303 gckCOMMAND command;
3304 gctUINT32_PTR buffer;
3305 gctUINT32 bufferSize;
3306 gctPOINTER pointer = gcvNULL;
3307 gctUINT32 flushSize;
3308 gctUINT32 count;
3309 gctPHYS_ADDR_T physical;
3310 gctUINT32 address;
3311
3312 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
3313
3314 /* Verify the arguments. */
3315 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
3316
3317 /* Verify the gckCOMMAND object pointer. */
3318 command = Hardware->kernel->command;
3319
3320 /* Flush the memory controller. */
3321 if (Hardware->mmuVersion == 0)
3322 {
3323 gcmkONERROR(gckCOMMAND_Reserve(
3324 command, 8, &pointer, &bufferSize
3325 ));
3326
3327 buffer = (gctUINT32_PTR) pointer;
3328
3329 buffer[0]
3330 = ((((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)))
3331 | ((((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)))
3332 | ((((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)));
3333
3334 buffer[1]
3335 = ((((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)))
3336 | ((((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)))
3337 | ((((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)))
3338 | ((((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)))
3339 | ((((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)));
3340
3341 gcmkONERROR(gckCOMMAND_Execute(command, 8));
3342 }
3343 else
3344 {
3345 /* semaphore stall cmd size */
3346 gctUINT32 stCmds = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX) ? 0 : 4;
3347
3348 flushSize = (stCmds + 18) * 4;
3349
3350 gcmkONERROR(gckCOMMAND_Reserve(
3351 command, flushSize, &pointer, &bufferSize
3352 ));
3353
3354 buffer = (gctUINT32_PTR) pointer;
3355
3356 count = ((gctUINT)bufferSize - flushSize + 7) >> 3;
3357
3358 gcmkONERROR(gckOS_GetPhysicalAddress(command->os, buffer, &physical));
3359
3360 gcmkSAFECASTPHYSADDRT(address, physical);
3361
3362 if (stCmds)
3363 {
3364 /* Arm the PE-FE Semaphore. */
3365 *buffer++
3366 = ((((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)))
3367 | ((((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)))
3368 | ((((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)));
3369
3370 *buffer++
3371 = ((((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)))
3372 | ((((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)));
3373
3374 /* STALL FE until PE is done flushing. */
3375 *buffer++
3376 = ((((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)));
3377
3378 *buffer++
3379 = ((((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)))
3380 | ((((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)));
3381 }
3382
3383 /* Flush cache. */
3384 *buffer++
3385 = ((((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)))
3386 | ((((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)))
3387 | ((((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)));
3388
3389 *buffer++
3390 = ((((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)))
3391 | ((((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)))
3392 | ((((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)))
3393 | ((((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)))
3394 | ((((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)));
3395
3396 /* Flush VTS in separate command */
3397 *buffer++
3398 = ((((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)))
3399 | ((((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)))
3400 | ((((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)));
3401
3402 *buffer++
3403 = ((((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)));
3404
3405 /* Arm the PE-FE Semaphore. */
3406 *buffer++
3407 = ((((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)))
3408 | ((((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)))
3409 | ((((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)));
3410
3411 *buffer++
3412 = ((((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)))
3413 | ((((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)));
3414
3415 /* STALL FE until PE is done flushing. */
3416 *buffer++
3417 = ((((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)));
3418
3419 *buffer++
3420 = ((((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)))
3421 | ((((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)));
3422
3423 /* LINK to next slot to flush FE FIFO. */
3424 *buffer++
3425 = ((((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)))
3426 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
3427
3428 *buffer++
3429 = address + (stCmds + 10) * gcmSIZEOF(gctUINT32);
3430
3431 /* Flush MMU cache. */
3432 *buffer++
3433 = ((((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)))
3434 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3435 | ((((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)));
3436
3437 *buffer++
3438 = (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))));
3439
3440 /* Arm the PE-FE Semaphore. */
3441 *buffer++
3442 = ((((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)))
3443 | ((((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)))
3444 | ((((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)));
3445
3446 *buffer++
3447 = ((((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)))
3448 | ((((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)));
3449
3450 /* STALL FE until PE is done flushing. */
3451 *buffer++
3452 = ((((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)));
3453
3454 *buffer++
3455 = ((((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)))
3456 | ((((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)));
3457
3458 /* LINK to next slot to flush FE FIFO. */
3459 *buffer++
3460 = ((((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)))
3461 | ((((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)));
3462
3463 *buffer++
3464 = address + flushSize;
3465
3466 gcmkONERROR(gckCOMMAND_Execute(command, flushSize));
3467 }
3468
3469 /* Success. */
3470 gcmkFOOTER_NO();
3471 return gcvSTATUS_OK;
3472
3473OnError:
3474
3475 /* Return the status. */
3476 gcmkFOOTER();
3477 return status;
3478}
3479
3480gceSTATUS
3481gckHARDWARE_SetMMUStates(
3482 IN gckHARDWARE Hardware,
3483 IN gctPOINTER MtlbAddress,
3484 IN gceMMU_MODE Mode,
3485 IN gctPOINTER SafeAddress,
3486 IN gctPOINTER Logical,
3487 IN OUT gctUINT32 * Bytes
3488 )
3489{
3490 gceSTATUS status;
3491 gctUINT32 config, address;
3492 gctUINT32 extMtlb, extSafeAddrss, configEx = 0;
3493 gctPHYS_ADDR_T physical;
3494 gctUINT32_PTR buffer;
3495 gctBOOL ace;
3496 gctUINT32 reserveBytes = 16 + 4 * 4;
3497
3498 gctBOOL config2D;
3499
3500 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
3501
3502 /* Verify the arguments. */
3503 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
3504 gcmkVERIFY_ARGUMENT(Hardware->mmuVersion != 0);
3505
3506 ace = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_ACE);
3507
3508 if (ace)
3509 {
3510 reserveBytes += 8;
3511 }
3512
3513 config2D = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_3D)
3514 && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_PIPE_2D);
3515
3516 if (config2D)
3517 {
3518 reserveBytes +=
3519 /* Pipe Select. */
3520 4 * 4
3521 /* Configure MMU States. */
3522 + 4 * 4
3523 /* Semaphore stall */
3524 + 4 * 8;
3525
3526 if (ace)
3527 {
3528 reserveBytes += 8;
3529 }
3530 }
3531
3532 /* Convert logical address into physical address. */
3533 gcmkONERROR(
3534 gckOS_GetPhysicalAddress(Hardware->os, MtlbAddress, &physical));
3535
3536 config = (gctUINT32)(physical & 0xFFFFFFFF);
3537 extMtlb = (gctUINT32)(physical >> 32);
3538
3539 gcmkONERROR(
3540 gckOS_GetPhysicalAddress(Hardware->os, SafeAddress, &physical));
3541
3542 address = (gctUINT32)(physical & 0xFFFFFFFF);
3543 extSafeAddrss = (gctUINT32)(physical >> 32);
3544
3545 if (address & 0x3F)
3546 {
3547 gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
3548 }
3549
3550 switch (Mode)
3551 {
3552 case gcvMMU_MODE_1K:
3553 if (config & 0x3FF)
3554 {
3555 gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
3556 }
3557
3558 config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
3559
3560 break;
3561
3562 case gcvMMU_MODE_4K:
3563 if (config & 0xFFF)
3564 {
3565 gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
3566 }
3567
3568 config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
3569
3570 break;
3571
3572 default:
3573 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
3574 }
3575
3576 if (ace)
3577 {
3578 configEx = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (extSafeAddrss) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
3579 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (extMtlb) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)));
3580 }
3581
3582 if (Logical != gcvNULL)
3583 {
3584 buffer = Logical;
3585
3586 *buffer++
3587 = ((((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)))
3588 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3589 | ((((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)));
3590
3591 *buffer++ = config;
3592
3593 *buffer++
3594 = ((((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)))
3595 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3596 | ((((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)));
3597
3598 *buffer++ = address;
3599
3600 if (ace)
3601 {
3602 *buffer++
3603 = ((((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)))
3604 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0068) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3605 | ((((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)));
3606
3607 *buffer++
3608 = configEx;
3609 }
3610
3611 do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);;
3612
3613 if (config2D)
3614 {
3615 /* LoadState(AQPipeSelect, 1), pipe. */
3616 *buffer++
3617 = ((((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)))
3618 | ((((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)))
3619 | ((((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)));
3620
3621 *buffer++ = 0x1;
3622
3623 *buffer++
3624 = ((((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)))
3625 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3626 | ((((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)));
3627
3628 *buffer++ = config;
3629
3630 *buffer++
3631 = ((((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)))
3632 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0060) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3633 | ((((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)));
3634
3635 *buffer++ = address;
3636
3637 if (ace)
3638 {
3639 *buffer++
3640 = ((((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)))
3641 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0068) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3642 | ((((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)));
3643
3644 *buffer++
3645 = configEx;
3646 }
3647
3648 do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);;
3649
3650 /* LoadState(AQPipeSelect, 1), pipe. */
3651 *buffer++
3652 = ((((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)))
3653 | ((((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)))
3654 | ((((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)));
3655
3656 *buffer++ = 0x0;
3657
3658 do{*buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E02) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x09 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))); *buffer++ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8))) | (((gctUINT32) (0x07 & ((gctUINT32) ((((1 ? 12:8) - (0 ? 12:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:8) - (0 ? 12:8) + 1))))))) << (0 ? 12:8)));} while(0);;
3659 }
3660
3661 }
3662
3663 if (Bytes != gcvNULL)
3664 {
3665 *Bytes = reserveBytes;
3666 }
3667
3668 /* Return the status. */
3669 gcmkFOOTER_NO();
3670 return status;
3671
3672OnError:
3673 /* Return the status. */
3674 gcmkFOOTER();
3675 return status;
3676}
3677
3678#if gcdPROCESS_ADDRESS_SPACE
3679/*******************************************************************************
3680**
3681** gckHARDWARE_ConfigMMU
3682**
3683** Append a MMU Configuration command sequence at the specified location in the command
3684** queue. That command sequence consists of mmu configuration, LINK and WAIT/LINK.
3685** LINK is fetched and paresed with new mmu configuration.
3686**
3687** If MMU Configuration is not changed between commit, change last WAIT/LINK to
3688** link to ENTRY.
3689**
3690** -+-----------+-----------+-----------------------------------------
3691** | WAIT/LINK | WAIT/LINK |
3692** -+-----------+-----------+-----------------------------------------
3693** | /|\
3694** \|/ |
3695** +--------------------+
3696** | ENTRY | ... | LINK |
3697** +--------------------+
3698**
3699** If MMU Configuration is changed between commit, change last WAIT/LINK to
3700** link to MMU CONFIGURATION command sequence, and there are an EVNET and
3701** an END at the end of this command sequence, when interrupt handler
3702** receives this event, it will start FE at ENTRY to continue the command
3703** buffer execution.
3704**
3705** -+-----------+-------------------+---------+---------+-----------+--
3706** | WAIT/LINK | MMU CONFIGURATION | EVENT | END | WAIT/LINK |
3707** -+-----------+-------------------+---------+---------+-----------+--
3708** | /|\ /|\
3709** +-------------+ |
3710** +--------------------+
3711** | ENTRY | ... | LINK |
3712** +--------------------+
3713** INPUT:
3714**
3715** gckHARDWARE Hardware
3716** Pointer to an gckHARDWARE object.
3717**
3718** gctPOINTER Logical
3719** Pointer to the current location inside the command queue to append
3720** command sequence at or gcvNULL just to query the size of the
3721** command sequence.
3722**
3723** gctPOINTER MtlbLogical
3724** Pointer to the current Master TLB.
3725**
3726** gctUINT32 Offset
3727** Offset into command buffer required for alignment.
3728**
3729** gctSIZE_T * Bytes
3730** Pointer to the number of bytes available for the command
3731** sequence. If 'Logical' is gcvNULL, this argument will be ignored.
3732**
3733** OUTPUT:
3734**
3735** gctSIZE_T * Bytes
3736** Pointer to a variable that will receive the number of bytes required
3737** by the command sequence. If 'Bytes' is gcvNULL, nothing will
3738** be returned.
3739**
3740** gctUINT32 * WaitLinkOffset
3741** Pointer to a variable that will receive the offset of the WAIT/LINK command
3742** from the specified logcial pointer.
3743** If 'WaitLinkOffset' is gcvNULL nothing will be returned.
3744**
3745** gctSIZE_T * WaitLinkBytes
3746** Pointer to a variable that will receive the number of bytes used by
3747** the WAIT command.
3748** If 'WaitLinkBytes' is gcvNULL nothing will be returned.
3749*/
3750gceSTATUS
3751gckHARDWARE_ConfigMMU(
3752 IN gckHARDWARE Hardware,
3753 IN gctPOINTER Logical,
3754 IN gctPOINTER MtlbLogical,
3755 IN gctUINT32 Offset,
3756 IN OUT gctSIZE_T * Bytes,
3757 OUT gctSIZE_T * WaitLinkOffset,
3758 OUT gctSIZE_T * WaitLinkBytes
3759 )
3760{
3761 gceSTATUS status;
3762 gctSIZE_T bytes, bytesAligned;
3763 gctUINT32 config;
3764 gctUINT32_PTR buffer = (gctUINT32_PTR) Logical;
3765 gctUINT32 physical;
3766 gctUINT32 event;
3767 gctSIZE_T stCmds; /* semaphore stall cmd size */;
3768
3769 gcmkHEADER_ARG("Hardware=0x%08X Logical=0x%08x MtlbLogical=0x%08X",
3770 Hardware, Logical, MtlbLogical);
3771
3772 stCmds = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX) ? 0 : 4;
3773
3774 bytes
3775 /* Semaphore stall states. */
3776 = stCmds * 4
3777 /* Flush cache states. */
3778 + 20 * 4
3779 /* MMU configuration states. */
3780 + 6 * 4
3781 /* EVENT. */
3782 + 2 * 4
3783 /* END. */
3784 + 2 * 4
3785 /* WAIT/LINK. */
3786 + 4 * 4;
3787
3788 /* Compute number of bytes required. */
3789 bytesAligned = gcmALIGN(Offset + bytes, 8) - Offset;
3790
3791 if (buffer != gcvNULL)
3792 {
3793 if (MtlbLogical == gcvNULL)
3794 {
3795 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
3796 }
3797
3798 /* Get physical address of this command buffer segment. */
3799 gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, buffer, &physical));
3800
3801 /* Get physical address of Master TLB. */
3802 gcmkONERROR(gckOS_GetPhysicalAddress(Hardware->os, MtlbLogical, &config));
3803
3804 config |= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
3805 | ((((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)));
3806
3807 if (stCmds)
3808 {
3809 /* Arm the PE-FE Semaphore. */
3810 *buffer++
3811 = ((((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)))
3812 | ((((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)))
3813 | ((((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)));
3814
3815 *buffer++
3816 = ((((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)))
3817 | ((((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)));
3818
3819 /* STALL FE until PE is done flushing. */
3820 *buffer++
3821 = ((((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)));
3822
3823 *buffer++
3824 = ((((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)))
3825 | ((((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)));
3826 }
3827
3828 /* Flush cache. */
3829 *buffer++
3830 = ((((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)))
3831 | ((((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)))
3832 | ((((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)));
3833
3834 *buffer++
3835 = ((((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)))
3836 | ((((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)))
3837 | ((((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)))
3838 | ((((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)))
3839 | ((((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)))
3840 | ((((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)));
3841
3842 /* Flush VTS in separate command */
3843 *buffer++
3844 = ((((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)))
3845 | ((((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)))
3846 | ((((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)));
3847
3848 *buffer++
3849 = ((((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)));
3850
3851 /* Flush tile status cache. */
3852 *buffer++
3853 = ((((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)))
3854 | ((((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)))
3855 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
3856
3857 *buffer++
3858 = ((((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)));
3859
3860 /* Arm the PE-FE Semaphore. */
3861 *buffer++
3862 = ((((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)))
3863 | ((((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)))
3864 | ((((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)));
3865
3866 *buffer++
3867 = ((((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)))
3868 | ((((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)));
3869
3870 /* STALL FE until PE is done flushing. */
3871 *buffer++
3872 = ((((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)));
3873
3874 *buffer++
3875 = ((((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)))
3876 | ((((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)));
3877
3878 /* LINK to next slot to flush FE FIFO. */
3879 *buffer++
3880 = ((((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)))
3881 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
3882
3883 *buffer++
3884 = physical + (stCmds + 12) * gcmSIZEOF(gctUINT32);
3885
3886 /* Configure MMU. */
3887 *buffer++
3888 = ((((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)))
3889 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3890 | ((((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)));
3891
3892 *buffer++
3893 = (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))));
3894
3895 /* Arm the PE-FE Semaphore. */
3896 *buffer++
3897 = ((((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)))
3898 | ((((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)))
3899 | ((((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)));
3900
3901 *buffer++
3902 = ((((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)))
3903 | ((((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)));
3904
3905 /* STALL FE until PE is done flushing. */
3906 *buffer++
3907 = ((((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)));
3908
3909 *buffer++
3910 = ((((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)))
3911 | ((((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)));
3912
3913 /* LINK to next slot to flush FE FIFO. */
3914 *buffer++
3915 = ((((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)))
3916 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
3917
3918 *buffer++
3919 = physical + (stCmds + 20) * 4;
3920
3921 *buffer++
3922 = ((((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)))
3923 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
3924 | ((((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)));
3925
3926 *buffer++
3927 = config;
3928
3929 /* Arm the PE-FE Semaphore. */
3930 *buffer++
3931 = ((((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)))
3932 | ((((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)))
3933 | ((((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)));
3934
3935 *buffer++
3936 = ((((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)))
3937 | ((((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)));
3938
3939 /* STALL FE until PE is done flushing. */
3940 *buffer++
3941 = ((((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)));
3942
3943 *buffer++
3944 = ((((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)))
3945 | ((((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)));
3946
3947 /* Event 29. */
3948 *buffer++
3949 = ((((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)))
3950 | ((((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)))
3951 | ((((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)));
3952
3953 event = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)));
3954 event = ((((gctUINT32) (event)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0))) | (((gctUINT32) ((gctUINT32) (29) & ((gctUINT32) ((((1 ? 4:0) - (0 ? 4:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:0) - (0 ? 4:0) + 1))))))) << (0 ? 4:0)));
3955
3956 *buffer++
3957 = event;
3958
3959 /* Append END. */
3960 *buffer++
3961 = ((((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)));
3962 }
3963
3964 if (Bytes != gcvNULL)
3965 {
3966 *Bytes = bytesAligned;
3967 }
3968
3969 if (WaitLinkOffset != gcvNULL)
3970 {
3971 *WaitLinkOffset = bytes - 4 * 4;
3972 }
3973
3974 if (WaitLinkBytes != gcvNULL)
3975 {
3976 *WaitLinkBytes = 4 * 4;
3977 }
3978
3979 gcmkFOOTER_NO();
3980 return gcvSTATUS_OK;
3981
3982OnError:
3983 gcmkFOOTER();
3984 return status;
3985}
3986#endif
3987
3988/*******************************************************************************
3989**
3990** gckHARDWARE_BuildVirtualAddress
3991**
3992** Build a virtual address.
3993**
3994** INPUT:
3995**
3996** gckHARDWARE Harwdare
3997** Pointer to an gckHARDWARE object.
3998**
3999** gctUINT32 Index
4000** Index into page table.
4001**
4002** gctUINT32 Offset
4003** Offset into page.
4004**
4005** OUTPUT:
4006**
4007** gctUINT32 * Address
4008** Pointer to a variable receiving te hardware address.
4009*/
4010gceSTATUS
4011gckHARDWARE_BuildVirtualAddress(
4012 IN gckHARDWARE Hardware,
4013 IN gctUINT32 Index,
4014 IN gctUINT32 Offset,
4015 OUT gctUINT32 * Address
4016 )
4017{
4018 gcmkHEADER_ARG("Hardware=0x%x Index=%u Offset=%u", Hardware, Index, Offset);
4019
4020 /* Verify the arguments. */
4021 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
4022 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
4023
4024 /* Build virtual address. */
4025 *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)))
4026 | ((((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)));
4027
4028 /* Success. */
4029 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
4030 return gcvSTATUS_OK;
4031}
4032
4033gceSTATUS
4034gckHARDWARE_GetIdle(
4035 IN gckHARDWARE Hardware,
4036 IN gctBOOL Wait,
4037 OUT gctUINT32 * Data
4038 )
4039{
4040 gceSTATUS status;
4041 gctUINT32 idle = 0;
4042 gctINT retry, poll, pollCount;
4043 gctUINT32 address;
4044
4045 gcmkHEADER_ARG("Hardware=0x%x Wait=%d", Hardware, Wait);
4046
4047 /* Verify the arguments. */
4048 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
4049 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
4050
4051
4052 /* If we have to wait, try 100 polls per millisecond. */
4053 pollCount = Wait ? 100 : 1;
4054
4055 /* At most, try for 1 second. */
4056 for (retry = 0; retry < 1000; ++retry)
4057 {
4058 /* If we have to wait, try 100 polls per millisecond. */
4059 for (poll = pollCount; poll > 0; --poll)
4060 {
4061 /* Read register. */
4062 gcmkONERROR(
4063 gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
4064
4065 /* Read the current FE address. */
4066 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
4067 Hardware->core,
4068 0x00664,
4069 &address));
4070
4071
4072 /* See if we have to wait for FE idle. */
4073 if (_IsGPUIdle(idle)
4074 && (address == Hardware->lastEnd + 8)
4075 )
4076 {
4077 /* FE is idle. */
4078 break;
4079 }
4080 }
4081
4082 /* Check if we need to wait for FE and FE is busy. */
4083 if (Wait && !_IsGPUIdle(idle))
4084 {
4085 /* Wait a little. */
4086 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
4087 "%s: Waiting for idle: 0x%08X",
4088 __FUNCTION__, idle);
4089
4090 gcmkVERIFY_OK(gckOS_Delay(Hardware->os, 1));
4091 }
4092 else
4093 {
4094 break;
4095 }
4096 }
4097
4098 /* Return idle to caller. */
4099 *Data = idle;
4100
4101#if defined(EMULATOR)
4102 /* Wait a little while until CModel FE gets END.
4103 * END is supposed to be appended by caller.
4104 */
4105 gckOS_Delay(gcvNULL, 100);
4106#endif
4107
4108 /* Success. */
4109 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
4110 return gcvSTATUS_OK;
4111
4112OnError:
4113 /* Return the status. */
4114 gcmkFOOTER();
4115 return status;
4116}
4117
4118/* Flush the caches. */
4119gceSTATUS
4120gckHARDWARE_Flush(
4121 IN gckHARDWARE Hardware,
4122 IN gceKERNEL_FLUSH Flush,
4123 IN gctPOINTER Logical,
4124 IN OUT gctUINT32 * Bytes
4125 )
4126{
4127 gctUINT32 pipe;
4128 gctUINT32 flush = 0;
4129 gctUINT32 flushVST = 0;
4130 gctBOOL flushTileStatus;
4131 gctUINT32_PTR logical = (gctUINT32_PTR) Logical;
4132 gceSTATUS status;
4133
4134 gcmkHEADER_ARG("Hardware=0x%x Flush=0x%x Logical=0x%x *Bytes=%lu",
4135 Hardware, Flush, Logical, gcmOPT_VALUE(Bytes));
4136
4137 /* Verify the arguments. */
4138 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
4139
4140 /* Get current pipe. */
4141 pipe = Hardware->kernel->command->pipeSelect;
4142
4143 /* Flush tile status cache. */
4144 flushTileStatus = Flush & gcvFLUSH_TILE_STATUS;
4145
4146 /* Flush 3D color cache. */
4147 if ((Flush & gcvFLUSH_COLOR) && (pipe == 0x0))
4148 {
4149 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)));
4150 }
4151
4152 /* Flush 3D depth cache. */
4153 if ((Flush & gcvFLUSH_DEPTH) && (pipe == 0x0))
4154 {
4155 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)));
4156 }
4157
4158 /* Flush 3D texture cache. */
4159 if ((Flush & gcvFLUSH_TEXTURE) && (pipe == 0x0))
4160 {
4161 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)));
4162 flushVST = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
4163 }
4164
4165 /* Flush 2D cache. */
4166 if ((Flush & gcvFLUSH_2D) && (pipe == 0x1))
4167 {
4168 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)));
4169 }
4170
4171
4172 /* See if there is a valid flush. */
4173 if ((flush == 0) && (flushTileStatus == gcvFALSE))
4174 {
4175 if (Bytes != gcvNULL)
4176 {
4177 /* No bytes required. */
4178 *Bytes = 0;
4179 }
4180 }
4181 else
4182 {
4183 gctUINT32 reserveBytes = 0;
4184 gctBOOL txCacheFix = gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_TEX_CACHE_FLUSH_FIX)
4185 ? gcvTRUE : gcvFALSE;
4186
4187 /* Determine reserve bytes. */
4188 if (!txCacheFix)
4189 {
4190 /* Semaphore/Stall */
4191 reserveBytes += 4 * gcmSIZEOF(gctUINT32);
4192 }
4193
4194 if (flush)
4195 {
4196 reserveBytes += 2 * gcmSIZEOF(gctUINT32);
4197 }
4198
4199 if (flushVST)
4200 {
4201 reserveBytes += 2 * gcmSIZEOF(gctUINT32);
4202 }
4203
4204 if (flushTileStatus)
4205 {
4206 reserveBytes += 2 * gcmSIZEOF(gctUINT32);
4207 }
4208
4209 /* Semaphore/Stall */
4210 reserveBytes += 4 * gcmSIZEOF(gctUINT32);
4211
4212 /* Copy to command queue. */
4213 if (Logical != gcvNULL)
4214 {
4215 if (*Bytes < reserveBytes)
4216 {
4217 /* Command queue too small. */
4218 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
4219 }
4220
4221 if (!txCacheFix)
4222 {
4223 /* Semaphore. */
4224 *logical++
4225 = ((((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)))
4226 | ((((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)))
4227 | ((((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)));
4228
4229 *logical++
4230 = ((((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)))
4231 | ((((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)));
4232
4233 /* Stall. */
4234 *logical++
4235 = ((((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)));
4236
4237 *logical++
4238 = ((((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)))
4239 | ((((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)));
4240 }
4241
4242 if (flush)
4243 {
4244 /* Append LOAD_STATE to AQFlush. */
4245 *logical++
4246 = ((((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)))
4247 | ((((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)))
4248 | ((((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)));
4249
4250 *logical++ = flush;
4251
4252 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: FLUSH 0x%x", logical - 1, flush);
4253 }
4254
4255 if (flushVST)
4256 {
4257 /* Append LOAD_STATE to AQFlush. */
4258 *logical++
4259 = ((((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)))
4260 | ((((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)))
4261 | ((((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)));
4262
4263 *logical++ = flushVST;
4264
4265 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "0x%x: FLUSH 0x%x", logical - 1, flush);
4266 }
4267
4268 if (flushTileStatus)
4269 {
4270 *logical++
4271 = ((((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)))
4272 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0594) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
4273 | ((((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)));
4274
4275 *logical++
4276 = ((((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)));
4277
4278 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
4279 "0x%x: FLUSH TILE STATUS 0x%x", logical - 1, logical[-1]);
4280 }
4281
4282 /* Semaphore. */
4283 *logical++
4284 = ((((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)))
4285 | ((((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)))
4286 | ((((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)));
4287
4288 *logical++
4289 = ((((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)))
4290 | ((((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)));
4291
4292 /* Stall. */
4293 *logical++
4294 = ((((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)));
4295
4296 *logical++
4297 = ((((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)))
4298 | ((((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)));
4299 }
4300
4301 if (Bytes != gcvNULL)
4302 {
4303 /* bytes required. */
4304 *Bytes = reserveBytes;
4305 }
4306 }
4307
4308 /* Success. */
4309 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
4310 return gcvSTATUS_OK;
4311
4312OnError:
4313 /* Return the status. */
4314 gcmkFOOTER();
4315 return status;
4316}
4317
4318gceSTATUS
4319gckHARDWARE_SetFastClear(
4320 IN gckHARDWARE Hardware,
4321 IN gctINT Enable,
4322 IN gctINT Compression
4323 )
4324{
4325 return gcvSTATUS_OK;
4326}
4327
4328typedef enum
4329{
4330 gcvPOWER_FLAG_INITIALIZE = 1 << 0,
4331 gcvPOWER_FLAG_STALL = 1 << 1,
4332 gcvPOWER_FLAG_STOP = 1 << 2,
4333 gcvPOWER_FLAG_START = 1 << 3,
4334 gcvPOWER_FLAG_RELEASE = 1 << 4,
4335 gcvPOWER_FLAG_DELAY = 1 << 5,
4336 gcvPOWER_FLAG_SAVE = 1 << 6,
4337 gcvPOWER_FLAG_ACQUIRE = 1 << 7,
4338 gcvPOWER_FLAG_POWER_OFF = 1 << 8,
4339 gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
4340 gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
4341}
4342gcePOWER_FLAGS;
4343
4344#if gcmIS_DEBUG(gcdDEBUG_TRACE)
4345static gctCONST_STRING
4346_PowerEnum(gceCHIPPOWERSTATE State)
4347{
4348 const gctCONST_STRING states[] =
4349 {
4350 gcmSTRING(gcvPOWER_ON),
4351 gcmSTRING(gcvPOWER_OFF),
4352 gcmSTRING(gcvPOWER_IDLE),
4353 gcmSTRING(gcvPOWER_SUSPEND),
4354 gcmSTRING(gcvPOWER_SUSPEND_ATPOWERON),
4355 gcmSTRING(gcvPOWER_OFF_ATPOWERON),
4356 gcmSTRING(gcvPOWER_IDLE_BROADCAST),
4357 gcmSTRING(gcvPOWER_SUSPEND_BROADCAST),
4358 gcmSTRING(gcvPOWER_OFF_BROADCAST),
4359 gcmSTRING(gcvPOWER_OFF_RECOVERY),
4360 gcmSTRING(gcvPOWER_OFF_TIMEOUT),
4361 gcmSTRING(gcvPOWER_ON_AUTO)
4362 };
4363
4364 if ((State >= gcvPOWER_ON) && (State <= gcvPOWER_ON_AUTO))
4365 {
4366 return states[State - gcvPOWER_ON];
4367 }
4368
4369 return "unknown";
4370}
4371#endif
4372
4373/*******************************************************************************
4374**
4375** gckHARDWARE_SetPowerManagementState
4376**
4377** Set GPU to a specified power state.
4378**
4379** INPUT:
4380**
4381** gckHARDWARE Harwdare
4382** Pointer to an gckHARDWARE object.
4383**
4384** gceCHIPPOWERSTATE State
4385** Power State.
4386**
4387*/
4388gceSTATUS
4389gckHARDWARE_SetPowerManagementState(
4390 IN gckHARDWARE Hardware,
4391 IN gceCHIPPOWERSTATE State
4392 )
4393{
4394 gceSTATUS status;
4395 gckCOMMAND command = gcvNULL;
4396 gckOS os;
4397 gctUINT flag, clock;
4398 gctPOINTER buffer;
4399 gctUINT32 bytes, requested;
4400 gctBOOL acquired = gcvFALSE;
4401 gctBOOL mutexAcquired = gcvFALSE;
4402 gctBOOL stall = gcvTRUE;
4403 gctBOOL broadcast = gcvFALSE;
4404#if gcdPOWEROFF_TIMEOUT
4405 gctBOOL timeout = gcvFALSE;
4406 gctBOOL isAfter = gcvFALSE;
4407 gctUINT32 currentTime;
4408#endif
4409 gctUINT32 process, thread;
4410 gctBOOL commitEntered = gcvFALSE;
4411 gctBOOL commandStarted = gcvFALSE;
4412 gctBOOL isrStarted = gcvFALSE;
4413
4414#if gcdENABLE_PROFILING
4415 gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
4416 initTime, offTime, startTime, totalTime;
4417#endif
4418 gctBOOL global = gcvFALSE;
4419 gctBOOL globalAcquired = gcvFALSE;
4420 gctBOOL configMmu = gcvFALSE;
4421
4422 /* State transition flags. */
4423 static const gctUINT flags[4][4] =
4424 {
4425 /* gcvPOWER_ON */
4426 { /* ON */ 0,
4427 /* OFF */ gcvPOWER_FLAG_ACQUIRE |
4428 gcvPOWER_FLAG_STALL |
4429 gcvPOWER_FLAG_STOP |
4430 gcvPOWER_FLAG_POWER_OFF |
4431 gcvPOWER_FLAG_CLOCK_OFF,
4432 /* IDLE */ gcvPOWER_FLAG_ACQUIRE |
4433 gcvPOWER_FLAG_STALL,
4434 /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
4435 gcvPOWER_FLAG_STALL |
4436 gcvPOWER_FLAG_STOP |
4437 gcvPOWER_FLAG_CLOCK_OFF,
4438 },
4439
4440 /* gcvPOWER_OFF */
4441 { /* ON */ gcvPOWER_FLAG_INITIALIZE |
4442 gcvPOWER_FLAG_START |
4443 gcvPOWER_FLAG_RELEASE |
4444 gcvPOWER_FLAG_DELAY,
4445 /* OFF */ 0,
4446 /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
4447 gcvPOWER_FLAG_START |
4448 gcvPOWER_FLAG_DELAY,
4449 /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
4450 gcvPOWER_FLAG_CLOCK_OFF,
4451 },
4452
4453 /* gcvPOWER_IDLE */
4454 { /* ON */ gcvPOWER_FLAG_RELEASE,
4455 /* OFF */ gcvPOWER_FLAG_STOP |
4456 gcvPOWER_FLAG_POWER_OFF |
4457 gcvPOWER_FLAG_CLOCK_OFF,
4458 /* IDLE */ 0,
4459 /* SUSPEND */ gcvPOWER_FLAG_STOP |
4460 gcvPOWER_FLAG_CLOCK_OFF,
4461 },
4462
4463 /* gcvPOWER_SUSPEND */
4464 { /* ON */ gcvPOWER_FLAG_START |
4465 gcvPOWER_FLAG_RELEASE |
4466 gcvPOWER_FLAG_DELAY |
4467 gcvPOWER_FLAG_CLOCK_ON,
4468 /* OFF */ gcvPOWER_FLAG_SAVE |
4469 gcvPOWER_FLAG_POWER_OFF |
4470 gcvPOWER_FLAG_CLOCK_OFF,
4471 /* IDLE */ gcvPOWER_FLAG_START |
4472 gcvPOWER_FLAG_DELAY |
4473 gcvPOWER_FLAG_CLOCK_ON,
4474 /* SUSPEND */ 0,
4475 },
4476 };
4477
4478 /* Clocks. */
4479 static const gctUINT clocks[4] =
4480 {
4481 /* gcvPOWER_ON */
4482 ((((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))) |
4483 ((((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))) |
4484 ((((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))) |
4485 ((((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))),
4486
4487 /* gcvPOWER_OFF */
4488 ((((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))) |
4489 ((((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))) |
4490 ((((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))) |
4491 ((((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))),
4492
4493 /* gcvPOWER_IDLE */
4494 ((((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))) |
4495 ((((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))) |
4496 ((((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))) |
4497 ((((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))),
4498
4499 /* gcvPOWER_SUSPEND */
4500 ((((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))) |
4501 ((((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))) |
4502 ((((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))) |
4503 ((((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))),
4504 };
4505
4506 gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
4507#if gcmIS_DEBUG(gcdDEBUG_TRACE)
4508 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
4509 "Switching to power state %d(%s)",
4510 State, _PowerEnum(State));
4511#endif
4512
4513 /* Verify the arguments. */
4514 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
4515
4516 /* Get the gckOS object pointer. */
4517 os = Hardware->os;
4518 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
4519
4520 /* Get the gckCOMMAND object pointer. */
4521 gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
4522 command = Hardware->kernel->command;
4523 gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
4524
4525 /* Start profiler. */
4526 gcmkPROFILE_INIT(freq, time);
4527
4528 /* Convert the broadcast power state. */
4529 switch (State)
4530 {
4531 case gcvPOWER_SUSPEND_ATPOWERON:
4532 /* Convert to SUSPEND and don't wait for STALL. */
4533 State = gcvPOWER_SUSPEND;
4534 stall = gcvFALSE;
4535 break;
4536
4537 case gcvPOWER_OFF_ATPOWERON:
4538 /* Convert to OFF and don't wait for STALL. */
4539 State = gcvPOWER_OFF;
4540 stall = gcvFALSE;
4541 break;
4542
4543 case gcvPOWER_IDLE_BROADCAST:
4544 /* Convert to IDLE and note we are inside broadcast. */
4545 State = gcvPOWER_IDLE;
4546 broadcast = gcvTRUE;
4547 break;
4548
4549 case gcvPOWER_SUSPEND_BROADCAST:
4550 /* Convert to SUSPEND and note we are inside broadcast. */
4551 State = gcvPOWER_SUSPEND;
4552 broadcast = gcvTRUE;
4553 break;
4554
4555 case gcvPOWER_OFF_BROADCAST:
4556 /* Convert to OFF and note we are inside broadcast. */
4557 State = gcvPOWER_OFF;
4558 broadcast = gcvTRUE;
4559 break;
4560
4561 case gcvPOWER_OFF_RECOVERY:
4562 /* Convert to OFF and note we are inside recovery. */
4563 State = gcvPOWER_OFF;
4564 stall = gcvFALSE;
4565 broadcast = gcvTRUE;
4566 break;
4567
4568 case gcvPOWER_ON_AUTO:
4569 /* Convert to ON and note we are inside recovery. */
4570 State = gcvPOWER_ON;
4571 break;
4572
4573 case gcvPOWER_ON:
4574 case gcvPOWER_IDLE:
4575 case gcvPOWER_SUSPEND:
4576 case gcvPOWER_OFF:
4577 /* Mark as global power management. */
4578 global = gcvTRUE;
4579 break;
4580
4581#if gcdPOWEROFF_TIMEOUT
4582 case gcvPOWER_OFF_TIMEOUT:
4583 /* Convert to OFF and note we are inside broadcast. */
4584 State = gcvPOWER_OFF;
4585 broadcast = gcvTRUE;
4586 /* Check time out */
4587 timeout = gcvTRUE;
4588 break;
4589#endif
4590
4591 default:
4592 break;
4593 }
4594
4595 if (Hardware->powerManagement == gcvFALSE
4596 && State != gcvPOWER_ON
4597 )
4598 {
4599 gcmkFOOTER_NO();
4600 return gcvSTATUS_OK;
4601 }
4602
4603 /* Get current process and thread IDs. */
4604 gcmkONERROR(gckOS_GetProcessID(&process));
4605 gcmkONERROR(gckOS_GetThreadID(&thread));
4606
4607 if (broadcast)
4608 {
4609 /* Try to acquire the power mutex. */
4610 status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
4611
4612 if (status == gcvSTATUS_TIMEOUT)
4613 {
4614 /* Check if we already own this mutex. */
4615 if ((Hardware->powerProcess == process)
4616 && (Hardware->powerThread == thread)
4617 )
4618 {
4619 /* Bail out on recursive power management. */
4620 gcmkFOOTER_NO();
4621 return gcvSTATUS_OK;
4622 }
4623 else if (State != gcvPOWER_ON)
4624 {
4625 /* Called from IST,
4626 ** so waiting here will cause deadlock,
4627 ** if lock holder call gckCOMMAND_Stall() */
4628 status = gcvSTATUS_INVALID_REQUEST;
4629 goto OnError;
4630 }
4631 else
4632 {
4633 /* Acquire the power mutex. */
4634 gcmkONERROR(gckOS_AcquireMutex(os,
4635 Hardware->powerMutex,
4636 gcvINFINITE));
4637 }
4638 }
4639 }
4640 else
4641 {
4642 /* Acquire the power mutex. */
4643 gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
4644 }
4645
4646 /* Get time until mtuex acquired. */
4647 gcmkPROFILE_QUERY(time, mutexTime);
4648
4649 Hardware->powerProcess = process;
4650 Hardware->powerThread = thread;
4651 mutexAcquired = gcvTRUE;
4652
4653 /* Grab control flags and clock. */
4654 flag = flags[Hardware->chipPowerState][State];
4655 clock = clocks[State];
4656
4657#if gcdENABLE_FSCALE_VAL_ADJUST
4658 if (State == gcvPOWER_ON)
4659 {
4660 clock = ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (Hardware->powerOnFscaleVal) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)));
4661 }
4662#endif
4663
4664 if (State == gcvPOWER_SUSPEND && Hardware->chipPowerState == gcvPOWER_OFF && broadcast)
4665 {
4666#if gcdPOWER_SUSPEND_WHEN_IDLE
4667 /* Do nothing */
4668
4669 /* Release the power mutex. */
4670 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
4671
4672 gcmkFOOTER_NO();
4673 return gcvSTATUS_OK;
4674#else
4675 /* Clock should be on when switch power from off to suspend */
4676 clock = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) |
4677 ((((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))) |
4678 ((((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))) |
4679 ((((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))) ;
4680#endif
4681 }
4682
4683#if gcdPOWEROFF_TIMEOUT
4684 if (timeout)
4685 {
4686 gcmkONERROR(gckOS_GetTicks(&currentTime));
4687
4688 gcmkONERROR(
4689 gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
4690
4691 /* powerOffTime is pushed forward, give up.*/
4692 if (isAfter
4693 /* Expect a transition start from IDLE or SUSPEND. */
4694 || (Hardware->chipPowerState == gcvPOWER_ON)
4695 || (Hardware->chipPowerState == gcvPOWER_OFF)
4696 )
4697 {
4698 /* Release the power mutex. */
4699 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
4700
4701 /* No need to do anything. */
4702 gcmkFOOTER_NO();
4703 return gcvSTATUS_OK;
4704 }
4705
4706 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
4707 "Power Off GPU[%d] at %u [supposed to be at %u]",
4708 Hardware->core, currentTime, Hardware->powerOffTime);
4709 }
4710#endif
4711
4712 if (flag == 0)
4713 {
4714 /* Release the power mutex. */
4715 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
4716
4717 /* No need to do anything. */
4718 gcmkFOOTER_NO();
4719 return gcvSTATUS_OK;
4720 }
4721
4722 /* If this is an internal power management, we have to check if we can grab
4723 ** the global power semaphore. If we cannot, we have to wait until the
4724 ** external world changes power management. */
4725 if (!global)
4726 {
4727 /* Try to acquire the global semaphore. */
4728 status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
4729 if (status == gcvSTATUS_TIMEOUT)
4730 {
4731 if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
4732 {
4733 /* Called from thread routine which should NEVER sleep.*/
4734 gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
4735 }
4736
4737 /* Release the power mutex. */
4738 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
4739 "Releasing the power mutex.");
4740 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
4741 mutexAcquired = gcvFALSE;
4742
4743 /* Wait for the semaphore. */
4744 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
4745 "Waiting for global semaphore.");
4746 gcmkONERROR(gckOS_AcquireSemaphore(os, Hardware->globalSemaphore));
4747 globalAcquired = gcvTRUE;
4748
4749 /* Acquire the power mutex. */
4750 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
4751 "Reacquiring the power mutex.");
4752 gcmkONERROR(gckOS_AcquireMutex(os,
4753 Hardware->powerMutex,
4754 gcvINFINITE));
4755 mutexAcquired = gcvTRUE;
4756
4757 /* chipPowerState may be changed by external world during the time
4758 ** we give up powerMutex, so updating flag now is necessary. */
4759 flag = flags[Hardware->chipPowerState][State];
4760
4761 if (flag == 0)
4762 {
4763 gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
4764 globalAcquired = gcvFALSE;
4765
4766 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
4767 mutexAcquired = gcvFALSE;
4768
4769 gcmkFOOTER_NO();
4770 return gcvSTATUS_OK;
4771 }
4772 }
4773 else
4774 {
4775 /* Error. */
4776 gcmkONERROR(status);
4777 }
4778
4779 /* Release the global semaphore again. */
4780 gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
4781 globalAcquired = gcvFALSE;
4782 }
4783 else
4784 {
4785 if (State == gcvPOWER_OFF || State == gcvPOWER_SUSPEND || State == gcvPOWER_IDLE)
4786 {
4787 /* Acquire the global semaphore if it has not been acquired. */
4788 status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
4789 if (status == gcvSTATUS_OK)
4790 {
4791 globalAcquired = gcvTRUE;
4792 }
4793 else if (status != gcvSTATUS_TIMEOUT)
4794 {
4795 /* Other errors. */
4796 gcmkONERROR(status);
4797 }
4798 /* Ignore gcvSTATUS_TIMEOUT and leave globalAcquired as gcvFALSE.
4799 ** gcvSTATUS_TIMEOUT means global semaphore has already
4800 ** been acquired before this operation, so even if we fail,
4801 ** we should not release it in our error handling. It should be
4802 ** released by the next successful global gcvPOWER_ON. */
4803 }
4804
4805 /* Global power management can't be aborted, so sync with
4806 ** proceeding last commit. */
4807 if (flag & gcvPOWER_FLAG_ACQUIRE)
4808 {
4809 /* Acquire the power management semaphore. */
4810 gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
4811 acquired = gcvTRUE;
4812
4813 /* avoid acquiring again. */
4814 flag &= ~gcvPOWER_FLAG_ACQUIRE;
4815 }
4816 }
4817
4818 if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
4819 {
4820 /* Turn on the power. */
4821 gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
4822
4823 /* Mark clock and power as enabled. */
4824 Hardware->clockState = gcvTRUE;
4825 Hardware->powerState = gcvTRUE;
4826
4827 for (;;)
4828 {
4829 /* Check if GPU is present and awake. */
4830 status = _IsGPUPresent(Hardware);
4831
4832 /* Check if the GPU is not responding. */
4833 if (status == gcvSTATUS_GPU_NOT_RESPONDING)
4834 {
4835 /* Turn off the power and clock. */
4836 gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvFALSE, gcvFALSE));
4837
4838 Hardware->clockState = gcvFALSE;
4839 Hardware->powerState = gcvFALSE;
4840
4841 /* Wait a little. */
4842 gckOS_Delay(os, 1);
4843
4844 /* Turn on the power and clock. */
4845 gcmkONERROR(gckOS_SetGPUPower(os, Hardware->core, gcvTRUE, gcvTRUE));
4846
4847 Hardware->clockState = gcvTRUE;
4848 Hardware->powerState = gcvTRUE;
4849
4850 /* We need to initialize the hardware and start the command
4851 * processor. */
4852 flag |= gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_START;
4853 }
4854 else
4855 {
4856 /* Test for error. */
4857 gcmkONERROR(status);
4858
4859 /* Break out of loop. */
4860 break;
4861 }
4862 }
4863 }
4864
4865 /* Get time until powered on. */
4866 gcmkPROFILE_QUERY(time, onTime);
4867
4868 if ((flag & gcvPOWER_FLAG_STALL) && stall)
4869 {
4870 gctBOOL idle;
4871 gctINT32 atomValue;
4872
4873 /* For global operation, all pending commits have already been
4874 ** blocked by globalSemaphore or powerSemaphore.*/
4875 if (!global)
4876 {
4877 /* Check commit atom. */
4878 gcmkONERROR(gckOS_AtomGet(os, command->atomCommit, &atomValue));
4879
4880 if (atomValue > 0)
4881 {
4882 /* Commits are pending - abort power management. */
4883 status = broadcast ? gcvSTATUS_CHIP_NOT_READY
4884 : gcvSTATUS_MORE_DATA;
4885 goto OnError;
4886 }
4887 }
4888
4889 if (broadcast)
4890 {
4891 /* Check for idle. */
4892 gcmkONERROR(gckHARDWARE_QueryIdle(Hardware, &idle));
4893
4894 if (!idle)
4895 {
4896 status = gcvSTATUS_CHIP_NOT_READY;
4897 goto OnError;
4898 }
4899 }
4900
4901 else
4902 {
4903 /* Acquire the command queue. */
4904 gcmkONERROR(gckCOMMAND_EnterCommit(command, gcvTRUE));
4905 commitEntered = gcvTRUE;
4906
4907 /* Get the size of the flush command. */
4908 gcmkONERROR(gckHARDWARE_Flush(Hardware,
4909 gcvFLUSH_ALL,
4910 gcvNULL,
4911 &requested));
4912
4913 /* Reserve space in the command queue. */
4914 gcmkONERROR(gckCOMMAND_Reserve(command,
4915 requested,
4916 &buffer,
4917 &bytes));
4918
4919 /* Append a flush. */
4920 gcmkONERROR(gckHARDWARE_Flush(
4921 Hardware, gcvFLUSH_ALL, buffer, &bytes
4922 ));
4923
4924 /* Execute the command queue. */
4925 gcmkONERROR(gckCOMMAND_Execute(command, requested));
4926
4927 /* Release the command queue. */
4928 gcmkONERROR(gckCOMMAND_ExitCommit(command, gcvTRUE));
4929 commitEntered = gcvFALSE;
4930
4931 /* Wait to finish all commands. */
4932 gcmkONERROR(gckCOMMAND_Stall(command, gcvTRUE));
4933 }
4934 }
4935
4936 /* Get time until stalled. */
4937 gcmkPROFILE_QUERY(time, stallTime);
4938
4939 if (flag & gcvPOWER_FLAG_ACQUIRE)
4940 {
4941 /* Acquire the power management semaphore. */
4942 gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
4943 acquired = gcvTRUE;
4944 }
4945
4946 if (flag & gcvPOWER_FLAG_STOP)
4947 {
4948 /* Stop the command parser. */
4949 gcmkONERROR(gckCOMMAND_Stop(command, gcvFALSE));
4950
4951 /* Stop the Isr. */
4952 if (Hardware->stopIsr)
4953 {
4954 gcmkONERROR(Hardware->stopIsr(Hardware->isrContext));
4955 }
4956 }
4957
4958 /* Flush Cache before Power Off. */
4959 if (flag & gcvPOWER_FLAG_POWER_OFF)
4960 {
4961 if (Hardware->clockState == gcvFALSE)
4962 {
4963 /* Turn off the GPU power. */
4964 gcmkONERROR(
4965 gckOS_SetGPUPower(os,
4966 Hardware->core,
4967 gcvTRUE,
4968 gcvTRUE));
4969
4970 Hardware->clockState = gcvTRUE;
4971
4972 if (gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE)
4973 {
4974 /* Write the clock control register. */
4975 gcmkONERROR(gckOS_WriteRegisterEx(os,
4976 Hardware->core,
4977 0x00000,
4978 clocks[0]));
4979
4980 /* Done loading the frequency scaler. */
4981 gcmkONERROR(gckOS_WriteRegisterEx(os,
4982 Hardware->core,
4983 0x00000,
4984 ((((gctUINT32) (clocks[0])) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
4985 }
4986 }
4987
4988 gcmkONERROR(gckCOMMAND_Start(command));
4989
4990 gcmkONERROR(_FlushCache(Hardware, command));
4991
4992 gckOS_Delay(gcvNULL, 1);
4993
4994 /* Stop the command parser. */
4995 gcmkONERROR(gckCOMMAND_Stop(command, gcvFALSE));
4996
4997 flag |= gcvPOWER_FLAG_CLOCK_OFF;
4998 }
4999
5000 /* Get time until stopped. */
5001 gcmkPROFILE_QUERY(time, stopTime);
5002
5003 /* Only process this when hardware is enabled. */
5004 if (Hardware->clockState && Hardware->powerState
5005 /* Don't touch clock control if dynamic frequency scaling is available. */
5006 && gckHARDWARE_IsFeatureAvailable(Hardware, gcvFEATURE_DYNAMIC_FREQUENCY_SCALING) != gcvTRUE
5007 )
5008 {
5009 if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
5010 {
5011 if (Hardware->identity.chipModel == gcv4000
5012 && ((Hardware->identity.chipRevision == 0x5208) || (Hardware->identity.chipRevision == 0x5222)))
5013 {
5014 clock &= ~2U;
5015 }
5016 }
5017
5018 /* Write the clock control register. */
5019 gcmkONERROR(gckOS_WriteRegisterEx(os,
5020 Hardware->core,
5021 0x00000,
5022 clock));
5023
5024 /* Done loading the frequency scaler. */
5025 gcmkONERROR(gckOS_WriteRegisterEx(os,
5026 Hardware->core,
5027 0x00000,
5028 ((((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)))));
5029 }
5030
5031 if (flag & gcvPOWER_FLAG_DELAY)
5032 {
5033 /* Wait for the specified amount of time to settle coming back from
5034 ** power-off or suspend state. */
5035 gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
5036 }
5037
5038 /* Get time until delayed. */
5039 gcmkPROFILE_QUERY(time, delayTime);
5040
5041 if (flag & gcvPOWER_FLAG_INITIALIZE)
5042 {
5043 /* Initialize hardware. */
5044 gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
5045
5046 gcmkONERROR(gckHARDWARE_SetFastClear(Hardware,
5047 Hardware->allowFastClear,
5048 Hardware->allowCompression));
5049
5050 /* Force the command queue to reload the next context. */
5051 command->currContext = gcvNULL;
5052
5053 /* Need to config mmu after command start. */
5054 configMmu = gcvTRUE;
5055 }
5056
5057 /* Get time until initialized. */
5058 gcmkPROFILE_QUERY(time, initTime);
5059
5060 if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
5061 {
5062 /* Turn off the GPU power. */
5063 gcmkONERROR(
5064 gckOS_SetGPUPower(os,
5065 Hardware->core,
5066 (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
5067 : gcvTRUE,
5068 (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
5069 : gcvTRUE));
5070
5071 /* Save current hardware power and clock states. */
5072 Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
5073 : gcvTRUE;
5074 Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
5075 : gcvTRUE;
5076 }
5077
5078 /* Get time until off. */
5079 gcmkPROFILE_QUERY(time, offTime);
5080
5081 if (flag & gcvPOWER_FLAG_START)
5082 {
5083 /* Start the command processor. */
5084 gcmkONERROR(gckCOMMAND_Start(command));
5085 commandStarted = gcvTRUE;
5086
5087 if (Hardware->startIsr)
5088 {
5089 /* Start the Isr. */
5090 gcmkONERROR(Hardware->startIsr(Hardware->isrContext));
5091 isrStarted = gcvTRUE;
5092 }
5093 }
5094
5095 /* Get time until started. */
5096 gcmkPROFILE_QUERY(time, startTime);
5097
5098 if (flag & gcvPOWER_FLAG_RELEASE)
5099 {
5100 /* Release the power management semaphore. */
5101 gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
5102 acquired = gcvFALSE;
5103
5104 if (global)
5105 {
5106 /* Verify global semaphore has been acquired already before
5107 ** we release it.
5108 ** If it was acquired, gckOS_TryAcquireSemaphore will return
5109 ** gcvSTATUS_TIMEOUT and we release it. Otherwise, global
5110 ** semaphore will be acquried now, but it still is released
5111 ** immediately. */
5112 status = gckOS_TryAcquireSemaphore(os, Hardware->globalSemaphore);
5113 if (status != gcvSTATUS_TIMEOUT)
5114 {
5115 gcmkONERROR(status);
5116 }
5117
5118 /* Release the global semaphore. */
5119 gcmkONERROR(gckOS_ReleaseSemaphore(os, Hardware->globalSemaphore));
5120 globalAcquired = gcvFALSE;
5121 }
5122 }
5123
5124 gckSTATETIMER_Accumulate(&Hardware->powerStateTimer, Hardware->chipPowerState);
5125
5126 /* Save the new power state. */
5127 Hardware->chipPowerState = State;
5128
5129#if gcdDVFS
5130 if (State == gcvPOWER_ON && Hardware->kernel->dvfs)
5131 {
5132 gckDVFS_Start(Hardware->kernel->dvfs);
5133 }
5134#endif
5135
5136#if gcdPOWEROFF_TIMEOUT
5137 /* Reset power off time */
5138 gcmkONERROR(gckOS_GetTicks(&currentTime));
5139
5140 Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
5141
5142 if (State == gcvPOWER_IDLE || State == gcvPOWER_SUSPEND)
5143 {
5144 /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
5145 gcmkVERIFY_OK(gckOS_StartTimer(os,
5146 Hardware->powerOffTimer,
5147 Hardware->powerOffTimeout));
5148 }
5149 else
5150 {
5151 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
5152
5153 /* Cancel running timer when GPU enters ON or OFF. */
5154 gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
5155 }
5156#endif
5157
5158 /* Release the power mutex. */
5159 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
5160
5161 /* Get total time. */
5162 gcmkPROFILE_QUERY(time, totalTime);
5163#if gcdENABLE_PROFILING
5164 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
5165 "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
5166 freq, mutexTime, onTime, stallTime, stopTime);
5167 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
5168 " delay:%llu init:%llu off:%llu start:%llu total:%llu",
5169 delayTime, initTime, offTime, startTime, totalTime);
5170#endif
5171
5172 /* Success. */
5173 gcmkFOOTER_NO();
5174 return gcvSTATUS_OK;
5175
5176OnError:
5177 if (commandStarted)
5178 {
5179 gcmkVERIFY_OK(gckCOMMAND_Stop(command, gcvFALSE));
5180 }
5181
5182 if (isrStarted)
5183 {
5184 gcmkVERIFY_OK(Hardware->stopIsr(Hardware->isrContext));
5185 }
5186
5187 if (commitEntered)
5188 {
5189 /* Release the command queue mutex. */
5190 gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, gcvTRUE));
5191 }
5192
5193 if (acquired)
5194 {
5195 /* Release semaphore. */
5196 gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
5197 command->powerSemaphore));
5198 }
5199
5200 if (globalAcquired)
5201 {
5202 gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
5203 Hardware->globalSemaphore));
5204 }
5205
5206 if (mutexAcquired)
5207 {
5208 gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
5209 }
5210
5211 /* Return the status. */
5212 gcmkFOOTER();
5213 return status;
5214}
5215
5216/*******************************************************************************
5217**
5218** gckHARDWARE_QueryPowerManagementState
5219**
5220** Get GPU power state.
5221**
5222** INPUT:
5223**
5224** gckHARDWARE Harwdare
5225** Pointer to an gckHARDWARE object.
5226**
5227** gceCHIPPOWERSTATE* State
5228** Power State.
5229**
5230*/
5231gceSTATUS
5232gckHARDWARE_QueryPowerManagementState(
5233 IN gckHARDWARE Hardware,
5234 OUT gceCHIPPOWERSTATE* State
5235 )
5236{
5237 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
5238
5239 /* Verify the arguments. */
5240 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5241 gcmkVERIFY_ARGUMENT(State != gcvNULL);
5242
5243 /* Return the statue. */
5244 *State = Hardware->chipPowerState;
5245
5246 /* Success. */
5247 gcmkFOOTER_ARG("*State=%d", *State);
5248 return gcvSTATUS_OK;
5249}
5250
5251/*******************************************************************************
5252**
5253** gckHARDWARE_SetPowerManagement
5254**
5255** Configure GPU power management function.
5256** Only used in driver initialization stage.
5257**
5258** INPUT:
5259**
5260** gckHARDWARE Harwdare
5261** Pointer to an gckHARDWARE object.
5262**
5263** gctBOOL PowerManagement
5264** Power Mangement State.
5265**
5266*/
5267gceSTATUS
5268gckHARDWARE_SetPowerManagement(
5269 IN gckHARDWARE Hardware,
5270 IN gctBOOL PowerManagement
5271 )
5272{
5273 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
5274
5275 /* Verify the arguments. */
5276 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5277
5278 gcmkVERIFY_OK(
5279 gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
5280
5281 Hardware->powerManagement = PowerManagement;
5282
5283 gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
5284
5285 /* Success. */
5286 gcmkFOOTER_NO();
5287 return gcvSTATUS_OK;
5288}
5289
5290/*******************************************************************************
5291**
5292** gckHARDWARE_SetGpuProfiler
5293**
5294** Configure GPU profiler function.
5295** Only used in driver initialization stage.
5296**
5297** INPUT:
5298**
5299** gckHARDWARE Harwdare
5300** Pointer to an gckHARDWARE object.
5301**
5302** gctBOOL GpuProfiler
5303** GOU Profiler State.
5304**
5305*/
5306gceSTATUS
5307gckHARDWARE_SetGpuProfiler(
5308 IN gckHARDWARE Hardware,
5309 IN gctBOOL GpuProfiler
5310 )
5311{
5312 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
5313
5314 /* Verify the arguments. */
5315 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5316
5317 if (GpuProfiler == gcvTRUE)
5318 {
5319 gctUINT32 data = 0;
5320
5321 /* Need to disable clock gating when doing profiling. */
5322 gcmkVERIFY_OK(
5323 gckOS_ReadRegisterEx(Hardware->os,
5324 Hardware->core,
5325 Hardware->powerBaseAddress +
5326 0x00100,
5327 &data));
5328
5329 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
5330
5331
5332 gcmkVERIFY_OK(
5333 gckOS_WriteRegisterEx(Hardware->os,
5334 Hardware->core,
5335 Hardware->powerBaseAddress
5336 + 0x00100,
5337 data));
5338 }
5339
5340 Hardware->gpuProfiler = GpuProfiler;
5341
5342 /* Success. */
5343 gcmkFOOTER_NO();
5344 return gcvSTATUS_OK;
5345}
5346
5347#if gcdENABLE_FSCALE_VAL_ADJUST
5348gceSTATUS
5349gckHARDWARE_SetFscaleValue(
5350 IN gckHARDWARE Hardware,
5351 IN gctUINT32 FscaleValue
5352 )
5353{
5354 gceSTATUS status;
5355 gctUINT32 clock;
5356 gctBOOL acquired = gcvFALSE;
5357
5358 gcmkHEADER_ARG("Hardware=0x%x FscaleValue=%d", Hardware, FscaleValue);
5359
5360 gcmkVERIFY_ARGUMENT(FscaleValue > 0 && FscaleValue <= 64);
5361
5362 gcmkONERROR(
5363 gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE));
5364 acquired = gcvTRUE;
5365
5366 Hardware->powerOnFscaleVal = FscaleValue;
5367
5368 if (Hardware->chipPowerState == gcvPOWER_ON)
5369 {
5370 gctUINT32 data;
5371
5372 gcmkONERROR(
5373 gckOS_ReadRegisterEx(Hardware->os,
5374 Hardware->core,
5375 Hardware->powerBaseAddress
5376 + 0x00104,
5377 &data));
5378
5379 /* Disable all clock gating. */
5380 gcmkONERROR(
5381 gckOS_WriteRegisterEx(Hardware->os,
5382 Hardware->core,
5383 Hardware->powerBaseAddress
5384 + 0x00104,
5385 ((((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)))
5386 | ((((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)))
5387 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
5388 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
5389 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)))
5390 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1))))))) << (0 ? 5:5)))
5391 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1))))))) << (0 ? 6:6)))
5392 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7)))
5393 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1))))))) << (0 ? 8:8)))
5394 | ((((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)))
5395 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11)))));
5396
5397 clock = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
5398 | ((((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)))
5399 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2))) | (((gctUINT32) ((gctUINT32) (FscaleValue) & ((gctUINT32) ((((1 ? 8:2) - (0 ? 8:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:2) - (0 ? 8:2) + 1))))))) << (0 ? 8:2)))
5400 | ((((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)));
5401
5402 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
5403 Hardware->core,
5404 0x00000,
5405 clock));
5406
5407 /* Done loading the frequency scaler. */
5408 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
5409 Hardware->core,
5410 0x00000,
5411 ((((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)))));
5412
5413 /* Restore all clock gating. */
5414 gcmkONERROR(
5415 gckOS_WriteRegisterEx(Hardware->os,
5416 Hardware->core,
5417 Hardware->powerBaseAddress
5418 + 0x00104,
5419 data));
5420 }
5421
5422 gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
5423
5424 gcmkFOOTER_NO();
5425 return gcvSTATUS_OK;
5426
5427OnError:
5428 if (acquired)
5429 {
5430 gcmkVERIFY(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
5431 }
5432
5433 gcmkFOOTER();
5434 return status;
5435}
5436
5437gceSTATUS
5438gckHARDWARE_GetFscaleValue(
5439 IN gckHARDWARE Hardware,
5440 IN gctUINT * FscaleValue,
5441 IN gctUINT * MinFscaleValue,
5442 IN gctUINT * MaxFscaleValue
5443 )
5444{
5445 *FscaleValue = Hardware->powerOnFscaleVal;
5446 *MinFscaleValue = Hardware->minFscaleValue;
5447 *MaxFscaleValue = 64;
5448
5449 return gcvSTATUS_OK;
5450}
5451
5452gceSTATUS
5453gckHARDWARE_SetMinFscaleValue(
5454 IN gckHARDWARE Hardware,
5455 IN gctUINT MinFscaleValue
5456 )
5457{
5458 if (MinFscaleValue >= 1 && MinFscaleValue <= 64)
5459 {
5460 Hardware->minFscaleValue = MinFscaleValue;
5461 }
5462
5463 return gcvSTATUS_OK;
5464}
5465#endif
5466
5467#if gcdPOWEROFF_TIMEOUT
5468gceSTATUS
5469gckHARDWARE_SetPowerOffTimeout(
5470 IN gckHARDWARE Hardware,
5471 IN gctUINT32 Timeout
5472)
5473{
5474 gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
5475
5476 Hardware->powerOffTimeout = Timeout;
5477
5478 gcmkFOOTER_NO();
5479 return gcvSTATUS_OK;
5480}
5481
5482
5483gceSTATUS
5484gckHARDWARE_QueryPowerOffTimeout(
5485 IN gckHARDWARE Hardware,
5486 OUT gctUINT32* Timeout
5487)
5488{
5489 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
5490
5491 *Timeout = Hardware->powerOffTimeout;
5492
5493 gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
5494 return gcvSTATUS_OK;
5495}
5496#endif
5497
5498gceSTATUS
5499gckHARDWARE_QueryIdle(
5500 IN gckHARDWARE Hardware,
5501 OUT gctBOOL_PTR IsIdle
5502 )
5503{
5504 gceSTATUS status;
5505 gctUINT32 idle, address;
5506 gctBOOL isIdle;
5507
5508#if gcdINTERRUPT_STATISTIC
5509 gctINT32 pendingInterrupt;
5510#endif
5511
5512 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
5513
5514 /* Verify the arguments. */
5515 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5516 gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
5517
5518 /* We are idle when the power is not ON. */
5519 if (Hardware->chipPowerState != gcvPOWER_ON)
5520 {
5521 isIdle = gcvTRUE;
5522 }
5523
5524 else
5525 {
5526 /* Read idle register. */
5527 gcmkONERROR(
5528 gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00004, &idle));
5529
5530
5531 /* Pipe must be idle. */
5532 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)
5533 || ((((((gctUINT32) (idle)) >> (0 ? 3:3)) & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1)))))) ) != 1)
5534 || ((((((gctUINT32) (idle)) >> (0 ? 4:4)) & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1)))))) ) != 1)
5535 || ((((((gctUINT32) (idle)) >> (0 ? 5:5)) & ((gctUINT32) ((((1 ? 5:5) - (0 ? 5:5) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 5:5) - (0 ? 5:5) + 1)))))) ) != 1)
5536 || ((((((gctUINT32) (idle)) >> (0 ? 6:6)) & ((gctUINT32) ((((1 ? 6:6) - (0 ? 6:6) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 6:6) - (0 ? 6:6) + 1)))))) ) != 1)
5537 || ((((((gctUINT32) (idle)) >> (0 ? 7:7)) & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1)))))) ) != 1)
5538 || ((((((gctUINT32) (idle)) >> (0 ? 2:2)) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) ) != 1)
5539 )
5540 {
5541 /* Something is busy. */
5542 isIdle = gcvFALSE;
5543 }
5544
5545 else
5546 {
5547 /* Read the current FE address. */
5548 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
5549 Hardware->core,
5550 0x00664,
5551 &address));
5552
5553 /* Test if address is inside the last WAIT/LINK sequence. */
5554 if ((address >= Hardware->lastWaitLink)
5555 && (address <= Hardware->lastWaitLink + 16)
5556 )
5557 {
5558 /* FE is in last WAIT/LINK and the pipe is idle. */
5559 isIdle = gcvTRUE;
5560 }
5561 else
5562 {
5563 /* FE is not in WAIT/LINK yet. */
5564 isIdle = gcvFALSE;
5565 }
5566 }
5567
5568
5569 }
5570
5571#if gcdINTERRUPT_STATISTIC
5572 gcmkONERROR(gckOS_AtomGet(
5573 Hardware->os,
5574 Hardware->kernel->eventObj->interruptCount,
5575 &pendingInterrupt
5576 ));
5577
5578 if (pendingInterrupt)
5579 {
5580 isIdle = gcvFALSE;
5581 }
5582#endif
5583
5584 {
5585 *IsIdle = isIdle;
5586 }
5587
5588 /* Success. */
5589 gcmkFOOTER_NO();
5590 return gcvSTATUS_OK;
5591
5592OnError:
5593 /* Return the status. */
5594 gcmkFOOTER();
5595 return status;
5596}
5597
5598/*******************************************************************************
5599** Handy macros that will help in reading those debug registers.
5600*/
5601
5602#define gcmkREAD_DEBUG_REGISTER(control, block, index, data) \
5603 gcmkONERROR(\
5604 gckOS_WriteRegisterEx(Hardware->os, \
5605 Hardware->core, \
5606 GC_DEBUG_CONTROL##control##_Address, \
5607 gcmSETFIELD(0, \
5608 GC_DEBUG_CONTROL##control, \
5609 block, \
5610 index))); \
5611 gcmkONERROR(\
5612 gckOS_ReadRegisterEx(Hardware->os, \
5613 Hardware->core, \
5614 GC_DEBUG_SIGNALS_##block##_Address, \
5615 &profiler->data))
5616
5617#define gcmkREAD_DEBUG_REGISTER_N(control, block, index, data) \
5618 gcmkONERROR(\
5619 gckOS_WriteRegisterEx(Hardware->os, \
5620 Hardware->core, \
5621 GC_DEBUG_CONTROL##control##_Address, \
5622 gcmSETFIELD(0, \
5623 GC_DEBUG_CONTROL##control, \
5624 block, \
5625 index))); \
5626 gcmkONERROR(\
5627 gckOS_ReadRegisterEx(Hardware->os, \
5628 Hardware->core, \
5629 GC_DEBUG_SIGNALS_##block##_Address, \
5630 &data))
5631
5632#define gcmkRESET_DEBUG_REGISTER(control, block, value) \
5633 gcmkONERROR(\
5634 gckOS_WriteRegisterEx(Hardware->os, \
5635 Hardware->core, \
5636 GC_DEBUG_CONTROL##control##_Address, \
5637 gcmSETFIELD(0, \
5638 GC_DEBUG_CONTROL##control, \
5639 block, \
5640 value))); \
5641 gcmkONERROR(\
5642 gckOS_WriteRegisterEx(Hardware->os, \
5643 Hardware->core, \
5644 GC_DEBUG_CONTROL##control##_Address, \
5645 gcmSETFIELD(0, \
5646 GC_DEBUG_CONTROL##control, \
5647 block, \
5648 0)))
5649
5650/*******************************************************************************
5651**
5652** gckHARDWARE_ProfileEngine2D
5653**
5654** Read the profile registers available in the 2D engine and sets them in the
5655** profile. The function will also reset the pixelsRendered counter every time.
5656**
5657** INPUT:
5658**
5659** gckHARDWARE Hardware
5660** Pointer to an gckHARDWARE object.
5661**
5662** OPTIONAL gcs2D_PROFILE_PTR Profile
5663** Pointer to a gcs2D_Profile structure.
5664**
5665** OUTPUT:
5666**
5667** Nothing.
5668*/
5669gceSTATUS
5670gckHARDWARE_ProfileEngine2D(
5671 IN gckHARDWARE Hardware,
5672 OPTIONAL gcs2D_PROFILE_PTR Profile
5673 )
5674{
5675 gceSTATUS status;
5676 gcs2D_PROFILE_PTR profiler = Profile;
5677
5678 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
5679
5680 /* Verify the arguments. */
5681 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5682
5683 if (Profile != gcvNULL)
5684 {
5685 /* Read the cycle count. */
5686 gcmkONERROR(
5687 gckOS_ReadRegisterEx(Hardware->os,
5688 Hardware->core,
5689 0x00438,
5690 &Profile->cycleCount));
5691
5692 /* Read pixels rendered by 2D engine. */
5693 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5694gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &profiler->pixelsRendered));
5695
5696 /* Reset counter. */
5697 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (15) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5698gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
5699));
5700 }
5701
5702 /* Success. */
5703 gcmkFOOTER_NO();
5704 return gcvSTATUS_OK;
5705
5706OnError:
5707 /* Return the status. */
5708 gcmkFOOTER();
5709 return status;
5710}
5711
5712#if VIVANTE_PROFILER
5713gceSTATUS
5714gckHARDWARE_QueryProfileRegisters(
5715 IN gckHARDWARE Hardware,
5716 IN gctBOOL Reset,
5717 OUT gcsPROFILER_COUNTERS * Counters
5718 )
5719{
5720 gceSTATUS status;
5721 gcsPROFILER_COUNTERS * profiler = Counters;
5722 gctUINT i, clock;
5723 gctUINT32 colorKilled, colorDrawn, depthKilled, depthDrawn;
5724 gctUINT32 totalRead, totalWrite;
5725 gceCHIPMODEL chipModel;
5726 gctUINT32 chipRevision;
5727 gctUINT32 resetValue = 0xF;
5728
5729 gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
5730
5731 /* Verify the arguments. */
5732 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5733
5734 chipModel = Hardware->identity.chipModel;
5735 chipRevision = Hardware->identity.chipRevision;
5736 if ((chipModel == gcv5000 && chipRevision == 0x5434) || (chipModel == gcv3000 && chipRevision == 0x5435))
5737 {
5738 resetValue = 0xFF;
5739 }
5740
5741 /* Read the counters. */
5742 gcmkONERROR(
5743 gckOS_ReadRegisterEx(Hardware->os,
5744 Hardware->core,
5745 0x00438,
5746 &profiler->gpuCyclesCounter));
5747
5748 gcmkONERROR(
5749 gckOS_ReadRegisterEx(Hardware->os,
5750 Hardware->core,
5751 0x00078,
5752 &profiler->gpuTotalCyclesCounter));
5753
5754 gcmkONERROR(
5755 gckOS_ReadRegisterEx(Hardware->os,
5756 Hardware->core,
5757 0x0007C,
5758 &profiler->gpuIdleCyclesCounter));
5759
5760
5761 /* Read clock control register. */
5762 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
5763 Hardware->core,
5764 0x00000,
5765 &clock));
5766
5767 profiler->gpuTotalRead64BytesPerFrame = 0;
5768 profiler->gpuTotalWrite64BytesPerFrame = 0;
5769 profiler->pe_pixel_count_killed_by_color_pipe = 0;
5770 profiler->pe_pixel_count_killed_by_depth_pipe = 0;
5771 profiler->pe_pixel_count_drawn_by_color_pipe = 0;
5772 profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
5773
5774 /* Walk through all avaiable pixel pipes. */
5775 for (i = 0; i < Hardware->identity.pixelPipes; ++i)
5776 {
5777 /* Select proper pipe. */
5778 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
5779 Hardware->core,
5780 0x00000,
5781 ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
5782
5783 /* BW */
5784 gcmkONERROR(
5785 gckOS_ReadRegisterEx(Hardware->os,
5786 Hardware->core,
5787 0x00040,
5788 &totalRead));
5789 gcmkONERROR(
5790 gckOS_ReadRegisterEx(Hardware->os,
5791 Hardware->core,
5792 0x00044,
5793 &totalWrite));
5794
5795 profiler->gpuTotalRead64BytesPerFrame += totalRead;
5796 profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
5797
5798 /* PE */
5799 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorKilled));
5800 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthKilled));
5801 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorDrawn));
5802 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthDrawn));
5803
5804 profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
5805 profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
5806 profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
5807 profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
5808 }
5809
5810 /* Reset clock control register. */
5811 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
5812 Hardware->core,
5813 0x00000,
5814 clock));
5815
5816 /* Reset counters. */
5817 gcmkONERROR(
5818 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
5819 gcmkONERROR(
5820 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
5821 gcmkONERROR(
5822 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
5823 gcmkONERROR(
5824 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
5825 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5826gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
5827));
5828
5829 /* SH */
5830 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5831gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
5832 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5833gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_pixel_counter));
5834 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5835gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_inst_counter));
5836 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5837gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_vertice_counter));
5838 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5839gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_branch_inst_counter));
5840 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5841gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_texld_inst_counter));
5842 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5843gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_branch_inst_counter));
5844 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5845gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_texld_inst_counter));
5846 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5847gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
5848));
5849
5850 /* PA */
5851 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5852gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
5853 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5854gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_prim_counter));
5855 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5856gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_output_prim_counter));
5857 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5858gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_depth_clipped_counter));
5859 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5860gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_trivial_rejected_counter));
5861 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5862gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_culled_counter));
5863 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5864gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
5865));
5866
5867 /* SE */
5868 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
5869gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
5870 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
5871gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
5872 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
5873gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
5874));
5875
5876 /* RA */
5877 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5878gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
5879 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5880gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_quad_count));
5881 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5882gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
5883 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5884gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_primitive_count));
5885 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5886gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_pipe_cache_miss_counter));
5887 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5888gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
5889 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
5890gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
5891));
5892
5893 /* TX */
5894 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5895gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
5896 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5897gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_trilinear_requests));
5898 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5899gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_discarded_texture_requests));
5900 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5901gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_texture_requests));
5902 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5903gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_count));
5904 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5905gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_in_8B_count));
5906 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5907gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_count));
5908 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5909gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
5910 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5911gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
5912 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
5913gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
5914));
5915
5916 /* MC */
5917 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5918gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
5919 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5920gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
5921 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5922gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
5923 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
5924gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
5925));
5926
5927 /* HI */
5928 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
5929gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
5930 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
5931gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
5932 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
5933gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
5934 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
5935gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
5936));
5937
5938 /* Success. */
5939 gcmkFOOTER_NO();
5940 return gcvSTATUS_OK;
5941
5942OnError:
5943 /* Return the status. */
5944 gcmkFOOTER();
5945 return status;
5946}
5947#endif
5948
5949
5950#if VIVANTE_PROFILER_CONTEXT
5951#define gcmkUPDATE_PROFILE_DATA(data) \
5952 profilerHistroy->data += profiler->data
5953
5954gceSTATUS
5955gckHARDWARE_QueryContextProfile(
5956 IN gckHARDWARE Hardware,
5957 IN gctBOOL Reset,
5958 IN gckCONTEXT Context,
5959 OUT gcsPROFILER_COUNTERS * Counters
5960 )
5961{
5962 gceSTATUS status;
5963 gckCOMMAND command = Hardware->kernel->command;
5964 gcsPROFILER_COUNTERS * profiler = Counters;
5965
5966 gcmkHEADER_ARG("Hardware=0x%x Counters=0x%x", Hardware, Counters);
5967
5968 /* Verify the arguments. */
5969 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5970
5971 /* Acquire the context sequnence mutex. */
5972 gcmkONERROR(gckOS_AcquireMutex(
5973 command->os, command->mutexContextSeq, gcvINFINITE
5974 ));
5975
5976 /* Read the counters. */
5977 gcmkVERIFY_OK(gckOS_MemCopy(
5978 profiler, &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
5979 ));
5980
5981 /* Reset counters. */
5982 gcmkVERIFY_OK(gckOS_ZeroMemory(
5983 &Context->histroyProfiler, gcmSIZEOF(gcsPROFILER_COUNTERS)
5984 ));
5985
5986 gcmkVERIFY_OK(gckOS_ReleaseMutex(
5987 command->os, command->mutexContextSeq
5988 ));
5989
5990 /* Success. */
5991 gcmkFOOTER_NO();
5992 return gcvSTATUS_OK;
5993
5994OnError:
5995 /* Return the status. */
5996 gcmkFOOTER();
5997 return status;
5998}
5999
6000static gctUINT32
6001CalcDelta(
6002 IN gctUINT32 new,
6003 IN gctUINT32 old
6004 )
6005{
6006 if (new >= old)
6007 {
6008 return new - old;
6009 }
6010 else
6011 {
6012 return (gctUINT32)((gctUINT64)new + 0x100000000ll - old);
6013 }
6014}
6015
6016#if USE_SW_RESET
6017#define gcmkRESET_PROFILE_DATA(counterName, prevCounterName) \
6018 temp = profiler->counterName; \
6019 profiler->counterName = CalcDelta(temp, Context->prevCounterName); \
6020 Context->prevCounterName = temp
6021
6022#endif
6023
6024gceSTATUS
6025gckHARDWARE_UpdateContextProfile(
6026 IN gckHARDWARE Hardware,
6027 IN gckCONTEXT Context
6028 )
6029{
6030 gceSTATUS status;
6031 gcsPROFILER_COUNTERS * profiler = &Context->latestProfiler;
6032 gcsPROFILER_COUNTERS * profilerHistroy = &Context->histroyProfiler;
6033 gctUINT i, clock;
6034 gctUINT32 colorKilled = 0, colorDrawn = 0, depthKilled = 0, depthDrawn = 0;
6035 gctUINT32 totalRead, totalWrite;
6036 gceCHIPMODEL chipModel;
6037 gctUINT32 chipRevision;
6038 gctUINT32 temp;
6039 gctUINT32 resetValue = 0xF;
6040
6041 gcmkHEADER_ARG("Hardware=0x%x Context=0x%x", Hardware, Context);
6042
6043 /* Verify the arguments. */
6044 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6045 gcmkVERIFY_OBJECT(Context, gcvOBJ_CONTEXT);
6046
6047 chipModel = Hardware->identity.chipModel;
6048 chipRevision = Hardware->identity.chipRevision;
6049 if ((chipModel == gcv5000 && chipRevision == 0x5434) || (chipModel == gcv3000 && chipRevision == 0x5435))
6050 {
6051 resetValue = 0xFF;
6052 }
6053
6054 /* Read the counters. */
6055 gcmkONERROR(
6056 gckOS_ReadRegisterEx(Hardware->os,
6057 Hardware->core,
6058 0x00438,
6059 &profiler->gpuCyclesCounter));
6060 gcmkUPDATE_PROFILE_DATA(gpuCyclesCounter);
6061
6062 gcmkONERROR(
6063 gckOS_ReadRegisterEx(Hardware->os,
6064 Hardware->core,
6065 0x00078,
6066 &profiler->gpuTotalCyclesCounter));
6067 gcmkUPDATE_PROFILE_DATA(gpuTotalCyclesCounter);
6068
6069 if (chipModel == gcv2100 || chipModel == gcv2000 || chipModel == gcv880)
6070 {
6071 gcmkONERROR(
6072 gckOS_ReadRegisterEx(Hardware->os,
6073 Hardware->core,
6074 0x00078,
6075 &profiler->gpuIdleCyclesCounter));
6076 }
6077 else
6078 {
6079 gcmkONERROR(
6080 gckOS_ReadRegisterEx(Hardware->os,
6081 Hardware->core,
6082 0x0007C,
6083 &profiler->gpuIdleCyclesCounter));
6084 }
6085 gcmkUPDATE_PROFILE_DATA(gpuIdleCyclesCounter);
6086
6087 /* Read clock control register. */
6088 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
6089 Hardware->core,
6090 0x00000,
6091 &clock));
6092
6093 profiler->gpuTotalRead64BytesPerFrame = 0;
6094 profiler->gpuTotalWrite64BytesPerFrame = 0;
6095 profiler->pe_pixel_count_killed_by_color_pipe = 0;
6096 profiler->pe_pixel_count_killed_by_depth_pipe = 0;
6097 profiler->pe_pixel_count_drawn_by_color_pipe = 0;
6098 profiler->pe_pixel_count_drawn_by_depth_pipe = 0;
6099
6100 /* Walk through all avaiable pixel pipes. */
6101 for (i = 0; i < Hardware->identity.pixelPipes; ++i)
6102 {
6103 /* Select proper pipe. */
6104 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
6105 Hardware->core,
6106 0x00000,
6107 ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
6108
6109 /* BW */
6110 gcmkONERROR(
6111 gckOS_ReadRegisterEx(Hardware->os,
6112 Hardware->core,
6113 0x00040,
6114 &totalRead));
6115 gcmkONERROR(
6116 gckOS_ReadRegisterEx(Hardware->os,
6117 Hardware->core,
6118 0x00044,
6119 &totalWrite));
6120
6121 profiler->gpuTotalRead64BytesPerFrame += totalRead;
6122 profiler->gpuTotalWrite64BytesPerFrame += totalWrite;
6123
6124 /* PE */
6125 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorKilled));
6126 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthKilled));
6127 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &colorDrawn));
6128 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))));gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00454, &depthDrawn));
6129
6130 profiler->pe_pixel_count_killed_by_color_pipe += colorKilled;
6131 profiler->pe_pixel_count_killed_by_depth_pipe += depthKilled;
6132 profiler->pe_pixel_count_drawn_by_color_pipe += colorDrawn;
6133 profiler->pe_pixel_count_drawn_by_depth_pipe += depthDrawn;
6134 }
6135
6136 gcmkUPDATE_PROFILE_DATA(gpuTotalRead64BytesPerFrame);
6137 gcmkUPDATE_PROFILE_DATA(gpuTotalWrite64BytesPerFrame);
6138#if USE_SW_RESET
6139 gcmkRESET_PROFILE_DATA(pe_pixel_count_killed_by_color_pipe, prevPePixelCountKilledByColorPipe);
6140 gcmkRESET_PROFILE_DATA(pe_pixel_count_killed_by_depth_pipe, prevPePixelCountKilledByDepthPipe);
6141 gcmkRESET_PROFILE_DATA(pe_pixel_count_drawn_by_color_pipe, prevPePixelCountDrawnByColorPipe);
6142 gcmkRESET_PROFILE_DATA(pe_pixel_count_drawn_by_depth_pipe, prevPePixelCountDrawnByDepthPipe);
6143#endif
6144 gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_color_pipe);
6145 gcmkUPDATE_PROFILE_DATA(pe_pixel_count_killed_by_depth_pipe);
6146 gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_color_pipe);
6147 gcmkUPDATE_PROFILE_DATA(pe_pixel_count_drawn_by_depth_pipe);
6148
6149 /* Reset clock control register. */
6150 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
6151 Hardware->core,
6152 0x00000,
6153 clock));
6154
6155 /* Reset counters. */
6156 gcmkONERROR(
6157 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 1));
6158 gcmkONERROR(
6159 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x0003C, 0));
6160 gcmkONERROR(
6161 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00438, 0));
6162 gcmkONERROR(
6163 gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00078, 0));
6164#if !USE_SW_RESET
6165 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6166gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
6167));
6168#endif
6169 /* SH */
6170 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6171gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->ps_inst_counter));
6172 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6173gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_pixel_counter));
6174 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6175gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vs_inst_counter));
6176 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6177gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->rendered_vertice_counter));
6178 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (11) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6179gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_branch_inst_counter));
6180 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (12) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6181gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->vtx_texld_inst_counter));
6182 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (13) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6183gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_branch_inst_counter));
6184 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (14) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6185gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0045C, &profiler->pxl_texld_inst_counter));
6186
6187#if USE_SW_RESET
6188 gcmkRESET_PROFILE_DATA(ps_inst_counter, prevPSInstCount);
6189 gcmkRESET_PROFILE_DATA(rendered_pixel_counter, prevPSPixelCount);
6190 gcmkRESET_PROFILE_DATA(vs_inst_counter, prevVSInstCount);
6191 gcmkRESET_PROFILE_DATA(rendered_vertice_counter, prevVSVertexCount);
6192 gcmkRESET_PROFILE_DATA(vtx_branch_inst_counter, prevVSBranchInstCount);
6193 gcmkRESET_PROFILE_DATA(vtx_texld_inst_counter, prevVSTexInstCount);
6194 gcmkRESET_PROFILE_DATA(pxl_branch_inst_counter, prevPSBranchInstCount);
6195 gcmkRESET_PROFILE_DATA(pxl_texld_inst_counter, prevPSTexInstCount);
6196#endif
6197
6198 gcmkUPDATE_PROFILE_DATA(ps_inst_counter);
6199 gcmkUPDATE_PROFILE_DATA(rendered_pixel_counter);
6200 gcmkUPDATE_PROFILE_DATA(vs_inst_counter);
6201 gcmkUPDATE_PROFILE_DATA(rendered_vertice_counter);
6202 gcmkUPDATE_PROFILE_DATA(vtx_branch_inst_counter);
6203 gcmkUPDATE_PROFILE_DATA(vtx_texld_inst_counter);
6204 gcmkUPDATE_PROFILE_DATA(pxl_branch_inst_counter);
6205 gcmkUPDATE_PROFILE_DATA(pxl_texld_inst_counter);
6206
6207#if !USE_SW_RESET
6208 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6209gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00470, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
6210));
6211#endif
6212
6213 /* PA */
6214 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6215gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_vtx_counter));
6216 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (4) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6217gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_input_prim_counter));
6218 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6219gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_output_prim_counter));
6220 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6221gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_depth_clipped_counter));
6222 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6223gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_trivial_rejected_counter));
6224 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6225gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00460, &profiler->pa_culled_counter));
6226#if USE_SW_RESET
6227 gcmkRESET_PROFILE_DATA(pa_input_vtx_counter, prevPaInputVtxCounter);
6228 gcmkRESET_PROFILE_DATA(pa_input_prim_counter, prevPaInputPrimCounter);
6229 gcmkRESET_PROFILE_DATA(pa_output_prim_counter, prevPaOutputPrimCounter);
6230 gcmkRESET_PROFILE_DATA(pa_depth_clipped_counter, prevPaDepthClippedCounter);
6231 gcmkRESET_PROFILE_DATA(pa_trivial_rejected_counter, prevPaTrivialRejectedCounter);
6232 gcmkRESET_PROFILE_DATA(pa_culled_counter, prevPaCulledCounter);
6233#endif
6234 gcmkUPDATE_PROFILE_DATA(pa_input_vtx_counter);
6235 gcmkUPDATE_PROFILE_DATA(pa_input_prim_counter);
6236 gcmkUPDATE_PROFILE_DATA(pa_output_prim_counter);
6237 gcmkUPDATE_PROFILE_DATA(pa_depth_clipped_counter);
6238 gcmkUPDATE_PROFILE_DATA(pa_trivial_rejected_counter);
6239 gcmkUPDATE_PROFILE_DATA(pa_culled_counter);
6240#if !USE_SW_RESET
6241 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6242gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
6243));
6244#endif
6245
6246 /* SE */
6247 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
6248gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_triangle_count));
6249 gcmkUPDATE_PROFILE_DATA(se_culled_triangle_count);
6250 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
6251gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00464, &profiler->se_culled_lines_count));
6252 gcmkUPDATE_PROFILE_DATA(se_culled_lines_count);
6253 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
6254gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
6255));
6256
6257 /* RA */
6258 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6259gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_pixel_count));
6260 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6261gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_quad_count));
6262 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6263gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_valid_quad_count_after_early_z));
6264 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6265gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_total_primitive_count));
6266 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6267gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_pipe_cache_miss_counter));
6268 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (10) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6269gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00448, &profiler->ra_prefetch_cache_miss_counter));
6270#if USE_SW_RESET
6271 gcmkRESET_PROFILE_DATA(ra_valid_pixel_count, prevRaValidPixelCount);
6272 gcmkRESET_PROFILE_DATA(ra_total_quad_count, prevRaTotalQuadCount);
6273 gcmkRESET_PROFILE_DATA(ra_valid_quad_count_after_early_z, prevRaValidQuadCountAfterEarlyZ);
6274 gcmkRESET_PROFILE_DATA(ra_total_primitive_count, prevRaTotalPrimitiveCount);
6275 gcmkRESET_PROFILE_DATA(ra_pipe_cache_miss_counter, prevRaPipeCacheMissCounter);
6276 gcmkRESET_PROFILE_DATA(ra_prefetch_cache_miss_counter, prevRaPrefetchCacheMissCounter);
6277#endif
6278 gcmkUPDATE_PROFILE_DATA(ra_valid_pixel_count);
6279 gcmkUPDATE_PROFILE_DATA(ra_total_quad_count);
6280 gcmkUPDATE_PROFILE_DATA(ra_valid_quad_count_after_early_z);
6281 gcmkUPDATE_PROFILE_DATA(ra_total_primitive_count);
6282 gcmkUPDATE_PROFILE_DATA(ra_pipe_cache_miss_counter);
6283 gcmkUPDATE_PROFILE_DATA(ra_prefetch_cache_miss_counter);
6284#if !USE_SW_RESET
6285 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) ));
6286gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 23:16) - (0 ? 23:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:16) - (0 ? 23:16) + 1))))))) << (0 ? 23:16)))
6287));
6288#endif
6289
6290 /* TX */
6291 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6292gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_bilinear_requests));
6293 gcmkUPDATE_PROFILE_DATA(tx_total_bilinear_requests);
6294 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6295gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_trilinear_requests));
6296 gcmkUPDATE_PROFILE_DATA(tx_total_trilinear_requests);
6297 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6298gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_discarded_texture_requests));
6299 gcmkUPDATE_PROFILE_DATA(tx_total_discarded_texture_requests);
6300 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6301gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_total_texture_requests));
6302 gcmkUPDATE_PROFILE_DATA(tx_total_texture_requests);
6303 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (5) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6304gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_count));
6305 gcmkUPDATE_PROFILE_DATA(tx_mem_read_count);
6306 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (6) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6307gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_mem_read_in_8B_count));
6308 gcmkUPDATE_PROFILE_DATA(tx_mem_read_in_8B_count);
6309 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (7) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6310gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_count));
6311 gcmkUPDATE_PROFILE_DATA(tx_cache_miss_count);
6312 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (8) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6313gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_hit_texel_count));
6314 gcmkUPDATE_PROFILE_DATA(tx_cache_hit_texel_count);
6315 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (9) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6316gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0044C, &profiler->tx_cache_miss_texel_count));
6317 gcmkUPDATE_PROFILE_DATA(tx_cache_miss_texel_count);
6318 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) ));
6319gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00474, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))) << (0 ? 31:24)))
6320));
6321
6322 /* MC */
6323 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6324gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_pipeline));
6325 gcmkUPDATE_PROFILE_DATA(mc_total_read_req_8B_from_pipeline);
6326 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6327gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_read_req_8B_from_IP));
6328 gcmkUPDATE_PROFILE_DATA(mc_total_read_req_8B_from_IP);
6329 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (3) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6330gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x00468, &profiler->mc_total_write_req_8B_from_pipeline));
6331 gcmkUPDATE_PROFILE_DATA(mc_total_write_req_8B_from_pipeline);
6332 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) ));
6333gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 7:0) - (0 ? 7:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:0) - (0 ? 7:0) + 1))))))) << (0 ? 7:0)))
6334));
6335
6336 /* HI */
6337 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
6338gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_read_request_stalled));
6339 gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_read_request_stalled);
6340 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
6341gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_request_stalled));
6342 gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_write_request_stalled);
6343 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (2) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
6344gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os, Hardware->core, 0x0046C, &profiler->hi_axi_cycles_write_data_stalled));
6345 gcmkUPDATE_PROFILE_DATA(hi_axi_cycles_write_data_stalled);
6346 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (resetValue) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) ));
6347gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, 0x00478, ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))
6348));
6349
6350 /* Success. */
6351 gcmkFOOTER_NO();
6352 return gcvSTATUS_OK;
6353
6354OnError:
6355 /* Return the status. */
6356 gcmkFOOTER();
6357 return status;
6358}
6359#endif
6360
6361
6362gceSTATUS
6363gckHARDWARE_InitProfiler(
6364 IN gckHARDWARE Hardware
6365 )
6366{
6367 gceSTATUS status;
6368 gctUINT32 control;
6369
6370 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
6371 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
6372 Hardware->core,
6373 0x00000,
6374 &control));
6375 /* Enable debug register. */
6376 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
6377 Hardware->core,
6378 0x00000,
6379 ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1))))))) << (0 ? 11:11)))));
6380
6381OnError:
6382 /* Return the status. */
6383 gcmkFOOTER();
6384 return status;
6385}
6386
6387static gceSTATUS
6388_ResetGPU(
6389 IN gckHARDWARE Hardware,
6390 IN gckOS Os,
6391 IN gceCORE Core
6392 )
6393{
6394 gctUINT32 control, idle;
6395 gceSTATUS status;
6396
6397 for (;;)
6398 {
6399 /* Disable clock gating. */
6400 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6401 Core,
6402 Hardware->powerBaseAddress +
6403 0x00104,
6404 0x00000000));
6405
6406 control = ((((gctUINT32) (0x01590880)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1))))))) << (0 ? 17:17)));
6407
6408 /* Disable pulse-eater. */
6409 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6410 Core,
6411 0x0010C,
6412 control));
6413
6414 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6415 Core,
6416 0x0010C,
6417 ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))));
6418
6419 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6420 Core,
6421 0x0010C,
6422 control));
6423
6424 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6425 Core,
6426 0x00000,
6427 ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
6428
6429 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6430 Core,
6431 0x00000,
6432 0x00000900));
6433
6434 /* Wait for clock being stable. */
6435 gcmkONERROR(gckOS_Delay(Os, 1));
6436
6437 /* Isolate the GPU. */
6438 control = ((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
6439
6440 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6441 Core,
6442 0x00000,
6443 control));
6444
6445 /* Set soft reset. */
6446 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6447 Core,
6448 0x00000,
6449 ((((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)))));
6450
6451 /* Wait for reset. */
6452 gcmkONERROR(gckOS_Delay(Os, 1));
6453
6454 /* Reset soft reset bit. */
6455 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6456 Core,
6457 0x00000,
6458 ((((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)))));
6459
6460 /* Reset GPU isolation. */
6461 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)));
6462
6463 gcmkONERROR(gckOS_WriteRegisterEx(Os,
6464 Core,
6465 0x00000,
6466 control));
6467
6468 /* Read idle register. */
6469 gcmkONERROR(gckOS_ReadRegisterEx(Os,
6470 Core,
6471 0x00004,
6472 &idle));
6473
6474 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)
6475 {
6476 continue;
6477 }
6478
6479 /* Read reset register. */
6480 gcmkONERROR(gckOS_ReadRegisterEx(Os,
6481 Core,
6482 0x00000,
6483 &control));
6484
6485 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)
6486 || ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
6487 )
6488 {
6489 continue;
6490 }
6491
6492 /* GPU is idle. */
6493 break;
6494 }
6495
6496 /* Success. */
6497 return gcvSTATUS_OK;
6498
6499OnError:
6500
6501 /* Return the error. */
6502 return status;
6503}
6504
6505gceSTATUS
6506gckHARDWARE_Reset(
6507 IN gckHARDWARE Hardware
6508 )
6509{
6510 gceSTATUS status;
6511
6512 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
6513
6514 /* Verify the arguments. */
6515 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6516 gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
6517
6518 /* Hardware reset. */
6519 status = gckOS_ResetGPU(Hardware->os, Hardware->core);
6520
6521 if (gcmIS_ERROR(status))
6522 {
6523 if (Hardware->identity.chipRevision < 0x4600)
6524 {
6525 /* Not supported - we need the isolation bit. */
6526 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
6527 }
6528
6529 /* Soft reset. */
6530 gcmkONERROR(_ResetGPU(Hardware, Hardware->os, Hardware->core));
6531 }
6532
6533 /* Initialize hardware. */
6534 gcmkONERROR(gckHARDWARE_InitializeHardware(Hardware));
6535
6536 /* Jump to address into which GPU should run if it doesn't stuck. */
6537 gcmkONERROR(gckHARDWARE_Execute(Hardware, Hardware->kernel->restoreAddress, 16));
6538
6539 gcmkPRINT("[galcore]: recovery done");
6540
6541 /* Success. */
6542 gcmkFOOTER_NO();
6543 return gcvSTATUS_OK;
6544
6545OnError:
6546 gcmkPRINT("[galcore]: Hardware not reset successfully, give up");
6547
6548 /* Return the error. */
6549 gcmkFOOTER();
6550 return status;
6551}
6552
6553gceSTATUS
6554gckHARDWARE_GetBaseAddress(
6555 IN gckHARDWARE Hardware,
6556 OUT gctUINT32_PTR BaseAddress
6557 )
6558{
6559 gceSTATUS status;
6560
6561 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
6562
6563 /* Verify the arguments. */
6564 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6565 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
6566
6567 /* Test if we have a new Memory Controller. */
6568 if (((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (0 ? 22:22) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))))
6569 {
6570 /* No base address required. */
6571 *BaseAddress = 0;
6572 }
6573 else
6574 {
6575 /* Get the base address from the OS. */
6576 gcmkONERROR(gckOS_GetBaseAddress(Hardware->os, BaseAddress));
6577 }
6578
6579 /* Success. */
6580 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
6581 return gcvSTATUS_OK;
6582
6583OnError:
6584 /* Return the status. */
6585 gcmkFOOTER();
6586 return status;
6587}
6588
6589gceSTATUS
6590gckHARDWARE_NeedBaseAddress(
6591 IN gckHARDWARE Hardware,
6592 IN gctUINT32 State,
6593 OUT gctBOOL_PTR NeedBase
6594 )
6595{
6596 gctBOOL need = gcvFALSE;
6597
6598 gcmkHEADER_ARG("Hardware=0x%x State=0x%08x", Hardware, State);
6599
6600 /* Verify the arguments. */
6601 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6602 gcmkVERIFY_ARGUMENT(NeedBase != gcvNULL);
6603
6604 /* Make sure this is a load state. */
6605 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))))))))
6606 {
6607 /* 2D addresses don't need a base address. */
6608 }
6609
6610 /* Return the flag. */
6611 *NeedBase = need;
6612
6613 /* Success. */
6614 gcmkFOOTER_ARG("*NeedBase=%d", *NeedBase);
6615 return gcvSTATUS_OK;
6616}
6617
6618gceSTATUS
6619gckHARDWARE_SetIsrManager(
6620 IN gckHARDWARE Hardware,
6621 IN gctISRMANAGERFUNC StartIsr,
6622 IN gctISRMANAGERFUNC StopIsr,
6623 IN gctPOINTER Context
6624 )
6625{
6626 gceSTATUS status = gcvSTATUS_OK;
6627
6628 gcmkHEADER_ARG("Hardware=0x%x, StartIsr=0x%x, StopIsr=0x%x, Context=0x%x",
6629 Hardware, StartIsr, StopIsr, Context);
6630
6631 /* Verify the arguments. */
6632 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6633
6634 if (StartIsr == gcvNULL ||
6635 StopIsr == gcvNULL ||
6636 Context == gcvNULL)
6637 {
6638 status = gcvSTATUS_INVALID_ARGUMENT;
6639
6640 gcmkFOOTER();
6641 return status;
6642 }
6643
6644 Hardware->startIsr = StartIsr;
6645 Hardware->stopIsr = StopIsr;
6646 Hardware->isrContext = Context;
6647
6648 /* Success. */
6649 gcmkFOOTER();
6650
6651 return status;
6652}
6653
6654/*******************************************************************************
6655**
6656** gckHARDWARE_Compose
6657**
6658** Start a composition.
6659**
6660** INPUT:
6661**
6662** gckHARDWARE Hardware
6663** Pointer to the gckHARDWARE object.
6664**
6665** OUTPUT:
6666**
6667** Nothing.
6668*/
6669gceSTATUS
6670gckHARDWARE_Compose(
6671 IN gckHARDWARE Hardware,
6672 IN gctUINT32 ProcessID,
6673 IN gctPHYS_ADDR Physical,
6674 IN gctPOINTER Logical,
6675 IN gctSIZE_T Offset,
6676 IN gctSIZE_T Size,
6677 IN gctUINT8 EventID
6678 )
6679{
6680 /* Return the status. */
6681 return gcvSTATUS_NOT_SUPPORTED;
6682}
6683
6684/*******************************************************************************
6685**
6686** gckHARDWARE_IsFeatureAvailable
6687**
6688** Verifies whether the specified feature is available in hardware.
6689**
6690** INPUT:
6691**
6692** gckHARDWARE Hardware
6693** Pointer to an gckHARDWARE object.
6694**
6695** gceFEATURE Feature
6696** Feature to be verified.
6697*/
6698gceSTATUS
6699gckHARDWARE_IsFeatureAvailable(
6700 IN gckHARDWARE Hardware,
6701 IN gceFEATURE Feature
6702 )
6703{
6704 gctBOOL available;
6705
6706 gcmkHEADER_ARG("Hardware=0x%x Feature=%d", Hardware, Feature);
6707
6708 /* Verify the arguments. */
6709 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6710
6711 /* Only features needed by common kernel logic added here. */
6712 switch (Feature)
6713 {
6714 case gcvFEATURE_END_EVENT:
6715 /*available = gcmVERIFYFIELDVALUE(Hardware->identity.chipMinorFeatures2,
6716 GC_MINOR_FEATURES2, END_EVENT, AVAILABLE
6717 );*/
6718 available = gcvFALSE;
6719 break;
6720
6721 case gcvFEATURE_MC20:
6722 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (0 ? 22:22) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1)))))));
6723 break;
6724
6725 case gcvFEATURE_EARLY_Z:
6726 available = ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x0 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))));
6727 break;
6728
6729 case gcvFEATURE_HZ:
6730 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures)) >> (0 ? 27:27) & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 27:27) - (0 ? 27:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 27:27) - (0 ? 27:27) + 1)))))));
6731 break;
6732
6733 case gcvFEATURE_NEW_HZ:
6734 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 26:26) & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 26:26) - (0 ? 26:26) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:26) - (0 ? 26:26) + 1)))))));
6735 break;
6736
6737 case gcvFEATURE_FAST_MSAA:
6738 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 8:8) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))));
6739 break;
6740
6741 case gcvFEATURE_SMALL_MSAA:
6742 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures4)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
6743 break;
6744
6745 case gcvFEATURE_DYNAMIC_FREQUENCY_SCALING:
6746 /* This feature doesn't apply for 2D cores. */
6747 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures2)) >> (0 ? 14:14) & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))))
6748 && ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 2:2) & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1)))))));
6749
6750 if (Hardware->identity.chipModel == gcv1000 &&
6751 (Hardware->identity.chipRevision == 0x5039 ||
6752 Hardware->identity.chipRevision == 0x5040))
6753 {
6754 available = gcvFALSE;
6755 }
6756 break;
6757
6758 case gcvFEATURE_ACE:
6759 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures3)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
6760 break;
6761
6762 case gcvFEATURE_HALTI2:
6763 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures4)) >> (0 ? 16:16) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))));
6764 break;
6765
6766 case gcvFEATURE_PIPE_2D:
6767 available = ((((gctUINT32) (Hardware->identity.chipFeatures)) >> (0 ? 9:9) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))));
6768 break;
6769
6770 case gcvFEATURE_PIPE_3D:
6771 available = gcvFALSE;
6772 break;
6773
6774 case gcvFEATURE_FC_FLUSH_STALL:
6775 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures1)) >> (0 ? 31:31) & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 31:31) - (0 ? 31:31) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:31) - (0 ? 31:31) + 1)))))));
6776 break;
6777
6778 case gcvFEATURE_TEX_CACHE_FLUSH_FIX:
6779 available = ((((gctUINT32) (Hardware->identity.chipMinorFeatures5)) >> (0 ? 14:14) & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 14:14) - (0 ? 14:14) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 14:14) - (0 ? 14:14) + 1)))))));
6780 break;
6781
6782 default:
6783 gcmkFATAL("Invalid feature has been requested.");
6784 available = gcvFALSE;
6785 }
6786
6787 /* Return result. */
6788 gcmkFOOTER_ARG("%d", available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE);
6789 return available ? gcvSTATUS_TRUE : gcvSTATUS_FALSE;
6790}
6791
6792/*******************************************************************************
6793**
6794** gckHARDWARE_DumpMMUException
6795**
6796** Dump the MMU debug info on an MMU exception.
6797**
6798** INPUT:
6799**
6800** gckHARDWARE Harwdare
6801** Pointer to an gckHARDWARE object.
6802**
6803** OUTPUT:
6804**
6805** Nothing.
6806*/
6807gceSTATUS
6808gckHARDWARE_DumpMMUException(
6809 IN gckHARDWARE Hardware
6810 )
6811{
6812 gctUINT32 mmu = 0;
6813 gctUINT32 mmuStatus = 0;
6814 gctUINT32 address = 0;
6815 gctUINT32 i = 0;
6816 gctUINT32 mtlb = 0;
6817 gctUINT32 stlb = 0;
6818 gctUINT32 offset = 0;
6819#if gcdPROCESS_ADDRESS_SPACE
6820 gcsDATABASE_PTR database;
6821#endif
6822
6823 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
6824
6825 /* Verify the arguments. */
6826 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6827
6828 gcmkPRINT("GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
6829 Hardware->core,
6830 Hardware->identity.chipModel,
6831 Hardware->identity.chipRevision);
6832
6833 gcmkPRINT("**************************\n");
6834 gcmkPRINT("*** MMU ERROR DUMP ***\n");
6835 gcmkPRINT("**************************\n");
6836
6837 gcmkVERIFY_OK(
6838 gckOS_ReadRegisterEx(Hardware->os,
6839 Hardware->core,
6840 0x00188,
6841 &mmuStatus));
6842
6843 gcmkPRINT(" MMU status = 0x%08X\n", mmuStatus);
6844
6845 for (i = 0; i < 4; i += 1)
6846 {
6847 mmu = mmuStatus & 0xF;
6848 mmuStatus >>= 4;
6849
6850 if (mmu == 0)
6851 {
6852 continue;
6853 }
6854
6855 switch (mmu)
6856 {
6857 case 1:
6858 gcmkPRINT(" MMU%d: slave not present\n", i);
6859 break;
6860
6861 case 2:
6862 gcmkPRINT(" MMU%d: page not present\n", i);
6863 break;
6864
6865 case 3:
6866 gcmkPRINT(" MMU%d: write violation\n", i);
6867 break;
6868
6869 default:
6870 gcmkPRINT(" MMU%d: unknown state\n", i);
6871 }
6872
6873 gcmkVERIFY_OK(
6874 gckOS_ReadRegisterEx(Hardware->os,
6875 Hardware->core,
6876 0x00190 + i * 4,
6877 &address));
6878
6879 mtlb = (address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
6880 stlb = (address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
6881 offset = address & gcdMMU_OFFSET_4K_MASK;
6882
6883 gcmkPRINT(" MMU%d: exception address = 0x%08X\n", i, address);
6884
6885 gcmkPRINT(" MTLB entry = %d\n", mtlb);
6886
6887 gcmkPRINT(" STLB entry = %d\n", stlb);
6888
6889 gcmkPRINT(" Offset = 0x%08X (%d)\n", offset, offset);
6890
6891 gckMMU_DumpPageTableEntry(Hardware->kernel->mmu, address);
6892
6893#if gcdPROCESS_ADDRESS_SPACE
6894 for (i = 0; i < gcmCOUNTOF(Hardware->kernel->db->db); ++i)
6895 {
6896 for (database = Hardware->kernel->db->db[i];
6897 database != gcvNULL;
6898 database = database->next)
6899 {
6900 gcmkPRINT(" database [%d] :", database->processID);
6901 gckMMU_DumpPageTableEntry(database->mmu, address);
6902 }
6903 }
6904#endif
6905 }
6906
6907 gcmkFOOTER_NO();
6908 return gcvSTATUS_OK;
6909}
6910
6911/*******************************************************************************
6912**
6913** gckHARDWARE_DumpGPUState
6914**
6915** Dump the GPU debug registers.
6916**
6917** INPUT:
6918**
6919** gckHARDWARE Harwdare
6920** Pointer to an gckHARDWARE object.
6921**
6922** OUTPUT:
6923**
6924** Nothing.
6925*/
6926gceSTATUS
6927gckHARDWARE_DumpGPUState(
6928 IN gckHARDWARE Hardware
6929 )
6930{
6931 static gctCONST_STRING _cmdState[] =
6932 {
6933 "PAR_IDLE_ST", "PAR_DEC_ST", "PAR_ADR0_ST", "PAR_LOAD0_ST",
6934 "PAR_ADR1_ST", "PAR_LOAD1_ST", "PAR_3DADR_ST", "PAR_3DCMD_ST",
6935 "PAR_3DCNTL_ST", "PAR_3DIDXCNTL_ST", "PAR_INITREQDMA_ST",
6936 "PAR_DRAWIDX_ST", "PAR_DRAW_ST", "PAR_2DRECT0_ST", "PAR_2DRECT1_ST",
6937 "PAR_2DDATA0_ST", "PAR_2DDATA1_ST", "PAR_WAITFIFO_ST", "PAR_WAIT_ST",
6938 "PAR_LINK_ST", "PAR_END_ST", "PAR_STALL_ST"
6939 };
6940
6941 static gctCONST_STRING _cmdDmaState[] =
6942 {
6943 "CMD_IDLE_ST", "CMD_START_ST", "CMD_REQ_ST", "CMD_END_ST"
6944 };
6945
6946 static gctCONST_STRING _cmdFetState[] =
6947 {
6948 "FET_IDLE_ST", "FET_RAMVALID_ST", "FET_VALID_ST"
6949 };
6950
6951 static gctCONST_STRING _reqDmaState[] =
6952 {
6953 "REQ_IDLE_ST", "REQ_WAITIDX_ST", "REQ_CAL_ST"
6954 };
6955
6956 static gctCONST_STRING _calState[] =
6957 {
6958 "CAL_IDLE_ST", "CAL_LDADR_ST", "CAL_IDXCALC_ST"
6959 };
6960
6961 static gctCONST_STRING _veReqState[] =
6962 {
6963 "VER_IDLE_ST", "VER_CKCACHE_ST", "VER_MISS_ST"
6964 };
6965
6966 static gcsiDEBUG_REGISTERS _dbgRegs[] =
6967 {
6968 { "RA", 0x474, 16, 0x448, 32, 0x12344321 },
6969 { "TX", 0x474, 24, 0x44C, 32, 0x12211221 },
6970 { "FE", 0x470, 0, 0x450, 32, 0xBABEF00D },
6971 { "PE", 0x470, 16, 0x454, 48, 0xBABEF00D },
6972 { "DE", 0x470, 8, 0x458, 32, 0xBABEF00D },
6973 { "SH", 0x470, 24, 0x45C, 32, 0xDEADBEEF },
6974 { "PA", 0x474, 0, 0x460, 32, 0x0000AAAA },
6975 { "SE", 0x474, 8, 0x464, 32, 0x5E5E5E5E },
6976 { "MC", 0x478, 0, 0x468, 32, 0x12345678 },
6977 { "HI", 0x478, 8, 0x46C, 32, 0xAAAAAAAA }
6978 };
6979
6980 static gctUINT32 _otherRegs[] =
6981 {
6982 0x040, 0x044, 0x04C, 0x050, 0x054, 0x058, 0x05C, 0x060,
6983 0x43c, 0x440, 0x444, 0x414,
6984 };
6985
6986 gceSTATUS status;
6987 gckKERNEL kernel = gcvNULL;
6988 gctUINT32 idle = 0, axi = 0;
6989 gctUINT32 dmaAddress1 = 0, dmaAddress2 = 0;
6990 gctUINT32 dmaState1 = 0, dmaState2 = 0;
6991 gctUINT32 dmaLow = 0, dmaHigh = 0;
6992 gctUINT32 cmdState = 0, cmdDmaState = 0, cmdFetState = 0;
6993 gctUINT32 dmaReqState = 0, calState = 0, veReqState = 0;
6994 gctUINT i;
6995 gctUINT pipe = 0, pixelPipes = 0;
6996 gctUINT32 control = 0, oldControl = 0;
6997 gckOS os = Hardware->os;
6998 gceCORE core = Hardware->core;
6999
7000 gcmkHEADER_ARG("Hardware=0x%X", Hardware);
7001
7002 kernel = Hardware->kernel;
7003
7004 gcmkPRINT_N(12, "GPU[%d](ChipModel=0x%x ChipRevision=0x%x):\n",
7005 core,
7006 Hardware->identity.chipModel,
7007 Hardware->identity.chipRevision);
7008
7009 pixelPipes = Hardware->identity.pixelPipes
7010 ? Hardware->identity.pixelPipes
7011 : 1;
7012
7013 /* Reset register values. */
7014 idle = axi =
7015 dmaState1 = dmaState2 =
7016 dmaAddress1 = dmaAddress2 =
7017 dmaLow = dmaHigh = 0;
7018
7019 /* Verify whether DMA is running. */
7020 gcmkONERROR(_VerifyDMA(
7021 os, core, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
7022 ));
7023
7024 cmdState = dmaState2 & 0x1F;
7025 cmdDmaState = (dmaState2 >> 8) & 0x03;
7026 cmdFetState = (dmaState2 >> 10) & 0x03;
7027 dmaReqState = (dmaState2 >> 12) & 0x03;
7028 calState = (dmaState2 >> 14) & 0x03;
7029 veReqState = (dmaState2 >> 16) & 0x03;
7030
7031 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x004, &idle));
7032 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x00C, &axi));
7033 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x668, &dmaLow));
7034 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x66C, &dmaHigh));
7035
7036 gcmkPRINT_N(0, "**************************\n");
7037 gcmkPRINT_N(0, "*** GPU STATE DUMP ***\n");
7038 gcmkPRINT_N(0, "**************************\n");
7039
7040 gcmkPRINT_N(4, " axi = 0x%08X\n", axi);
7041
7042 gcmkPRINT_N(4, " idle = 0x%08X\n", idle);
7043 if ((idle & 0x00000001) == 0) gcmkPRINT_N(0, " FE not idle\n");
7044 if ((idle & 0x00000002) == 0) gcmkPRINT_N(0, " DE not idle\n");
7045 if ((idle & 0x00000004) == 0) gcmkPRINT_N(0, " PE not idle\n");
7046 if ((idle & 0x00000008) == 0) gcmkPRINT_N(0, " SH not idle\n");
7047 if ((idle & 0x00000010) == 0) gcmkPRINT_N(0, " PA not idle\n");
7048 if ((idle & 0x00000020) == 0) gcmkPRINT_N(0, " SE not idle\n");
7049 if ((idle & 0x00000040) == 0) gcmkPRINT_N(0, " RA not idle\n");
7050 if ((idle & 0x00000080) == 0) gcmkPRINT_N(0, " TX not idle\n");
7051 if ((idle & 0x00000100) == 0) gcmkPRINT_N(0, " VG not idle\n");
7052 if ((idle & 0x00000200) == 0) gcmkPRINT_N(0, " IM not idle\n");
7053 if ((idle & 0x00000400) == 0) gcmkPRINT_N(0, " FP not idle\n");
7054 if ((idle & 0x00000800) == 0) gcmkPRINT_N(0, " TS not idle\n");
7055 if ((idle & 0x80000000) != 0) gcmkPRINT_N(0, " AXI low power mode\n");
7056
7057 if (
7058 (dmaAddress1 == dmaAddress2)
7059 && (dmaState1 == dmaState2)
7060 )
7061 {
7062 gcmkPRINT_N(0, " DMA appears to be stuck at this address:\n");
7063 gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
7064 }
7065 else
7066 {
7067 if (dmaAddress1 == dmaAddress2)
7068 {
7069 gcmkPRINT_N(0, " DMA address is constant, but state is changing:\n");
7070 gcmkPRINT_N(4, " 0x%08X\n", dmaState1);
7071 gcmkPRINT_N(4, " 0x%08X\n", dmaState2);
7072 }
7073 else
7074 {
7075 gcmkPRINT_N(0, " DMA is running; known addresses are:\n");
7076 gcmkPRINT_N(4, " 0x%08X\n", dmaAddress1);
7077 gcmkPRINT_N(4, " 0x%08X\n", dmaAddress2);
7078 }
7079 }
7080
7081 gcmkPRINT_N(4, " dmaLow = 0x%08X\n", dmaLow);
7082 gcmkPRINT_N(4, " dmaHigh = 0x%08X\n", dmaHigh);
7083 gcmkPRINT_N(4, " dmaState = 0x%08X\n", dmaState2);
7084 gcmkPRINT_N(8, " command state = %d (%s)\n", cmdState, _cmdState [cmdState]);
7085 gcmkPRINT_N(8, " command DMA state = %d (%s)\n", cmdDmaState, _cmdDmaState[cmdDmaState]);
7086 gcmkPRINT_N(8, " command fetch state = %d (%s)\n", cmdFetState, _cmdFetState[cmdFetState]);
7087 gcmkPRINT_N(8, " DMA request state = %d (%s)\n", dmaReqState, _reqDmaState[dmaReqState]);
7088 gcmkPRINT_N(8, " cal state = %d (%s)\n", calState, _calState [calState]);
7089 gcmkPRINT_N(8, " VE request state = %d (%s)\n", veReqState, _veReqState [veReqState]);
7090
7091 /* Record control. */
7092 gckOS_ReadRegisterEx(os, core, 0x0, &oldControl);
7093
7094 for (pipe = 0; pipe < pixelPipes; pipe++)
7095 {
7096 gcmkPRINT_N(4, " Debug registers of pipe[%d]:\n", pipe);
7097
7098 /* Switch pipe. */
7099 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x0, &control));
7100 control &= ~(0xF << 20);
7101 control |= (pipe << 20);
7102 gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, control));
7103
7104 for (i = 0; i < gcmCOUNTOF(_dbgRegs); i += 1)
7105 {
7106 gcmkONERROR(_DumpDebugRegisters(os, core, &_dbgRegs[i]));
7107 }
7108
7109 gcmkPRINT_N(0, " Other Registers:\n");
7110 for (i = 0; i < gcmCOUNTOF(_otherRegs); i += 1)
7111 {
7112 gctUINT32 read;
7113 gcmkONERROR(gckOS_ReadRegisterEx(os, core, _otherRegs[i], &read));
7114 gcmkPRINT_N(12, " [0x%04X] 0x%08X\n", _otherRegs[i], read);
7115 }
7116
7117 if (Hardware->mmuVersion)
7118 {
7119 gcmkPRINT(" MMU status from MC[%d]:", pipe);
7120
7121 gckHARDWARE_DumpMMUException(Hardware);
7122 }
7123 }
7124
7125 if (kernel->hardware->identity.chipFeatures & (1 << 4))
7126 {
7127 gctUINT32 read0, read1, write;
7128
7129 read0 = read1 = write = 0;
7130
7131 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x43C, &read0));
7132 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x440, &read1));
7133 gcmkONERROR(gckOS_ReadRegisterEx(os, core, 0x444, &write));
7134
7135 gcmkPRINT_N(4, " read0 = 0x%08X\n", read0);
7136 gcmkPRINT_N(4, " read1 = 0x%08X\n", read1);
7137 gcmkPRINT_N(4, " write = 0x%08X\n", write);
7138 }
7139
7140 /* Restore control. */
7141 gcmkONERROR(gckOS_WriteRegisterEx(os, core, 0x0, oldControl));
7142
7143 gcmkPRINT_N(0, "**************************\n");
7144 gcmkPRINT_N(0, "***** SW COUNTERS *****\n");
7145 gcmkPRINT_N(0, "**************************\n");
7146 gcmkPRINT_N(4, " Execute Count = 0x%08X\n", Hardware->executeCount);
7147 gcmkPRINT_N(4, " Execute Addr = 0x%08X\n", Hardware->lastExecuteAddress);
7148 gcmkPRINT_N(4, " End Addr = 0x%08X\n", Hardware->lastEnd);
7149
7150 /* dump stack. */
7151 gckOS_DumpCallStack(os);
7152
7153OnError:
7154
7155 /* Return the error. */
7156 gcmkFOOTER();
7157 return status;
7158}
7159
7160static gceSTATUS
7161gckHARDWARE_ReadPerformanceRegister(
7162 IN gckHARDWARE Hardware,
7163 IN gctUINT PerformanceAddress,
7164 IN gctUINT IndexAddress,
7165 IN gctUINT IndexShift,
7166 IN gctUINT Index,
7167 OUT gctUINT32_PTR Value
7168 )
7169{
7170 gceSTATUS status;
7171
7172 gcmkHEADER_ARG("Hardware=0x%x PerformanceAddress=0x%x IndexAddress=0x%x "
7173 "IndexShift=%u Index=%u",
7174 Hardware, PerformanceAddress, IndexAddress, IndexShift,
7175 Index);
7176
7177 /* Write the index. */
7178 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7179 Hardware->core,
7180 IndexAddress,
7181 Index << IndexShift));
7182
7183 /* Read the register. */
7184 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7185 Hardware->core,
7186 PerformanceAddress,
7187 Value));
7188
7189 /* Test for reset. */
7190 if (Index == 15)
7191 {
7192 /* Index another register to get out of reset. */
7193 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os, Hardware->core, IndexAddress, 0));
7194 }
7195
7196 /* Success. */
7197 gcmkFOOTER_ARG("*Value=0x%x", *Value);
7198 return gcvSTATUS_OK;
7199
7200OnError:
7201 /* Return the status. */
7202 gcmkFOOTER();
7203 return status;
7204}
7205
7206gceSTATUS
7207gckHARDWARE_GetFrameInfo(
7208 IN gckHARDWARE Hardware,
7209 OUT gcsHAL_FRAME_INFO * FrameInfo
7210 )
7211{
7212 gceSTATUS status;
7213 gctUINT i, clock;
7214 gcsHAL_FRAME_INFO info;
7215#if gcdFRAME_DB_RESET
7216 gctUINT reset;
7217#endif
7218
7219 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
7220
7221 /* Get profile tick. */
7222 gcmkONERROR(gckOS_GetProfileTick(&info.ticks));
7223
7224 /* Read SH counters and reset them. */
7225 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7226 Hardware,
7227 0x0045C,
7228 0x00470,
7229 24,
7230 4,
7231 &info.shaderCycles));
7232 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7233 Hardware,
7234 0x0045C,
7235 0x00470,
7236 24,
7237 9,
7238 &info.vsInstructionCount));
7239 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7240 Hardware,
7241 0x0045C,
7242 0x00470,
7243 24,
7244 12,
7245 &info.vsTextureCount));
7246 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7247 Hardware,
7248 0x0045C,
7249 0x00470,
7250 24,
7251 7,
7252 &info.psInstructionCount));
7253 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7254 Hardware,
7255 0x0045C,
7256 0x00470,
7257 24,
7258 14,
7259 &info.psTextureCount));
7260#if gcdFRAME_DB_RESET
7261 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7262 Hardware,
7263 0x0045C,
7264 0x00470,
7265 24,
7266 15,
7267 &reset));
7268#endif
7269
7270 /* Read PA counters and reset them. */
7271 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7272 Hardware,
7273 0x00460,
7274 0x00474,
7275 0,
7276 3,
7277 &info.vertexCount));
7278 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7279 Hardware,
7280 0x00460,
7281 0x00474,
7282 0,
7283 4,
7284 &info.primitiveCount));
7285 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7286 Hardware,
7287 0x00460,
7288 0x00474,
7289 0,
7290 7,
7291 &info.rejectedPrimitives));
7292 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7293 Hardware,
7294 0x00460,
7295 0x00474,
7296 0,
7297 8,
7298 &info.culledPrimitives));
7299 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7300 Hardware,
7301 0x00460,
7302 0x00474,
7303 0,
7304 6,
7305 &info.clippedPrimitives));
7306 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7307 Hardware,
7308 0x00460,
7309 0x00474,
7310 0,
7311 5,
7312 &info.outPrimitives));
7313#if gcdFRAME_DB_RESET
7314 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7315 Hardware,
7316 0x00460,
7317 0x00474,
7318 0,
7319 15,
7320 &reset));
7321#endif
7322
7323 /* Read RA counters and reset them. */
7324 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7325 Hardware,
7326 0x00448,
7327 0x00474,
7328 16,
7329 3,
7330 &info.inPrimitives));
7331 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7332 Hardware,
7333 0x00448,
7334 0x00474,
7335 16,
7336 11,
7337 &info.culledQuadCount));
7338 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7339 Hardware,
7340 0x00448,
7341 0x00474,
7342 16,
7343 1,
7344 &info.totalQuadCount));
7345 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7346 Hardware,
7347 0x00448,
7348 0x00474,
7349 16,
7350 2,
7351 &info.quadCount));
7352 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7353 Hardware,
7354 0x00448,
7355 0x00474,
7356 16,
7357 0,
7358 &info.totalPixelCount));
7359#if gcdFRAME_DB_RESET
7360 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7361 Hardware,
7362 0x00448,
7363 0x00474,
7364 16,
7365 15,
7366 &reset));
7367#endif
7368
7369 /* Read TX counters and reset them. */
7370 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7371 Hardware,
7372 0x0044C,
7373 0x00474,
7374 24,
7375 0,
7376 &info.bilinearRequests));
7377 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7378 Hardware,
7379 0x0044C,
7380 0x00474,
7381 24,
7382 1,
7383 &info.trilinearRequests));
7384 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7385 Hardware,
7386 0x0044C,
7387 0x00474,
7388 24,
7389 8,
7390 &info.txHitCount));
7391 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7392 Hardware,
7393 0x0044C,
7394 0x00474,
7395 24,
7396 9,
7397 &info.txMissCount));
7398 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7399 Hardware,
7400 0x0044C,
7401 0x00474,
7402 24,
7403 6,
7404 &info.txBytes8));
7405#if gcdFRAME_DB_RESET
7406 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7407 Hardware,
7408 0x0044C,
7409 0x00474,
7410 24,
7411 15,
7412 &reset));
7413#endif
7414
7415 /* Read clock control register. */
7416 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7417 Hardware->core,
7418 0x00000,
7419 &clock));
7420
7421 /* Walk through all avaiable pixel pipes. */
7422 for (i = 0; i < Hardware->identity.pixelPipes; ++i)
7423 {
7424 /* Select proper pipe. */
7425 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7426 Hardware->core,
7427 0x00000,
7428 ((((gctUINT32) (clock)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20))) | (((gctUINT32) ((gctUINT32) (i) & ((gctUINT32) ((((1 ? 23:20) - (0 ? 23:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:20) - (0 ? 23:20) + 1))))))) << (0 ? 23:20)))));
7429
7430 /* Read cycle registers. */
7431 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7432 Hardware->core,
7433 0x00078,
7434 &info.cycles[i]));
7435 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7436 Hardware->core,
7437 0x0007C,
7438 &info.idleCycles[i]));
7439 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7440 Hardware->core,
7441 0x00438,
7442 &info.mcCycles[i]));
7443
7444 /* Read bandwidth registers. */
7445 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7446 Hardware->core,
7447 0x0005C,
7448 &info.readRequests[i]));
7449 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7450 Hardware->core,
7451 0x00040,
7452 &info.readBytes8[i]));
7453 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7454 Hardware->core,
7455 0x00050,
7456 &info.writeRequests[i]));
7457 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7458 Hardware->core,
7459 0x00044,
7460 &info.writeBytes8[i]));
7461
7462 /* Read PE counters. */
7463 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7464 Hardware,
7465 0x00454,
7466 0x00470,
7467 16,
7468 0,
7469 &info.colorKilled[i]));
7470 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7471 Hardware,
7472 0x00454,
7473 0x00470,
7474 16,
7475 2,
7476 &info.colorDrawn[i]));
7477 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7478 Hardware,
7479 0x00454,
7480 0x00470,
7481 16,
7482 1,
7483 &info.depthKilled[i]));
7484 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7485 Hardware,
7486 0x00454,
7487 0x00470,
7488 16,
7489 3,
7490 &info.depthDrawn[i]));
7491 }
7492
7493 /* Zero out remaning reserved counters. */
7494 for (; i < 8; ++i)
7495 {
7496 info.readBytes8[i] = 0;
7497 info.writeBytes8[i] = 0;
7498 info.cycles[i] = 0;
7499 info.idleCycles[i] = 0;
7500 info.mcCycles[i] = 0;
7501 info.readRequests[i] = 0;
7502 info.writeRequests[i] = 0;
7503 info.colorKilled[i] = 0;
7504 info.colorDrawn[i] = 0;
7505 info.depthKilled[i] = 0;
7506 info.depthDrawn[i] = 0;
7507 }
7508
7509 /* Reset clock control register. */
7510 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7511 Hardware->core,
7512 0x00000,
7513 clock));
7514
7515 /* Reset cycle and bandwidth counters. */
7516 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7517 Hardware->core,
7518 0x0003C,
7519 1));
7520 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7521 Hardware->core,
7522 0x0003C,
7523 0));
7524 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7525 Hardware->core,
7526 0x00078,
7527 0));
7528
7529#if gcdFRAME_DB_RESET
7530 /* Reset PE counters. */
7531 gcmkONERROR(gckHARDWARE_ReadPerformanceRegister(
7532 Hardware,
7533 0x00454,
7534 0x00470,
7535 16,
7536 15,
7537 &reset));
7538#endif
7539
7540 /* Copy to user. */
7541 gcmkONERROR(gckOS_CopyToUserData(Hardware->os,
7542 &info,
7543 FrameInfo,
7544 gcmSIZEOF(info)));
7545
7546 /* Success. */
7547 gcmkFOOTER_NO();
7548 return gcvSTATUS_OK;
7549
7550OnError:
7551 /* Return the status. */
7552 gcmkFOOTER();
7553 return status;
7554}
7555
7556#if gcdDVFS
7557#define READ_FROM_EATER1 0
7558
7559gceSTATUS
7560gckHARDWARE_QueryLoad(
7561 IN gckHARDWARE Hardware,
7562 OUT gctUINT32 * Load
7563 )
7564{
7565 gctUINT32 debug1;
7566 gceSTATUS status;
7567 gcmkHEADER_ARG("Hardware=0x%X", Hardware);
7568
7569 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
7570 gcmkVERIFY_ARGUMENT(Load != gcvNULL);
7571
7572 gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
7573
7574 if (Hardware->chipPowerState == gcvPOWER_ON)
7575 {
7576 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7577 Hardware->core,
7578 0x00110,
7579 Load));
7580#if READ_FROM_EATER1
7581 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7582 Hardware->core,
7583 0x00134,
7584 Load));
7585#endif
7586
7587 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7588 Hardware->core,
7589 0x00114,
7590 &debug1));
7591
7592 /* Patch result of 0x110 with result of 0x114. */
7593 if ((debug1 & 0xFF) == 1)
7594 {
7595 *Load &= ~0xFF;
7596 *Load |= 1;
7597 }
7598
7599 if (((debug1 & 0xFF00) >> 8) == 1)
7600 {
7601 *Load &= ~(0xFF << 8);
7602 *Load |= 1 << 8;
7603 }
7604
7605 if (((debug1 & 0xFF0000) >> 16) == 1)
7606 {
7607 *Load &= ~(0xFF << 16);
7608 *Load |= 1 << 16;
7609 }
7610
7611 if (((debug1 & 0xFF000000) >> 24) == 1)
7612 {
7613 *Load &= ~(0xFF << 24);
7614 *Load |= 1 << 24;
7615 }
7616 }
7617 else
7618 {
7619 status = gcvSTATUS_INVALID_REQUEST;
7620 }
7621
7622OnError:
7623
7624 gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
7625
7626 gcmkFOOTER();
7627 return status;
7628}
7629
7630gceSTATUS
7631gckHARDWARE_SetDVFSPeroid(
7632 IN gckHARDWARE Hardware,
7633 OUT gctUINT32 Frequency
7634 )
7635{
7636 gceSTATUS status;
7637 gctUINT32 period;
7638 gctUINT32 eater;
7639
7640#if READ_FROM_EATER1
7641 gctUINT32 period1;
7642 gctUINT32 eater1;
7643#endif
7644
7645 gcmkHEADER_ARG("Hardware=0x%X Frequency=%d", Hardware, Frequency);
7646
7647 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
7648
7649 period = 0;
7650
7651 while((64 << period) < (gcdDVFS_ANAYLSE_WINDOW * Frequency * 1000) )
7652 {
7653 period++;
7654 }
7655
7656#if READ_FROM_EATER1
7657 /*
7658 * Peroid = F * 1000 * 1000 / (60 * 16 * 1024);
7659 */
7660 period1 = Frequency * 6250 / 6114;
7661#endif
7662
7663 gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
7664
7665 if (Hardware->chipPowerState == gcvPOWER_ON)
7666 {
7667 /* Get current configure. */
7668 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7669 Hardware->core,
7670 0x0010C,
7671 &eater));
7672
7673 /* Change peroid. */
7674 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7675 Hardware->core,
7676 0x0010C,
7677 ((((gctUINT32) (eater)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8))) | (((gctUINT32) ((gctUINT32) (period) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1))))))) << (0 ? 15:8)))));
7678
7679#if READ_FROM_EATER1
7680 /* Config eater1. */
7681 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7682 Hardware->core,
7683 0x00130,
7684 &eater1));
7685
7686 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7687 Hardware->core,
7688 0x00130,
7689 ((((gctUINT32) (eater1)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1))))))) << (0 ? 31:16))) | (((gctUINT32) ((gctUINT32) (period1) & ((gctUINT32) ((((1 ? 31:16) - (0 ? 31:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:16) - (0 ? 31:16) + 1))))))) << (0 ? 31:16)))));
7690#endif
7691 }
7692 else
7693 {
7694 status = gcvSTATUS_INVALID_REQUEST;
7695 }
7696
7697OnError:
7698 gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
7699
7700 gcmkFOOTER();
7701 return status;
7702}
7703
7704gceSTATUS
7705gckHARDWARE_InitDVFS(
7706 IN gckHARDWARE Hardware
7707 )
7708{
7709 gceSTATUS status;
7710 gctUINT32 data;
7711
7712 gcmkHEADER_ARG("Hardware=0x%X", Hardware);
7713
7714 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
7715
7716 gcmkONERROR(gckOS_ReadRegisterEx(Hardware->os,
7717 Hardware->core,
7718 0x0010C,
7719 &data));
7720
7721 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16)));
7722 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1))))))) << (0 ? 18:18)));
7723 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
7724 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
7725 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 23:23) - (0 ? 23:23) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 23:23) - (0 ? 23:23) + 1))))))) << (0 ? 23:23)));
7726 data = ((((gctUINT32) (data)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 22:22) - (0 ? 22:22) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 22:22) - (0 ? 22:22) + 1))))))) << (0 ? 22:22)));
7727
7728 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
7729 "DVFS Configure=0x%X",
7730 data);
7731
7732 gcmkONERROR(gckOS_WriteRegisterEx(Hardware->os,
7733 Hardware->core,
7734 0x0010C,
7735 data));
7736
7737 gcmkFOOTER_NO();
7738 return gcvSTATUS_OK;
7739
7740OnError:
7741 gcmkFOOTER();
7742 return status;
7743}
7744#endif
7745
7746/*******************************************************************************
7747**
7748** gckHARDWARE_PrepareFunctions
7749**
7750** Generate command buffer snippets which will be used by gckHARDWARE, by which
7751** gckHARDWARE can manipulate GPU by FE command without using gckCOMMAND to avoid
7752** race condition and deadlock.
7753**
7754** Notice:
7755** 1. Each snippet can only be executed when GPU is idle.
7756** 2. Execution is triggered by AHB (0x658)
7757** 3. Each snippet followed by END so software can sync with GPU by checking GPU
7758** idle
7759** 4. It is transparent to gckCOMMAND command buffer.
7760**
7761** Existing Snippets:
7762** 1. MMU Configure
7763** For new MMU, after GPU is reset, FE execute this command sequence to enble MMU.
7764*/
7765gceSTATUS
7766gckHARDWARE_PrepareFunctions(
7767 gckHARDWARE Hardware
7768 )
7769{
7770 gceSTATUS status;
7771 gckOS os;
7772 gctUINT32 offset = 0;
7773 gctUINT32 mmuBytes;
7774 gctUINT32 endBytes;
7775 gctUINT8_PTR logical;
7776 gctPHYS_ADDR_T physical;
7777
7778 gcmkHEADER_ARG("%x", Hardware);
7779
7780 os = Hardware->os;
7781
7782 gcmkVERIFY_OK(gckOS_GetPageSize(os, &Hardware->functionBytes));
7783
7784 /* Allocate a command buffer. */
7785 gcmkONERROR(gckOS_AllocateNonPagedMemory(
7786 os,
7787 gcvFALSE,
7788 &Hardware->functionBytes,
7789 &Hardware->functionPhysical,
7790 &Hardware->functionLogical
7791 ));
7792
7793 gcmkONERROR(gckOS_GetPhysicalAddress(
7794 os,
7795 Hardware->functionLogical,
7796 &physical
7797 ));
7798
7799 gcmkSAFECASTPHYSADDRT(Hardware->functionAddress, physical);
7800
7801 if (Hardware->mmuVersion > 0)
7802 {
7803 /* MMU configure command sequence. */
7804 logical = (gctUINT8_PTR)Hardware->functionLogical + offset;
7805
7806 Hardware->functions[gcvHARDWARE_FUNCTION_MMU].address
7807 = Hardware->functionAddress + offset;
7808
7809 gcmkONERROR(gckHARDWARE_SetMMUStates(
7810 Hardware,
7811 Hardware->kernel->mmu->mtlbLogical,
7812 gcvMMU_MODE_4K,
7813 (gctUINT8_PTR)Hardware->kernel->mmu->mtlbLogical + gcdMMU_MTLB_SIZE,
7814 logical,
7815 &mmuBytes
7816 ));
7817
7818 offset += mmuBytes;
7819
7820 logical = (gctUINT8_PTR)Hardware->functionLogical + offset;
7821
7822 gcmkONERROR(gckHARDWARE_End(
7823 Hardware,
7824 gcvNULL,
7825 &endBytes
7826 ));
7827
7828 gcmkONERROR(gckHARDWARE_End(
7829 Hardware,
7830 logical,
7831 &endBytes
7832 ));
7833
7834 offset += endBytes;
7835
7836 Hardware->functions[gcvHARDWARE_FUNCTION_MMU].bytes = mmuBytes + endBytes;
7837
7838 Hardware->functions[gcvHARDWARE_FUNCTION_MMU].endAddress =
7839 Hardware->functions[gcvHARDWARE_FUNCTION_MMU].address + mmuBytes;
7840
7841 Hardware->functions[gcvHARDWARE_FUNCTION_MMU].endLogical =
7842 logical + mmuBytes;
7843 }
7844
7845 gcmkASSERT(offset < Hardware->functionBytes);
7846
7847 gcmkFOOTER_NO();
7848 return gcvSTATUS_OK;
7849
7850OnError:
7851 gcmkFOOTER();
7852 return status;
7853}
7854
7855gceSTATUS
7856gckHARDWARE_AddressInHardwareFuncions(
7857 IN gckHARDWARE Hardware,
7858 IN gctUINT32 Address,
7859 OUT gctPOINTER *Pointer
7860 )
7861{
7862 if (Address >= Hardware->functionAddress && Address <= Hardware->functionAddress - 1 + Hardware->functionBytes)
7863 {
7864 *Pointer = (gctUINT8_PTR)Hardware->functionLogical
7865 + (Address - Hardware->functionAddress)
7866 ;
7867
7868 return gcvSTATUS_OK;
7869 }
7870
7871 return gcvSTATUS_NOT_FOUND;
7872}
7873
7874gceSTATUS
7875gckHARDWARE_QueryStateTimer(
7876 IN gckHARDWARE Hardware,
7877 OUT gctUINT64_PTR Start,
7878 OUT gctUINT64_PTR End,
7879 OUT gctUINT64_PTR On,
7880 OUT gctUINT64_PTR Off,
7881 OUT gctUINT64_PTR Idle,
7882 OUT gctUINT64_PTR Suspend
7883 )
7884{
7885 gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, gcvINFINITE);
7886
7887 gckSTATETIMER_Query(
7888 &Hardware->powerStateTimer, Hardware->chipPowerState, Start, End, On, Off, Idle, Suspend);
7889
7890 gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
7891
7892 return gcvSTATUS_OK;
7893}
7894
diff --git a/src/hal/kernel/arch/gc_hal_kernel_hardware.h b/src/hal/kernel/arch/gc_hal_kernel_hardware.h
new file mode 100755
index 0000000..68732d0
--- /dev/null
+++ b/src/hal/kernel/arch/gc_hal_kernel_hardware.h
@@ -0,0 +1,210 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_hardware_h_
57#define __gc_hal_kernel_hardware_h_
58
59
60#ifdef __cplusplus
61extern "C" {
62#endif
63
64typedef enum {
65 gcvHARDWARE_FUNCTION_MMU,
66 gcvHARDWARE_FUNCTION_FLUSH,
67
68 gcvHARDWARE_FUNCTION_NUM,
69}
70gceHARDWARE_FUNCTION;
71
72
73typedef struct _gcsHARWARE_FUNCTION
74{
75 /* Entry of the function. */
76 gctUINT32 address;
77
78 /* Bytes of the function. */
79 gctUINT32 bytes;
80
81 /* Hardware address of END in this function. */
82 gctUINT32 endAddress;
83
84 /* Logical of END in this function. */
85 gctUINT8_PTR endLogical;
86}
87gcsHARDWARE_FUNCTION;
88
89typedef struct _gcsSTATETIMER
90{
91 gctUINT64 start;
92 gctUINT64 recent;
93
94 /* Elapse of each power state. */
95 gctUINT64 elapse[4];
96}
97gcsSTATETIMER;
98
99/* gckHARDWARE object. */
100struct _gckHARDWARE
101{
102 /* Object. */
103 gcsOBJECT object;
104
105 /* Pointer to gctKERNEL object. */
106 gckKERNEL kernel;
107
108 /* Pointer to gctOS object. */
109 gckOS os;
110
111 /* Core */
112 gceCORE core;
113
114 /* Chip characteristics. */
115 gcsHAL_QUERY_CHIP_IDENTITY identity;
116 gctBOOL allowFastClear;
117 gctBOOL allowCompression;
118 gctUINT32 powerBaseAddress;
119 gctBOOL extraEventStates;
120
121 /* Big endian */
122 gctBOOL bigEndian;
123
124 /* Chip status */
125 gctPOINTER powerMutex;
126 gctUINT32 powerProcess;
127 gctUINT32 powerThread;
128 gceCHIPPOWERSTATE chipPowerState;
129 gctUINT32 lastWaitLink;
130 gctUINT32 lastEnd;
131 gctBOOL clockState;
132 gctBOOL powerState;
133 gctPOINTER globalSemaphore;
134
135 gctISRMANAGERFUNC startIsr;
136 gctISRMANAGERFUNC stopIsr;
137 gctPOINTER isrContext;
138
139 gctUINT32 mmuVersion;
140
141 /* Whether use new MMU. It is meaningless
142 ** for old MMU since old MMU is always enabled.
143 */
144 gctBOOL enableMMU;
145
146 /* Type */
147 gceHARDWARE_TYPE type;
148
149#if gcdPOWEROFF_TIMEOUT
150 gctUINT32 powerOffTime;
151 gctUINT32 powerOffTimeout;
152 gctPOINTER powerOffTimer;
153#endif
154
155#if gcdENABLE_FSCALE_VAL_ADJUST
156 gctUINT32 powerOnFscaleVal;
157#endif
158 gctPOINTER pageTableDirty;
159
160#if gcdLINK_QUEUE_SIZE
161 struct _gckLINKQUEUE linkQueue;
162#endif
163
164 gctBOOL powerManagement;
165 gctBOOL gpuProfiler;
166
167 gctBOOL endAfterFlushMmuCache;
168
169 gctUINT32 minFscaleValue;
170
171 gctPOINTER pendingEvent;
172
173 /* Function used by gckHARDWARE. */
174 gctPHYS_ADDR functionPhysical;
175 gctPOINTER functionLogical;
176 gctUINT32 functionAddress;
177 gctSIZE_T functionBytes;
178
179 gcsHARDWARE_FUNCTION functions[gcvHARDWARE_FUNCTION_NUM];
180
181 gcsSTATETIMER powerStateTimer;
182 gctUINT32 executeCount;
183 gctUINT32 lastExecuteAddress;
184};
185
186gceSTATUS
187gckHARDWARE_GetBaseAddress(
188 IN gckHARDWARE Hardware,
189 OUT gctUINT32_PTR BaseAddress
190 );
191
192gceSTATUS
193gckHARDWARE_NeedBaseAddress(
194 IN gckHARDWARE Hardware,
195 IN gctUINT32 State,
196 OUT gctBOOL_PTR NeedBase
197 );
198
199gceSTATUS
200gckHARDWARE_GetFrameInfo(
201 IN gckHARDWARE Hardware,
202 OUT gcsHAL_FRAME_INFO * FrameInfo
203 );
204
205#ifdef __cplusplus
206}
207#endif
208
209#endif /* __gc_hal_kernel_hardware_h_ */
210
diff --git a/src/hal/kernel/arch/gc_hal_kernel_recorder.c b/src/hal/kernel/arch/gc_hal_kernel_recorder.c
new file mode 100755
index 0000000..540d9e8
--- /dev/null
+++ b/src/hal/kernel/arch/gc_hal_kernel_recorder.c
@@ -0,0 +1,713 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal.h"
57#include "gc_hal_kernel.h"
58#include "gc_hal_kernel_context.h"
59
60/*
61 * -----------------------
62 * HARDWARE STATE RECORDER
63 * -----------------------
64 *
65 * State mirror buffer is used to 'mirror' hardware states since hardware
66 * states can't be dumpped. It is a context buffer which stores 'global'
67 * context.
68 *
69 * For each commit, state recorder
70 * 1) Records context buffer (if there is) and command buffers in this commit.
71 * 2) Parse those buffers to estimate the state changed.
72 * 3) Stores result to a mirror buffer.
73 *
74 * == Commit 0 ====================================================================
75 *
76 * Context Buffer 0
77 *
78 * Command Buffer 0
79 *
80 * Mirror Buffer 0 <- Context Buffer 0 + Command Buffer 0
81 *
82 * == Commit 1 ====================================================================
83 *
84 * Command Buffer 1
85 *
86 * Mirror Buffer 1 <- Command buffer 1 + Mirror Buffer 0
87 *
88 * == Commit 2 ====================================================================
89 *
90 * Context Buffer 2 (optional)
91 *
92 * Command Buffer 2
93 *
94 * Mirror Buffer 2 <- Command buffer 2 + Context Buffer 2 + Mirror Buffer 1
95 *
96 * == Commit N ====================================================================
97 *
98 * For Commit N, these buffers are needed to reproduce hardware's behavior in
99 * this commit.
100 *
101 * Mirror Buffer [N - 1] : State Mirror accumlated by past commits,
102 * which is used to restore hardware state.
103 * Context Buffer [N] :
104 * Command Buffer [N] : Command buffer executed by hardware in this commit.
105 *
106 * If sequence of states programming matters, hardware's behavior can't be reproduced,
107 * but the state values stored in mirror buffer are assuring.
108 */
109
110/* Queue size. */
111#define gcdNUM_RECORDS 6
112
113typedef struct _gcsPARSER_HANDLER * gckPARSER_HANDLER;
114
115typedef void
116(*HandlerFunction)(
117 IN gckPARSER_HANDLER Handler,
118 IN gctUINT32 Addr,
119 IN gctUINT32 Data
120 );
121
122typedef struct _gcsPARSER_HANDLER
123{
124 gctUINT32 type;
125 gctUINT32 cmd;
126 gctPOINTER private;
127 HandlerFunction function;
128}
129gcsPARSER_HANDLER;
130
131typedef struct _gcsPARSER * gckPARSER;
132typedef struct _gcsPARSER
133{
134 gctUINT8_PTR currentCmdBufferAddr;
135
136 /* Current command. */
137 gctUINT32 lo;
138 gctUINT32 hi;
139
140 gctUINT8 cmdOpcode;
141 gctUINT16 cmdAddr;
142 gctUINT32 cmdSize;
143 gctUINT32 cmdRectCount;
144 gctUINT8 skip;
145 gctUINT32 skipCount;
146
147 gctBOOL allow;
148
149 /* Callback used by parser to handle a command. */
150 gckPARSER_HANDLER commandHandler;
151}
152gcsPARSER;
153
154typedef struct _gcsMIRROR
155{
156 gctUINT32_PTR logical[gcdNUM_RECORDS];
157 gctUINT32 bytes;
158 gcsSTATE_MAP_PTR map;
159 gctUINT32 maxState;
160}
161gcsMIRROR;
162
163typedef struct _gcsDELTA
164{
165 gctUINT64 commitStamp;
166 gctUINT32_PTR command;
167 gctUINT32 commandBytes;
168 gctUINT32_PTR context;
169 gctUINT32 contextBytes;
170}
171gcsDELTA;
172
173typedef struct _gcsRECORDER
174{
175 gckOS os;
176 gcsMIRROR mirror;
177 gcsDELTA deltas[gcdNUM_RECORDS];
178
179 /* Index of current record. */
180 gctUINT index;
181
182 /* Number of records. */
183 gctUINT num;
184
185 /* Plugin used by gckPARSER. */
186 gcsPARSER_HANDLER recorderHandler;
187 gckPARSER parser;
188}
189gcsRECORDER;
190
191
192/******************************************************************************\
193***************************** Command Buffer Parser ****************************
194\******************************************************************************/
195
196/*
197** Command buffer parser checks command buffer in FE's view to make sure there
198** is no format error.
199**
200** Parser provide a callback mechnisam, so plug-in can be added to implement
201** other functions.
202*/
203
204static void
205_HandleLoadState(
206 IN OUT gckPARSER Parser
207 )
208{
209 gctUINT i;
210 gctUINT32_PTR data = (gctUINT32_PTR)Parser->currentCmdBufferAddr;
211 gctUINT32 cmdAddr = Parser->cmdAddr;
212
213 if (Parser->commandHandler == gcvNULL
214 || Parser->commandHandler->cmd != 0x01
215 )
216 {
217 /* No handler for this command. */
218 return;
219 }
220
221 for (i = 0; i < Parser->cmdSize; i++)
222 {
223 Parser->commandHandler->function(Parser->commandHandler, cmdAddr, *data);
224
225 /* Advance to next state. */
226 cmdAddr++;
227 data++;
228 }
229}
230
231static void
232_GetCommand(
233 IN OUT gckPARSER Parser
234 )
235{
236 gctUINT32 * buffer = (gctUINT32 *)Parser->currentCmdBufferAddr;
237
238 gctUINT16 cmdRectCount;
239 gctUINT16 cmdDataCount;
240
241 Parser->hi = buffer[0];
242 Parser->lo = buffer[1];
243
244 Parser->cmdOpcode = (((((gctUINT32) (Parser->hi)) >> (0 ? 31:27)) & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1)))))) );
245 Parser->cmdRectCount = 1;
246
247 switch (Parser->cmdOpcode)
248 {
249 case 0x01:
250 /* Extract count. */
251 Parser->cmdSize = (((((gctUINT32) (Parser->hi)) >> (0 ? 25:16)) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1)))))) );
252 if (Parser->cmdSize == 0)
253 {
254 /* 0 means 1024. */
255 Parser->cmdSize = 1024;
256 }
257 Parser->skip = (Parser->cmdSize & 0x1) ? 0 : 1;
258
259 /* Extract address. */
260 Parser->cmdAddr = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:0)) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1)))))) );
261
262 Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 4;
263 Parser->skipCount = Parser->cmdSize + Parser->skip;
264 break;
265
266 case 0x05:
267 Parser->cmdSize = 4;
268 Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
269 break;
270
271 case 0x06:
272 Parser->cmdSize = 5;
273 Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
274 break;
275
276 case 0x0C:
277 Parser->cmdSize = 3;
278 Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
279 break;
280
281 case 0x09:
282 Parser->cmdSize = 2;
283 Parser->cmdAddr = 0x0F16;
284 Parser->skipCount = gcmALIGN(Parser->cmdSize, 2);
285 break;
286
287 case 0x04:
288 Parser->cmdSize = 1;
289 Parser->cmdAddr = 0x0F06;
290
291 cmdRectCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 15:8)) & ((gctUINT32) ((((1 ? 15:8) - (0 ? 15:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:8) - (0 ? 15:8) + 1)))))) );
292 cmdDataCount = (((((gctUINT32) (Parser->hi)) >> (0 ? 26:16)) & ((gctUINT32) ((((1 ? 26:16) - (0 ? 26:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 26:16) - (0 ? 26:16) + 1)))))) );
293
294 Parser->skipCount = gcmALIGN(Parser->cmdSize, 2)
295 + cmdRectCount * 2
296 + gcmALIGN(cmdDataCount, 2);
297
298 Parser->cmdRectCount = cmdRectCount;
299 break;
300
301 case 0x03:
302 Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
303 Parser->skipCount = 0;
304 break;
305
306 case 0x02:
307 Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr + 8;
308 Parser->skipCount = 0;
309 break;
310
311 default:
312 /* Unknown command is a risk. */
313 Parser->allow = gcvFALSE;
314 break;
315 }
316}
317
318static void
319_ParseCommand(
320 IN OUT gckPARSER Parser
321 )
322{
323 switch(Parser->cmdOpcode)
324 {
325 case 0x01:
326 _HandleLoadState(Parser);
327 break;
328 case 0x05:
329 case 0x06:
330 case 0x0C:
331 break;
332 case 0x04:
333 break;
334 default:
335 break;
336 }
337
338 /* Advance to next command. */
339 Parser->currentCmdBufferAddr = Parser->currentCmdBufferAddr
340 + (Parser->skipCount << 2);
341}
342
343gceSTATUS
344gckPARSER_Parse(
345 IN gckPARSER Parser,
346 IN gctUINT8_PTR Buffer,
347 IN gctUINT32 Bytes
348 )
349{
350 gckPARSER parser = Parser;
351 gctUINT8_PTR end = (gctUINT8_PTR)Buffer + Bytes;
352
353 /* Initialize parser. */
354 parser->currentCmdBufferAddr = (gctUINT8_PTR)Buffer;
355 parser->skip = 0;
356 parser->allow = gcvTRUE;
357
358 /* Go through command buffer until reaching the end
359 ** or meeting an error. */
360 do
361 {
362 _GetCommand(parser);
363
364 _ParseCommand(parser);
365 }
366 while ((parser->currentCmdBufferAddr < end) && (parser->allow == gcvTRUE));
367
368 if (parser->allow == gcvFALSE)
369 {
370 /* Error detected. */
371 return gcvSTATUS_NOT_SUPPORTED;
372 }
373
374 return gcvSTATUS_OK;
375}
376
377/*******************************************************************************
378**
379** gckPARSER_RegisterCommandHandler
380**
381** Register a command handler which will be called when parser get a command.
382**
383*/
384gceSTATUS
385gckPARSER_RegisterCommandHandler(
386 IN gckPARSER Parser,
387 IN gckPARSER_HANDLER Handler
388 )
389{
390 Parser->commandHandler = Handler;
391
392 return gcvSTATUS_OK;
393}
394
395gceSTATUS
396gckPARSER_Construct(
397 IN gckOS Os,
398 IN gckPARSER_HANDLER Handler,
399 OUT gckPARSER * Parser
400 )
401{
402 gceSTATUS status;
403 gckPARSER pointer;
404
405 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsPARSER), (gctPOINTER *)&pointer));
406
407 /* Put it here temp, should have a more general plug-in mechnisam. */
408 pointer->commandHandler = Handler;
409
410 *Parser = pointer;
411
412 return gcvSTATUS_OK;
413
414OnError:
415 return status;
416}
417
418void
419gckPARSER_Destroy(
420 IN gckOS Os,
421 IN gckPARSER Parser
422 )
423{
424 gcmkOS_SAFE_FREE(Os, Parser);
425}
426
427/******************************************************************************\
428**************************** Hardware States Recorder **************************
429\******************************************************************************/
430
431static void
432_RecodeState(
433 IN gckPARSER_HANDLER Handler,
434 IN gctUINT32 Addr,
435 IN gctUINT32 Data
436 )
437{
438 gcmkVERIFY_OK(gckRECORDER_UpdateMirror(Handler->private, Addr, Data));
439}
440
441static gctUINT
442_Previous(
443 IN gctUINT Index
444 )
445{
446 if (Index == 0)
447 {
448 return gcdNUM_RECORDS - 1;
449 }
450
451 return Index - 1;
452}
453
454static gctUINT
455_Next(
456 IN gctUINT Index
457 )
458{
459 return (Index + 1) % gcdNUM_RECORDS;
460}
461
462gceSTATUS
463gckRECORDER_Construct(
464 IN gckOS Os,
465 IN gckHARDWARE Hardware,
466 OUT gckRECORDER * Recorder
467 )
468{
469 gceSTATUS status;
470 gckCONTEXT context = gcvNULL;
471 gckRECORDER recorder = gcvNULL;
472 gctUINT32 mapSize;
473 gctUINT i;
474 gctBOOL virtualCommandBuffer = Hardware->kernel->virtualCommandBuffer;
475
476 /* TODO: We only need context buffer and state map, it should be able to get without construct a
477 ** new context.
478 ** Now it is leaked, since we can't free it when command buffer is gone.
479 */
480
481 /* MMU is not ready now. */
482 Hardware->kernel->virtualCommandBuffer = gcvFALSE;
483
484 gcmkONERROR(gckCONTEXT_Construct(Os, Hardware, 0, &context));
485
486 /* Restore. */
487 Hardware->kernel->virtualCommandBuffer = virtualCommandBuffer;
488
489 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsRECORDER), (gctPOINTER *)&recorder));
490
491 gckOS_ZeroMemory(recorder, gcmSIZEOF(gcsRECORDER));
492
493 /* Copy state map. */
494 recorder->mirror.maxState = context->maxState;
495
496 mapSize = context->maxState * gcmSIZEOF(gcsSTATE_MAP);
497
498 gcmkONERROR(gckOS_Allocate(Os, mapSize, (gctPOINTER *)&recorder->mirror.map));
499
500 gckOS_MemCopy(recorder->mirror.map, context->map, mapSize);
501
502 /* Copy context buffer. */
503 recorder->mirror.bytes = context->totalSize;
504
505 for (i = 0; i < gcdNUM_RECORDS; i++)
506 {
507 gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->mirror.logical[i]));
508 gckOS_MemCopy(recorder->mirror.logical[i], context->buffer->logical, context->totalSize);
509 }
510
511 for (i = 0; i < gcdNUM_RECORDS; i++)
512 {
513 /* TODO : Optimize size. */
514 gcmkONERROR(gckOS_Allocate(Os, gcdCMD_BUFFER_SIZE, (gctPOINTER *)&recorder->deltas[i].command));
515 gcmkONERROR(gckOS_Allocate(Os, context->totalSize, (gctPOINTER *)&recorder->deltas[i].context));
516 }
517
518 recorder->index = 0;
519 recorder->num = 0;
520
521 /* Initialize Parser plugin. */
522 recorder->recorderHandler.cmd = 0x01;
523 recorder->recorderHandler.private = recorder;
524 recorder->recorderHandler.function = _RecodeState;
525
526 gcmkONERROR(gckPARSER_Construct(Os, &recorder->recorderHandler, &recorder->parser));
527
528 recorder->os = Os;
529
530 *Recorder = recorder;
531
532 return gcvSTATUS_OK;
533
534OnError:
535 if (recorder)
536 {
537 gckRECORDER_Destory(Os, recorder);
538 }
539
540 return status;
541}
542
543gceSTATUS
544gckRECORDER_Destory(
545 IN gckOS Os,
546 IN gckRECORDER Recorder
547 )
548{
549 gctUINT i;
550
551 if (Recorder->mirror.map)
552 {
553 gcmkOS_SAFE_FREE(Os, Recorder->mirror.map);
554 }
555
556 for (i = 0; i < gcdNUM_RECORDS; i++)
557 {
558 if (Recorder->mirror.logical[i])
559 {
560 gcmkOS_SAFE_FREE(Os, Recorder->mirror.logical[i]);
561 }
562 }
563
564 for (i = 0; i < gcdNUM_RECORDS; i++)
565 {
566 if (Recorder->deltas[i].command)
567 {
568 gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].command);
569 }
570
571 if (Recorder->deltas[i].context)
572 {
573 gcmkOS_SAFE_FREE(Os, Recorder->deltas[i].context);
574 }
575 }
576
577 if (Recorder->parser)
578 {
579 gckPARSER_Destroy(Os, Recorder->parser);
580 }
581
582 gcmkOS_SAFE_FREE(Os, Recorder);
583
584 return gcvSTATUS_OK;
585}
586
587gceSTATUS
588gckRECORDER_UpdateMirror(
589 IN gckRECORDER Recorder,
590 IN gctUINT32 State,
591 IN gctUINT32 Data
592 )
593{
594 gctUINT32 index;
595 gcsSTATE_MAP_PTR map = Recorder->mirror.map;
596 gctUINT32_PTR buffer = Recorder->mirror.logical[Recorder->index];
597
598 if (State >= Recorder->mirror.maxState)
599 {
600 /* Ignore them just like HW does. */
601 return gcvSTATUS_OK;
602 }
603
604 index = map[State].index;
605
606 if (index)
607 {
608 buffer[index] = Data;
609 }
610
611 return gcvSTATUS_OK;
612}
613
614void
615gckRECORDER_AdvanceIndex(
616 IN gckRECORDER Recorder,
617 IN gctUINT64 CommitStamp
618 )
619{
620 /* Get next record. */
621 gctUINT next = (Recorder->index + 1) % gcdNUM_RECORDS;
622
623 /* Record stamp of this commit. */
624 Recorder->deltas[Recorder->index].commitStamp = CommitStamp;
625
626 /* Mirror of next record is mirror of this record and delta in next record. */
627 gckOS_MemCopy(Recorder->mirror.logical[next],
628 Recorder->mirror.logical[Recorder->index], Recorder->mirror.bytes);
629
630 /* Advance to next record. */
631 Recorder->index = next;
632
633 Recorder->num = gcmMIN(Recorder->num + 1, gcdNUM_RECORDS - 1);
634
635
636 /* Reset delta. */
637 Recorder->deltas[Recorder->index].commandBytes = 0;
638 Recorder->deltas[Recorder->index].contextBytes = 0;
639}
640
641void
642gckRECORDER_Record(
643 IN gckRECORDER Recorder,
644 IN gctUINT8_PTR CommandBuffer,
645 IN gctUINT32 CommandBytes,
646 IN gctUINT8_PTR ContextBuffer,
647 IN gctUINT32 ContextBytes
648 )
649{
650 gcsDELTA * delta = &Recorder->deltas[Recorder->index];
651
652 if (CommandBytes != 0xFFFFFFFF)
653 {
654 gckPARSER_Parse(Recorder->parser, CommandBuffer, CommandBytes);
655 gckOS_MemCopy(delta->command, CommandBuffer, CommandBytes);
656 delta->commandBytes = CommandBytes;
657 }
658
659 if (ContextBytes != 0xFFFFFFFF)
660 {
661 gckPARSER_Parse(Recorder->parser, ContextBuffer, ContextBytes);
662 gckOS_MemCopy(delta->context, ContextBuffer, ContextBytes);
663 delta->contextBytes = ContextBytes;
664 }
665}
666
667void
668gckRECORDER_Dump(
669 IN gckRECORDER Recorder
670 )
671{
672 gctUINT last = Recorder->index;
673 gctUINT previous;
674 gctUINT i;
675 gcsMIRROR *mirror = &Recorder->mirror;
676 gcsDELTA *delta;
677 gckOS os = Recorder->os;
678
679 for (i = 0; i < Recorder->num; i++)
680 {
681 last = _Previous(last);
682 }
683
684 for (i = 0; i < Recorder->num; i++)
685 {
686 delta = &Recorder->deltas[last];
687
688 /* Dump record */
689 gcmkPRINT("#[commit %llu]", delta->commitStamp);
690
691 if (delta->commitStamp)
692 {
693 previous = _Previous(last);
694
695 gcmkPRINT("#[mirror]");
696 gckOS_DumpBuffer(os, mirror->logical[previous], mirror->bytes, gceDUMP_BUFFER_CONTEXT, gcvTRUE);
697 gcmkPRINT("@[kernel.execute]");
698 }
699
700 if (delta->contextBytes)
701 {
702 gckOS_DumpBuffer(os, delta->context, delta->contextBytes, gceDUMP_BUFFER_CONTEXT, gcvTRUE);
703 gcmkPRINT("@[kernel.execute]");
704 }
705
706 gckOS_DumpBuffer(os, delta->command, delta->commandBytes, gceDUMP_BUFFER_USER, gcvTRUE);
707 gcmkPRINT("@[kernel.execute]");
708
709 last = _Next(last);
710 }
711}
712
713
diff --git a/src/hal/kernel/arch/makefile b/src/hal/kernel/arch/makefile
new file mode 100755
index 0000000..caa3d18
--- /dev/null
+++ b/src/hal/kernel/arch/makefile
@@ -0,0 +1,57 @@
1##############################################################################
2#
3# The MIT License (MIT)
4#
5# Copyright (c) 2014 Vivante Corporation
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25##############################################################################
26#
27# The GPL License (GPL)
28#
29# Copyright (C) 2014 Vivante Corporation
30#
31# This program is free software; you can redistribute it and/or
32# modify it under the terms of the GNU General Public License
33# as published by the Free Software Foundation; either version 2
34# of the License, or (at your option) any later version.
35#
36# This program is distributed in the hope that it will be useful,
37# but WITHOUT ANY WARRANTY; without even the implied warranty of
38# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39# GNU General Public License for more details.
40#
41# You should have received a copy of the GNU General Public License
42# along with this program; if not, write to the Free Software Foundation,
43# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44#
45##############################################################################
46#
47# Note: This software is released under dual MIT and GPL licenses. A
48# recipient may use this file under the terms of either the MIT license or
49# GPL License. If you wish to use only one license not the other, you can
50# indicate your decision by deleting one of the above license notices in your
51# version of this file.
52#
53##############################################################################
54
55
56!INCLUDE $(_MAKEENVROOT)\makefile.def
57
diff --git a/src/hal/kernel/arch/makefile.linux b/src/hal/kernel/arch/makefile.linux
new file mode 100755
index 0000000..0132775
--- /dev/null
+++ b/src/hal/kernel/arch/makefile.linux
@@ -0,0 +1,88 @@
1##############################################################################
2#
3# The MIT License (MIT)
4#
5# Copyright (c) 2014 Vivante Corporation
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25##############################################################################
26#
27# The GPL License (GPL)
28#
29# Copyright (C) 2014 Vivante Corporation
30#
31# This program is free software; you can redistribute it and/or
32# modify it under the terms of the GNU General Public License
33# as published by the Free Software Foundation; either version 2
34# of the License, or (at your option) any later version.
35#
36# This program is distributed in the hope that it will be useful,
37# but WITHOUT ANY WARRANTY; without even the implied warranty of
38# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39# GNU General Public License for more details.
40#
41# You should have received a copy of the GNU General Public License
42# along with this program; if not, write to the Free Software Foundation,
43# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44#
45##############################################################################
46#
47# Note: This software is released under dual MIT and GPL licenses. A
48# recipient may use this file under the terms of either the MIT license or
49# GPL License. If you wish to use only one license not the other, you can
50# indicate your decision by deleting one of the above license notices in your
51# version of this file.
52#
53##############################################################################
54
55
56#
57# Linux build file for architecture dependent kernel HAL layer.
58#
59
60################################################################################
61# Include common definitions.
62
63include $(AQROOT)/makefile.linux.def
64
65################################################################################
66# Define a shortcut for the main target.
67
68STATIC = 1
69TARGET_NAME = libhalarchkernel.a
70
71################################################################################
72# Supply additional include directories.
73
74INCLUDE += -I$(AQROOT)/hal/kernel/inc
75INCLUDE += -I$(AQROOT)/hal/kernel/inc
76INCLUDE += -I$(AQROOT)/hal/kernel
77INCLUDE += -I$(AQROOT)/hal/kernel/arch
78
79CFLAGS += $(INCLUDE) -Werror -ansi
80
81
82################################################################################
83# Describe object files.
84
85OBJECTS = $(OBJ_DIR)/gc_hal_kernel_context.o \
86 $(OBJ_DIR)/gc_hal_kernel_hardware.o
87
88include $(AQROOT)/common.target
diff --git a/src/hal/kernel/arch/sources b/src/hal/kernel/arch/sources
new file mode 100755
index 0000000..ab91223
--- /dev/null
+++ b/src/hal/kernel/arch/sources
@@ -0,0 +1,71 @@
1##############################################################################
2#
3# The MIT License (MIT)
4#
5# Copyright (c) 2014 Vivante Corporation
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25##############################################################################
26#
27# The GPL License (GPL)
28#
29# Copyright (C) 2014 Vivante Corporation
30#
31# This program is free software; you can redistribute it and/or
32# modify it under the terms of the GNU General Public License
33# as published by the Free Software Foundation; either version 2
34# of the License, or (at your option) any later version.
35#
36# This program is distributed in the hope that it will be useful,
37# but WITHOUT ANY WARRANTY; without even the implied warranty of
38# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39# GNU General Public License for more details.
40#
41# You should have received a copy of the GNU General Public License
42# along with this program; if not, write to the Free Software Foundation,
43# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44#
45##############################################################################
46#
47# Note: This software is released under dual MIT and GPL licenses. A
48# recipient may use this file under the terms of either the MIT license or
49# GPL License. If you wish to use only one license not the other, you can
50# indicate your decision by deleting one of the above license notices in your
51# version of this file.
52#
53##############################################################################
54
55
56SYNCHRONIZE_DRAIN=1
57TARGETNAME=arch.kernel
58TARGETTYPE=LIBRARY
59
60SOURCES= \
61 gc_hal_kernel_hardware.c \
62 gc_hal_kernel_context.c \
63
64INCLUDES= \
65 $(INCLUDES); \
66 $(AQROOT)\hal\kernel\inc; \
67 $(AQROOT)\hal\kernel; \
68 $(AQROOT)\hal\kernel\inc; \
69 $(AQROOT)\hal\os\ce\kernel; \
70 $(AQROOT)\hal\kernel\archvg; \
71
diff --git a/src/hal/kernel/gc_hal_kernel.c b/src/hal/kernel/gc_hal_kernel.c
new file mode 100755
index 0000000..d9387fe
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel.c
@@ -0,0 +1,5008 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57
58#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
59#include "viv_dec300_main.h"
60#endif
61
62#define _GC_OBJ_ZONE gcvZONE_KERNEL
63
64/*******************************************************************************
65***** Version Signature *******************************************************/
66
67#define _gcmTXT2STR(t) #t
68#define gcmTXT2STR(t) _gcmTXT2STR(t)
69const char * _VERSION = "\n\0$VERSION$"
70 gcmTXT2STR(gcvVERSION_MAJOR) "."
71 gcmTXT2STR(gcvVERSION_MINOR) "."
72 gcmTXT2STR(gcvVERSION_PATCH) ":"
73 gcmTXT2STR(gcvVERSION_BUILD) "$\n";
74
75/******************************************************************************\
76******************************* gckKERNEL API Code ******************************
77\******************************************************************************/
78
79#if gcmIS_DEBUG(gcdDEBUG_TRACE)
80#define gcmDEFINE2TEXT(d) #d
81gctCONST_STRING _DispatchText[] =
82{
83 gcmDEFINE2TEXT(gcvHAL_QUERY_VIDEO_MEMORY),
84 gcmDEFINE2TEXT(gcvHAL_QUERY_CHIP_IDENTITY),
85 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_NON_PAGED_MEMORY),
86 gcmDEFINE2TEXT(gcvHAL_FREE_NON_PAGED_MEMORY),
87 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY),
88 gcmDEFINE2TEXT(gcvHAL_FREE_CONTIGUOUS_MEMORY),
89 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIDEO_MEMORY),
90 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY),
91 gcmDEFINE2TEXT(gcvHAL_RELEASE_VIDEO_MEMORY),
92 gcmDEFINE2TEXT(gcvHAL_MAP_MEMORY),
93 gcmDEFINE2TEXT(gcvHAL_UNMAP_MEMORY),
94 gcmDEFINE2TEXT(gcvHAL_MAP_USER_MEMORY),
95 gcmDEFINE2TEXT(gcvHAL_UNMAP_USER_MEMORY),
96 gcmDEFINE2TEXT(gcvHAL_LOCK_VIDEO_MEMORY),
97 gcmDEFINE2TEXT(gcvHAL_UNLOCK_VIDEO_MEMORY),
98 gcmDEFINE2TEXT(gcvHAL_EVENT_COMMIT),
99 gcmDEFINE2TEXT(gcvHAL_USER_SIGNAL),
100 gcmDEFINE2TEXT(gcvHAL_SIGNAL),
101 gcmDEFINE2TEXT(gcvHAL_WRITE_DATA),
102 gcmDEFINE2TEXT(gcvHAL_COMMIT),
103 gcmDEFINE2TEXT(gcvHAL_STALL),
104 gcmDEFINE2TEXT(gcvHAL_READ_REGISTER),
105 gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER),
106 gcmDEFINE2TEXT(gcvHAL_GET_PROFILE_SETTING),
107 gcmDEFINE2TEXT(gcvHAL_SET_PROFILE_SETTING),
108 gcmDEFINE2TEXT(gcvHAL_READ_ALL_PROFILE_REGISTERS),
109 gcmDEFINE2TEXT(gcvHAL_PROFILE_REGISTERS_2D),
110#if VIVANTE_PROFILER_PERDRAW
111 gcvHAL_READ_PROFILER_REGISTER_SETTING,
112#endif
113 gcmDEFINE2TEXT(gcvHAL_SET_POWER_MANAGEMENT_STATE),
114 gcmDEFINE2TEXT(gcvHAL_QUERY_POWER_MANAGEMENT_STATE),
115 gcmDEFINE2TEXT(gcvHAL_GET_BASE_ADDRESS),
116 gcmDEFINE2TEXT(gcvHAL_SET_IDLE),
117 gcmDEFINE2TEXT(gcvHAL_QUERY_KERNEL_SETTINGS),
118 gcmDEFINE2TEXT(gcvHAL_RESET),
119 gcmDEFINE2TEXT(gcvHAL_MAP_PHYSICAL),
120 gcmDEFINE2TEXT(gcvHAL_DEBUG),
121 gcmDEFINE2TEXT(gcvHAL_CACHE),
122 gcmDEFINE2TEXT(gcvHAL_TIMESTAMP),
123 gcmDEFINE2TEXT(gcvHAL_DATABASE),
124 gcmDEFINE2TEXT(gcvHAL_VERSION),
125 gcmDEFINE2TEXT(gcvHAL_CHIP_INFO),
126 gcmDEFINE2TEXT(gcvHAL_ATTACH),
127 gcmDEFINE2TEXT(gcvHAL_DETACH),
128 gcmDEFINE2TEXT(gcvHAL_COMPOSE),
129 gcmDEFINE2TEXT(gcvHAL_SET_TIMEOUT),
130 gcmDEFINE2TEXT(gcvHAL_GET_FRAME_INFO),
131 gcmDEFINE2TEXT(gcvHAL_QUERY_COMMAND_BUFFER),
132 gcmDEFINE2TEXT(gcvHAL_COMMIT_DONE),
133 gcmDEFINE2TEXT(gcvHAL_DUMP_GPU_STATE),
134 gcmDEFINE2TEXT(gcvHAL_DUMP_EVENT),
135 gcmDEFINE2TEXT(gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER),
136 gcmDEFINE2TEXT(gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER),
137 gcmDEFINE2TEXT(gcvHAL_SET_FSCALE_VALUE),
138 gcmDEFINE2TEXT(gcvHAL_GET_FSCALE_VALUE),
139 gcmDEFINE2TEXT(gcvHAL_NAME_VIDEO_MEMORY),
140 gcmDEFINE2TEXT(gcvHAL_IMPORT_VIDEO_MEMORY),
141 gcmDEFINE2TEXT(gcvHAL_QUERY_RESET_TIME_STAMP),
142 gcmDEFINE2TEXT(gcvHAL_READ_REGISTER_EX),
143 gcmDEFINE2TEXT(gcvHAL_WRITE_REGISTER_EX),
144 gcmDEFINE2TEXT(gcvHAL_SYNC_POINT),
145 gcmDEFINE2TEXT(gcvHAL_CREATE_NATIVE_FENCE),
146 gcmDEFINE2TEXT(gcvHAL_DESTROY_MMU),
147 gcmDEFINE2TEXT(gcvHAL_SHBUF),
148};
149#endif
150
151#if gcdGPU_TIMEOUT && gcdINTERRUPT_STATISTIC
152void
153_MonitorTimerFunction(
154 gctPOINTER Data
155 )
156{
157 gckKERNEL kernel = (gckKERNEL)Data;
158 gctUINT32 pendingInterrupt;
159 gctBOOL reset = gcvFALSE;
160 gctUINT32 mask;
161 gctUINT32 advance = kernel->timeOut/2;
162
163
164 if (kernel->monitorTimerStop)
165 {
166 /* Stop. */
167 return;
168 }
169
170 gckOS_AtomGet(kernel->os, kernel->eventObj->interruptCount, &pendingInterrupt);
171
172 if (kernel->monitoring == gcvFALSE)
173 {
174 if (pendingInterrupt)
175 {
176 /* Begin to mointor GPU state. */
177 kernel->monitoring = gcvTRUE;
178
179 /* Record current state. */
180 kernel->lastCommitStamp = kernel->eventObj->lastCommitStamp;
181 kernel->restoreAddress = kernel->hardware->lastWaitLink;
182 gcmkVERIFY_OK(gckOS_AtomGet(
183 kernel->os,
184 kernel->hardware->pendingEvent,
185 &kernel->restoreMask
186 ));
187
188 /* Clear timeout. */
189 kernel->timer = 0;
190 }
191 }
192 else
193 {
194 if (pendingInterrupt)
195 {
196 gcmkVERIFY_OK(gckOS_AtomGet(
197 kernel->os,
198 kernel->hardware->pendingEvent,
199 &mask
200 ));
201
202 if (kernel->eventObj->lastCommitStamp == kernel->lastCommitStamp
203 && kernel->hardware->lastWaitLink == kernel->restoreAddress
204 && mask == kernel->restoreMask
205 )
206 {
207 /* GPU state is not changed, accumlate timeout. */
208 kernel->timer += advance;
209
210 if (kernel->timer >= kernel->timeOut)
211 {
212 /* GPU stuck, trigger reset. */
213 reset = gcvTRUE;
214 }
215 }
216 else
217 {
218 /* GPU state changed, cancel current timeout.*/
219 kernel->monitoring = gcvFALSE;
220 }
221 }
222 else
223 {
224 /* GPU finish all jobs, cancel current timeout*/
225 kernel->monitoring = gcvFALSE;
226 }
227 }
228
229 if (reset)
230 {
231 gckKERNEL_Recovery(kernel);
232
233 /* Work in this timeout is done. */
234 kernel->monitoring = gcvFALSE;
235 }
236
237 gcmkVERIFY_OK(gckOS_StartTimer(kernel->os, kernel->monitorTimer, advance));
238}
239#endif
240
241#if gcdPROCESS_ADDRESS_SPACE
242gceSTATUS
243_MapCommandBuffer(
244 IN gckKERNEL Kernel
245 )
246{
247 gceSTATUS status;
248 gctUINT32 i;
249 gctUINT32 physical;
250 gckMMU mmu;
251
252 gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
253
254 for (i = 0; i < gcdCOMMAND_QUEUES; i++)
255 {
256 gcmkONERROR(gckOS_GetPhysicalAddress(
257 Kernel->os,
258 Kernel->command->queues[i].logical,
259 &physical
260 ));
261
262 gcmkONERROR(gckMMU_FlatMapping(mmu, physical));
263 }
264
265 return gcvSTATUS_OK;
266
267OnError:
268 return status;
269}
270#endif
271
272void
273_DumpDriverConfigure(
274 IN gckKERNEL Kernel
275 )
276{
277 gcmkPRINT_N(0, "**************************\n");
278 gcmkPRINT_N(0, "*** GPU DRV CONFIG ***\n");
279 gcmkPRINT_N(0, "**************************\n");
280
281 gcmkPRINT("Galcore version %d.%d.%d.%d\n",
282 gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
283
284 gckOS_DumpParam();
285}
286
287void
288_DumpState(
289 IN gckKERNEL Kernel
290 )
291{
292 /* Dump GPU Debug registers. */
293 gcmkVERIFY_OK(gckHARDWARE_DumpGPUState(Kernel->hardware));
294
295 gcmkVERIFY_OK(gckCOMMAND_DumpExecutingBuffer(Kernel->command));
296
297 /* Dump Pending event. */
298 gcmkVERIFY_OK(gckEVENT_Dump(Kernel->eventObj));
299
300 /* Dump Process DB. */
301 gcmkVERIFY_OK(gckKERNEL_DumpProcessDB(Kernel));
302
303#if gcdRECORD_COMMAND
304 /* Dump record. */
305 gckRECORDER_Dump(Kernel->command->recorder);
306#endif
307}
308
309/*******************************************************************************
310**
311** gckKERNEL_Construct
312**
313** Construct a new gckKERNEL object.
314**
315** INPUT:
316**
317** gckOS Os
318** Pointer to an gckOS object.
319**
320** gceCORE Core
321** Specified core.
322**
323** IN gctPOINTER Context
324** Pointer to a driver defined context.
325**
326** IN gckDB SharedDB,
327** Pointer to a shared DB.
328**
329** OUTPUT:
330**
331** gckKERNEL * Kernel
332** Pointer to a variable that will hold the pointer to the gckKERNEL
333** object.
334*/
335
336gceSTATUS
337gckKERNEL_Construct(
338 IN gckOS Os,
339 IN gceCORE Core,
340 IN gctPOINTER Context,
341 IN gckDB SharedDB,
342 OUT gckKERNEL * Kernel
343 )
344{
345 gckKERNEL kernel = gcvNULL;
346 gceSTATUS status;
347 gctSIZE_T i;
348 gctPOINTER pointer = gcvNULL;
349
350 gcmkHEADER_ARG("Os=0x%x Context=0x%x", Os, Context);
351
352 /* Verify the arguments. */
353 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
354 gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
355
356 /* Allocate the gckKERNEL object. */
357 gcmkONERROR(gckOS_Allocate(Os,
358 gcmSIZEOF(struct _gckKERNEL),
359 &pointer));
360
361 kernel = pointer;
362
363 /* Zero the object pointers. */
364 kernel->hardware = gcvNULL;
365 kernel->command = gcvNULL;
366 kernel->eventObj = gcvNULL;
367 kernel->mmu = gcvNULL;
368#if gcdDVFS
369 kernel->dvfs = gcvNULL;
370#endif
371 kernel->monitorTimer = gcvNULL;
372
373 /* Initialize the gckKERNEL object. */
374 kernel->object.type = gcvOBJ_KERNEL;
375 kernel->os = Os;
376 kernel->core = Core;
377
378 if (SharedDB == gcvNULL)
379 {
380 gcmkONERROR(gckOS_Allocate(Os,
381 gcmSIZEOF(struct _gckDB),
382 &pointer));
383
384 kernel->db = pointer;
385 kernel->dbCreated = gcvTRUE;
386 kernel->db->freeDatabase = gcvNULL;
387 kernel->db->freeRecord = gcvNULL;
388 kernel->db->dbMutex = gcvNULL;
389 kernel->db->lastDatabase = gcvNULL;
390 kernel->db->idleTime = 0;
391 kernel->db->lastIdle = 0;
392 kernel->db->lastSlowdown = 0;
393
394 for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
395 {
396 kernel->db->db[i] = gcvNULL;
397 }
398
399 /* Construct a database mutex. */
400 gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->dbMutex));
401
402 /* Construct a video memory name database. */
403 gcmkONERROR(gckKERNEL_CreateIntegerDatabase(kernel, &kernel->db->nameDatabase));
404
405 /* Construct a video memory name database mutex. */
406 gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->nameDatabaseMutex));
407
408 /* Construct a pointer name database. */
409 gcmkONERROR(gckKERNEL_CreateIntegerDatabase(kernel, &kernel->db->pointerDatabase));
410
411 /* Construct a pointer name database mutex. */
412 gcmkONERROR(gckOS_CreateMutex(Os, &kernel->db->pointerDatabaseMutex));
413 }
414 else
415 {
416 kernel->db = SharedDB;
417 kernel->dbCreated = gcvFALSE;
418 }
419
420 for (i = 0; i < gcmCOUNTOF(kernel->timers); ++i)
421 {
422 kernel->timers[i].startTime = 0;
423 kernel->timers[i].stopTime = 0;
424 }
425
426 /* Save context. */
427 kernel->context = Context;
428
429 /* Construct atom holding number of clients. */
430 kernel->atomClients = gcvNULL;
431 gcmkONERROR(gckOS_AtomConstruct(Os, &kernel->atomClients));
432
433 {
434 /* Construct the gckHARDWARE object. */
435 gcmkONERROR(
436 gckHARDWARE_Construct(Os, kernel->core, &kernel->hardware));
437
438 /* Set pointer to gckKERNEL object in gckHARDWARE object. */
439 kernel->hardware->kernel = kernel;
440
441 kernel->timeOut = kernel->hardware->type == gcvHARDWARE_2D
442 ? gcdGPU_2D_TIMEOUT
443 : gcdGPU_TIMEOUT
444 ;
445
446 /* Initialize virtual command buffer. */
447 /* TODO: Remove platform limitation after porting. */
448#if (defined(LINUX) || defined(__QNXNTO__)) && !gcdALLOC_CMD_FROM_RESERVE
449 kernel->virtualCommandBuffer = gcvTRUE;
450#else
451 kernel->virtualCommandBuffer = gcvFALSE;
452#endif
453
454
455 /* Construct the gckCOMMAND object. */
456 gcmkONERROR(
457 gckCOMMAND_Construct(kernel, &kernel->command));
458
459 /* Construct the gckEVENT object. */
460 gcmkONERROR(
461 gckEVENT_Construct(kernel, &kernel->eventObj));
462
463 /* Construct the gckMMU object. */
464 gcmkONERROR(
465 gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
466
467 gcmkVERIFY_OK(gckOS_GetTime(&kernel->resetTimeStamp));
468
469 gcmkONERROR(gckHARDWARE_PrepareFunctions(kernel->hardware));
470
471 /* Initialize the hardware. */
472 gcmkONERROR(
473 gckHARDWARE_InitializeHardware(kernel->hardware));
474
475#if gcdDVFS
476 if (gckHARDWARE_IsFeatureAvailable(kernel->hardware,
477 gcvFEATURE_DYNAMIC_FREQUENCY_SCALING))
478 {
479 gcmkONERROR(gckDVFS_Construct(kernel->hardware, &kernel->dvfs));
480 gcmkONERROR(gckDVFS_Start(kernel->dvfs));
481 }
482#endif
483 }
484
485#if VIVANTE_PROFILER
486 /* Initialize profile setting */
487 kernel->profileEnable = gcvFALSE;
488 kernel->profileCleanRegister = gcvTRUE;
489#endif
490
491#if gcdANDROID_NATIVE_FENCE_SYNC
492 gcmkONERROR(gckOS_CreateSyncTimeline(Os, &kernel->timeline));
493#endif
494
495 kernel->recovery = gcvTRUE;
496 kernel->stuckDump = gcvSTUCK_DUMP_NONE;
497
498 kernel->virtualBufferHead =
499 kernel->virtualBufferTail = gcvNULL;
500
501 gcmkONERROR(
502 gckOS_CreateMutex(Os, (gctPOINTER)&kernel->virtualBufferLock));
503
504
505#if gcdGPU_TIMEOUT && gcdINTERRUPT_STATISTIC
506 if (kernel->timeOut)
507 {
508 gcmkVERIFY_OK(gckOS_CreateTimer(
509 Os,
510 (gctTIMERFUNCTION)_MonitorTimerFunction,
511 (gctPOINTER)kernel,
512 &kernel->monitorTimer
513 ));
514
515 kernel->monitoring = gcvFALSE;
516
517 kernel->monitorTimerStop = gcvFALSE;
518
519 gcmkVERIFY_OK(gckOS_StartTimer(
520 Os,
521 kernel->monitorTimer,
522 100
523 ));
524 }
525#endif
526
527 /* Return pointer to the gckKERNEL object. */
528 *Kernel = kernel;
529
530 /* Success. */
531 gcmkFOOTER_ARG("*Kernel=0x%x", *Kernel);
532 return gcvSTATUS_OK;
533
534OnError:
535 if (kernel != gcvNULL)
536 {
537 {
538 if (kernel->eventObj != gcvNULL)
539 {
540 gcmkVERIFY_OK(gckEVENT_Destroy(kernel->eventObj));
541 }
542
543 if (kernel->command != gcvNULL)
544 {
545 gcmkVERIFY_OK(gckCOMMAND_Destroy(kernel->command));
546 }
547
548 if (kernel->hardware != gcvNULL)
549 {
550 /* Turn off the power. */
551 gcmkVERIFY_OK(gckOS_SetGPUPower(kernel->hardware->os,
552 kernel->hardware->core,
553 gcvFALSE,
554 gcvFALSE));
555 gcmkVERIFY_OK(gckHARDWARE_Destroy(kernel->hardware));
556 }
557 }
558
559 if (kernel->atomClients != gcvNULL)
560 {
561 gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
562 }
563
564 if (kernel->dbCreated && kernel->db != gcvNULL)
565 {
566 if (kernel->db->dbMutex != gcvNULL)
567 {
568 /* Destroy the database mutex. */
569 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->db->dbMutex));
570 }
571
572 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel->db));
573 }
574
575 if (kernel->virtualBufferLock != gcvNULL)
576 {
577 /* Destroy the virtual command buffer mutex. */
578 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, kernel->virtualBufferLock));
579 }
580
581#if gcdDVFS
582 if (kernel->dvfs)
583 {
584 gcmkVERIFY_OK(gckDVFS_Stop(kernel->dvfs));
585 gcmkVERIFY_OK(gckDVFS_Destroy(kernel->dvfs));
586 }
587#endif
588
589#if gcdANDROID_NATIVE_FENCE_SYNC
590 if (kernel->timeline)
591 {
592 gcmkVERIFY_OK(gckOS_DestroySyncTimeline(Os, kernel->timeline));
593 }
594#endif
595
596 if (kernel->monitorTimer)
597 {
598 gcmkVERIFY_OK(gckOS_StopTimer(Os, kernel->monitorTimer));
599 gcmkVERIFY_OK(gckOS_DestroyTimer(Os, kernel->monitorTimer));
600 }
601
602 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, kernel));
603 }
604
605 /* Return the error. */
606 gcmkFOOTER();
607 return status;
608}
609
610/*******************************************************************************
611**
612** gckKERNEL_Destroy
613**
614** Destroy an gckKERNEL object.
615**
616** INPUT:
617**
618** gckKERNEL Kernel
619** Pointer to an gckKERNEL object to destroy.
620**
621** OUTPUT:
622**
623** Nothing.
624*/
625gceSTATUS
626gckKERNEL_Destroy(
627 IN gckKERNEL Kernel
628 )
629{
630 gctSIZE_T i;
631 gcsDATABASE_PTR database, databaseNext;
632 gcsDATABASE_RECORD_PTR record, recordNext;
633
634 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
635
636 /* Verify the arguments. */
637 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
638#if QNX_SINGLE_THREADED_DEBUGGING
639 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->debugMutex));
640#endif
641
642 /* Destroy the database. */
643 if (Kernel->dbCreated)
644 {
645 for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
646 {
647 if (Kernel->db->db[i] != gcvNULL)
648 {
649 gcmkVERIFY_OK(
650 gckKERNEL_DestroyProcessDB(Kernel, Kernel->db->db[i]->processID));
651 }
652 }
653
654 /* Free all databases. */
655 for (database = Kernel->db->freeDatabase;
656 database != gcvNULL;
657 database = databaseNext)
658 {
659 databaseNext = database->next;
660
661 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->counterMutex));
662 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, database));
663 }
664
665 if (Kernel->db->lastDatabase != gcvNULL)
666 {
667 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->lastDatabase->counterMutex));
668 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db->lastDatabase));
669 }
670
671 /* Free all database records. */
672 for (record = Kernel->db->freeRecord; record != gcvNULL; record = recordNext)
673 {
674 recordNext = record->next;
675 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
676 }
677
678 /* Destroy the database mutex. */
679 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->dbMutex));
680
681 /* Destroy video memory name database. */
682 gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Kernel->db->nameDatabase));
683
684 /* Destroy video memory name database mutex. */
685 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->nameDatabaseMutex));
686
687
688 /* Destroy id-pointer database. */
689 gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Kernel->db->pointerDatabase));
690
691 /* Destroy id-pointer database mutex. */
692 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
693
694 /* Destroy the database. */
695 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel->db));
696
697 /* Notify stuck timer to quit. */
698 Kernel->monitorTimerStop = gcvTRUE;
699 }
700
701 {
702 /* Destroy the gckMMU object. */
703 gcmkVERIFY_OK(gckMMU_Destroy(Kernel->mmu));
704
705 /* Destroy the gckCOMMNAND object. */
706 gcmkVERIFY_OK(gckCOMMAND_Destroy(Kernel->command));
707
708 /* Destroy the gckEVENT object. */
709 gcmkVERIFY_OK(gckEVENT_Destroy(Kernel->eventObj));
710
711 /* Destroy the gckHARDWARE object. */
712 gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
713 }
714
715 /* Detsroy the client atom. */
716 gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->atomClients));
717
718 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Kernel->virtualBufferLock));
719
720#if gcdDVFS
721 if (Kernel->dvfs)
722 {
723 gcmkVERIFY_OK(gckDVFS_Stop(Kernel->dvfs));
724 gcmkVERIFY_OK(gckDVFS_Destroy(Kernel->dvfs));
725 }
726#endif
727
728#if gcdANDROID_NATIVE_FENCE_SYNC
729 gcmkVERIFY_OK(gckOS_DestroySyncTimeline(Kernel->os, Kernel->timeline));
730#endif
731
732
733 if (Kernel->monitorTimer)
734 {
735 gcmkVERIFY_OK(gckOS_StopTimer(Kernel->os, Kernel->monitorTimer));
736 gcmkVERIFY_OK(gckOS_DestroyTimer(Kernel->os, Kernel->monitorTimer));
737 }
738
739 /* Mark the gckKERNEL object as unknown. */
740 Kernel->object.type = gcvOBJ_UNKNOWN;
741
742 /* Free the gckKERNEL object. */
743 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, Kernel));
744
745 /* Success. */
746 gcmkFOOTER_NO();
747 return gcvSTATUS_OK;
748}
749
750/*******************************************************************************
751**
752** _AllocateMemory
753**
754** Private function to walk all required memory pools to allocate the requested
755** amount of video memory.
756**
757** INPUT:
758**
759** gckKERNEL Kernel
760** Pointer to an gckKERNEL object.
761**
762** gcsHAL_INTERFACE * Interface
763** Pointer to a gcsHAL_INTERFACE structure that defines the command to
764** be dispatched.
765**
766** OUTPUT:
767**
768** gcsHAL_INTERFACE * Interface
769** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
770** returned.
771*/
772gceSTATUS
773gckKERNEL_AllocateLinearMemory(
774 IN gckKERNEL Kernel,
775 IN gctUINT32 ProcessID,
776 IN OUT gcePOOL * Pool,
777 IN gctSIZE_T Bytes,
778 IN gctUINT32 Alignment,
779 IN gceSURF_TYPE Type,
780 IN gctUINT32 Flag,
781 OUT gctUINT32 * Node
782 )
783{
784 gcePOOL pool;
785 gceSTATUS status;
786 gckVIDMEM videoMemory;
787 gctINT loopCount;
788 gcuVIDMEM_NODE_PTR node = gcvNULL;
789 gctBOOL tileStatusInVirtual;
790 gctBOOL contiguous = gcvFALSE;
791 gctBOOL cacheable = gcvFALSE;
792 gctSIZE_T bytes = Bytes;
793 gctUINT32 handle = 0;
794 gceDATABASE_TYPE type;
795
796 gcmkHEADER_ARG("Kernel=0x%x *Pool=%d Bytes=%lu Alignment=%lu Type=%d",
797 Kernel, *Pool, Bytes, Alignment, Type);
798
799 gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
800 gcmkVERIFY_ARGUMENT(Bytes != 0);
801
802 /* Get basic type. */
803 Type &= 0xFF;
804
805 /* Check flags. */
806 contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
807 cacheable = Flag & gcvALLOC_FLAG_CACHEABLE;
808
809AllocateMemory:
810
811 /* Get initial pool. */
812 switch (pool = *Pool)
813 {
814 case gcvPOOL_DEFAULT:
815 case gcvPOOL_LOCAL:
816 pool = gcvPOOL_LOCAL_INTERNAL;
817 loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
818 break;
819
820 case gcvPOOL_UNIFIED:
821 pool = gcvPOOL_SYSTEM;
822 loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
823 break;
824
825 case gcvPOOL_CONTIGUOUS:
826 loopCount = (gctINT) gcvPOOL_NUMBER_OF_POOLS;
827 break;
828
829 default:
830 loopCount = 1;
831 break;
832 }
833
834 while (loopCount-- > 0)
835 {
836 if (pool == gcvPOOL_VIRTUAL)
837 {
838 /* Create a gcuVIDMEM_NODE for virtual memory. */
839 gcmkONERROR(
840 gckVIDMEM_ConstructVirtual(Kernel, Flag | gcvALLOC_FLAG_NON_CONTIGUOUS, Bytes, &node));
841
842 bytes = node->Virtual.bytes;
843 node->Virtual.type = Type;
844
845 /* Success. */
846 break;
847 }
848
849 else
850 if (pool == gcvPOOL_CONTIGUOUS)
851 {
852#if gcdCONTIGUOUS_SIZE_LIMIT
853 if (Bytes > gcdCONTIGUOUS_SIZE_LIMIT && contiguous == gcvFALSE)
854 {
855 status = gcvSTATUS_OUT_OF_MEMORY;
856 }
857 else
858#endif
859 {
860 /* Create a gcuVIDMEM_NODE from contiguous memory. */
861 status = gckVIDMEM_ConstructVirtual(
862 Kernel,
863 Flag | gcvALLOC_FLAG_CONTIGUOUS,
864 Bytes,
865 &node);
866 }
867
868 if (gcmIS_SUCCESS(status))
869 {
870 bytes = node->Virtual.bytes;
871 node->Virtual.type = Type;
872
873 /* Memory allocated. */
874 break;
875 }
876 }
877
878 else
879 /* gcvPOOL_SYSTEM can't be cacheable. */
880 if (cacheable == gcvFALSE)
881 {
882 /* Get pointer to gckVIDMEM object for pool. */
883 status = gckKERNEL_GetVideoMemoryPool(Kernel, pool, &videoMemory);
884
885 if (gcmIS_SUCCESS(status))
886 {
887 /* Allocate memory. */
888#if defined(gcdLINEAR_SIZE_LIMIT)
889 /* 512 KB */
890 if (Bytes > gcdLINEAR_SIZE_LIMIT)
891 {
892 status = gcvSTATUS_OUT_OF_MEMORY;
893 }
894 else
895#endif
896 {
897 status = gckVIDMEM_AllocateLinear(Kernel,
898 videoMemory,
899 Bytes,
900 Alignment,
901 Type,
902 (*Pool == gcvPOOL_SYSTEM),
903 &node);
904 }
905
906 if (gcmIS_SUCCESS(status))
907 {
908 /* Memory allocated. */
909 node->VidMem.pool = pool;
910 bytes = node->VidMem.bytes;
911 break;
912 }
913 }
914 }
915
916 if (pool == gcvPOOL_LOCAL_INTERNAL)
917 {
918 /* Advance to external memory. */
919 pool = gcvPOOL_LOCAL_EXTERNAL;
920 }
921
922 else
923 if (pool == gcvPOOL_LOCAL_EXTERNAL)
924 {
925 /* Advance to contiguous system memory. */
926 pool = gcvPOOL_SYSTEM;
927 }
928
929 else
930 if (pool == gcvPOOL_SYSTEM)
931 {
932 /* Advance to contiguous memory. */
933 pool = gcvPOOL_CONTIGUOUS;
934 }
935
936 else
937 if (pool == gcvPOOL_CONTIGUOUS)
938 {
939 {
940 tileStatusInVirtual =
941 gckHARDWARE_IsFeatureAvailable(Kernel->hardware,
942 gcvFEATURE_MC20);
943 }
944
945 if (Type == gcvSURF_TILE_STATUS && tileStatusInVirtual != gcvTRUE)
946 {
947 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
948 }
949
950 if (contiguous)
951 {
952 break;
953 }
954
955 /* Advance to virtual memory. */
956 pool = gcvPOOL_VIRTUAL;
957 }
958
959 else
960 {
961 /* Out of pools. */
962 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
963 }
964 }
965
966 if (node == gcvNULL)
967 {
968 if (contiguous)
969 {
970 /* Broadcast OOM message. */
971 status = gckOS_Broadcast(Kernel->os, Kernel->hardware, gcvBROADCAST_OUT_OF_MEMORY);
972
973 if (gcmIS_SUCCESS(status))
974 {
975 /* Get some memory. */
976 gckOS_Delay(gcvNULL, 1);
977 goto AllocateMemory;
978 }
979 }
980
981 /* Nothing allocated. */
982 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
983 }
984
985 /* Allocate handle for this video memory. */
986 gcmkONERROR(
987 gckVIDMEM_NODE_Allocate(Kernel, node, Type, pool, &handle));
988
989 /* Return node and pool used for allocation. */
990 *Node = handle;
991 *Pool = pool;
992
993 /* Encode surface type and pool to database type. */
994 type = gcvDB_VIDEO_MEMORY
995 | (Type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
996 | (pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
997
998 /* Record in process db. */
999 gcmkONERROR(
1000 gckKERNEL_AddProcessDB(Kernel,
1001 ProcessID,
1002 type,
1003 gcmINT2PTR(handle),
1004 gcvNULL,
1005 bytes));
1006
1007 /* Return status. */
1008 gcmkFOOTER_ARG("*Pool=%d *Node=0x%x", *Pool, *Node);
1009 return gcvSTATUS_OK;
1010
1011OnError:
1012 if (handle)
1013 {
1014 /* Destroy handle allocated. */
1015 gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, handle));
1016 }
1017
1018 if (node)
1019 {
1020 /* Free video memory allocated. */
1021 gcmkVERIFY_OK(gckVIDMEM_Free(Kernel, node));
1022 }
1023
1024 /* For some case like chrome with webgl test, it needs too much memory so that it invokes oom_killer
1025 * And the case is killed by oom_killer, the user wants not to see the crash and hope the case iteself handles the condition
1026 * So the patch reports the out_of_memory to the case */
1027 if ( status == gcvSTATUS_OUT_OF_MEMORY && (Flag & gcvALLOC_FLAG_MEMLIMIT) )
1028 gcmkPRINT("The running case is out_of_memory");
1029
1030 /* Return the status. */
1031 gcmkFOOTER();
1032 return status;
1033}
1034
1035/*******************************************************************************
1036**
1037** gckKERNEL_ReleaseVideoMemory
1038**
1039** Release handle of a video memory.
1040**
1041** INPUT:
1042**
1043** gckKERNEL Kernel
1044** Pointer to an gckKERNEL object.
1045**
1046** gctUINT32 ProcessID
1047** ProcessID of current process.
1048**
1049** gctUINT32 Handle
1050** Handle of video memory.
1051**
1052** OUTPUT:
1053**
1054** Nothing.
1055*/
1056gceSTATUS
1057gckKERNEL_ReleaseVideoMemory(
1058 IN gckKERNEL Kernel,
1059 IN gctUINT32 ProcessID,
1060 IN gctUINT32 Handle
1061 )
1062{
1063 gceSTATUS status;
1064 gckVIDMEM_NODE nodeObject;
1065 gceDATABASE_TYPE type;
1066
1067 gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d Handle=%d",
1068 Kernel, ProcessID, Handle);
1069
1070 gcmkONERROR(
1071 gckVIDMEM_HANDLE_Lookup(Kernel, ProcessID, Handle, &nodeObject));
1072
1073 type = gcvDB_VIDEO_MEMORY
1074 | (nodeObject->type << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
1075 | (nodeObject->pool << gcdDB_VIDEO_MEMORY_POOL_SHIFT);
1076
1077 gcmkONERROR(
1078 gckKERNEL_RemoveProcessDB(Kernel,
1079 ProcessID,
1080 type,
1081 gcmINT2PTR(Handle)));
1082
1083 gckVIDMEM_HANDLE_Dereference(Kernel, ProcessID, Handle);
1084
1085 gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
1086
1087 gcmkFOOTER_NO();
1088 return gcvSTATUS_OK;
1089
1090OnError:
1091 gcmkFOOTER();
1092 return status;
1093}
1094
1095/*******************************************************************************
1096**
1097** gckKERNEL_LockVideoMemory
1098**
1099** Lock a video memory node. It will generate a cpu virtual address used
1100** by software and a GPU address used by GPU.
1101**
1102** INPUT:
1103**
1104** gckKERNEL Kernel
1105** Pointer to an gckKERNEL object.
1106**
1107** gceCORE Core
1108** GPU to which video memory is locked.
1109**
1110** gcsHAL_INTERFACE * Interface
1111** Pointer to a gcsHAL_INTERFACE structure that defines the command to
1112** be dispatched.
1113**
1114** OUTPUT:
1115**
1116** gcsHAL_INTERFACE * Interface
1117** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
1118** returned.
1119*/
1120gceSTATUS
1121gckKERNEL_LockVideoMemory(
1122 IN gckKERNEL Kernel,
1123 IN gceCORE Core,
1124 IN gctUINT32 ProcessID,
1125 IN gctBOOL FromUser,
1126 IN OUT gcsHAL_INTERFACE * Interface
1127 )
1128{
1129 gceSTATUS status;
1130 gckVIDMEM_NODE nodeObject = gcvNULL;
1131 gcuVIDMEM_NODE_PTR node = gcvNULL;
1132 gctBOOL locked = gcvFALSE;
1133 gctBOOL asynchronous = gcvFALSE;
1134#ifndef __QNXNTO__
1135 gctPOINTER pointer = gcvNULL;
1136#endif
1137
1138 gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
1139 Kernel, ProcessID);
1140
1141 gcmkONERROR(
1142 gckVIDMEM_HANDLE_LookupAndReference(Kernel,
1143 Interface->u.LockVideoMemory.node,
1144 &nodeObject));
1145
1146 node = nodeObject->node;
1147
1148 Interface->u.LockVideoMemory.gid = 0;
1149
1150 /* Lock video memory. */
1151 gcmkONERROR(
1152 gckVIDMEM_Lock(Kernel,
1153 nodeObject,
1154 Interface->u.LockVideoMemory.cacheable,
1155 &Interface->u.LockVideoMemory.address,
1156 &Interface->u.LockVideoMemory.gid,
1157 &Interface->u.LockVideoMemory.physicalAddress));
1158
1159 locked = gcvTRUE;
1160
1161 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1162 {
1163 /* Map video memory address into user space. */
1164#ifdef __QNXNTO__
1165 if (node->VidMem.logical == gcvNULL)
1166 {
1167 gcmkONERROR(
1168 gckKERNEL_MapVideoMemory(Kernel,
1169 FromUser,
1170 Interface->u.LockVideoMemory.address,
1171 ProcessID,
1172 node->VidMem.bytes,
1173 &node->VidMem.logical));
1174 }
1175 gcmkASSERT(node->VidMem.logical != gcvNULL);
1176
1177 Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->VidMem.logical);
1178#else
1179 gcmkONERROR(
1180 gckKERNEL_MapVideoMemoryEx(Kernel,
1181 Core,
1182 FromUser,
1183 Interface->u.LockVideoMemory.address,
1184 &pointer));
1185
1186 Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(pointer);
1187#endif
1188 }
1189 else
1190 {
1191 Interface->u.LockVideoMemory.memory = gcmPTR_TO_UINT64(node->Virtual.logical);
1192
1193 /* Success. */
1194 status = gcvSTATUS_OK;
1195 }
1196
1197#if gcdPROCESS_ADDRESS_SPACE
1198 gcmkONERROR(gckVIDMEM_Node_Lock(
1199 Kernel,
1200 nodeObject,
1201 &Interface->u.LockVideoMemory.address
1202 ));
1203#endif
1204
1205
1206#if gcdSECURE_USER
1207 /* Return logical address as physical address. */
1208 Interface->u.LockVideoMemory.address =
1209 (gctUINT32)(Interface->u.LockVideoMemory.memory);
1210#endif
1211 gcmkONERROR(
1212 gckKERNEL_AddProcessDB(Kernel,
1213 ProcessID, gcvDB_VIDEO_MEMORY_LOCKED,
1214 gcmINT2PTR(Interface->u.LockVideoMemory.node),
1215 gcvNULL,
1216 0));
1217
1218 gckVIDMEM_HANDLE_Reference(
1219 Kernel, ProcessID, (gctUINT32)Interface->u.LockVideoMemory.node);
1220
1221 gcmkFOOTER_NO();
1222 return gcvSTATUS_OK;
1223
1224OnError:
1225 if (locked)
1226 {
1227 /* Roll back the lock. */
1228 gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
1229 nodeObject,
1230 gcvSURF_TYPE_UNKNOWN,
1231 &asynchronous));
1232
1233 if (gcvTRUE == asynchronous)
1234 {
1235 /* Bottom Half */
1236 gcmkVERIFY_OK(gckVIDMEM_Unlock(Kernel,
1237 nodeObject,
1238 gcvSURF_TYPE_UNKNOWN,
1239 gcvNULL));
1240 }
1241 }
1242
1243 if (nodeObject != gcvNULL)
1244 {
1245 gckVIDMEM_NODE_Dereference(Kernel, nodeObject);
1246 }
1247
1248 gcmkFOOTER();
1249 return status;
1250}
1251
1252/*******************************************************************************
1253**
1254** gckKERNEL_UnlockVideoMemory
1255**
1256** Unlock a video memory node.
1257**
1258** INPUT:
1259**
1260** gckKERNEL Kernel
1261** Pointer to an gckKERNEL object.
1262**
1263** gctUINT32 ProcessID
1264** ProcessID of current process.
1265**
1266** gcsHAL_INTERFACE * Interface
1267** Pointer to a gcsHAL_INTERFACE structure that defines the command to
1268** be dispatched.
1269**
1270** OUTPUT:
1271**
1272** gcsHAL_INTERFACE * Interface
1273** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
1274** returned.
1275*/
1276gceSTATUS
1277gckKERNEL_UnlockVideoMemory(
1278 IN gckKERNEL Kernel,
1279 IN gctUINT32 ProcessID,
1280 IN OUT gcsHAL_INTERFACE * Interface
1281 )
1282{
1283 gceSTATUS status;
1284 gckVIDMEM_NODE nodeObject;
1285 gcuVIDMEM_NODE_PTR node;
1286
1287 gcmkHEADER_ARG("Kernel=0x%08X ProcessID=%d",
1288 Kernel, ProcessID);
1289
1290 gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
1291 Kernel,
1292 ProcessID,
1293 (gctUINT32)Interface->u.UnlockVideoMemory.node,
1294 &nodeObject));
1295
1296 node = nodeObject->node;
1297
1298 /* Unlock video memory. */
1299#if gcdSECURE_USER
1300 /* Save node information before it disappears. */
1301 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1302 {
1303 logical = gcvNULL;
1304 bytes = 0;
1305 }
1306 else
1307 {
1308 logical = node->Virtual.logical;
1309 bytes = node->Virtual.bytes;
1310 }
1311#endif
1312
1313 /* Unlock video memory. */
1314 gcmkONERROR(gckVIDMEM_Unlock(
1315 Kernel,
1316 nodeObject,
1317 Interface->u.UnlockVideoMemory.type,
1318 &Interface->u.UnlockVideoMemory.asynchroneous));
1319
1320#if gcdSECURE_USER
1321 /* Flush the translation cache for virtual surfaces. */
1322 if (logical != gcvNULL)
1323 {
1324 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(Kernel,
1325 cache,
1326 logical,
1327 bytes));
1328 }
1329#endif
1330
1331 gcmkFOOTER_NO();
1332 return gcvSTATUS_OK;
1333
1334OnError:
1335 gcmkFOOTER();
1336 return status;
1337}
1338
1339gceSTATUS
1340gckKERNEL_QueryDatabase(
1341 IN gckKERNEL Kernel,
1342 IN gctUINT32 ProcessID,
1343 IN OUT gcsHAL_INTERFACE * Interface
1344 )
1345{
1346 gceSTATUS status;
1347 gctINT i;
1348
1349 gceDATABASE_TYPE type[3] = {
1350 gcvDB_VIDEO_MEMORY | (gcvPOOL_SYSTEM << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
1351 gcvDB_VIDEO_MEMORY | (gcvPOOL_CONTIGUOUS << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
1352 gcvDB_VIDEO_MEMORY | (gcvPOOL_VIRTUAL << gcdDB_VIDEO_MEMORY_POOL_SHIFT),
1353 };
1354
1355 gcmkHEADER();
1356
1357 /* Query video memory. */
1358 gcmkONERROR(
1359 gckKERNEL_QueryProcessDB(Kernel,
1360 Interface->u.Database.processID,
1361 !Interface->u.Database.validProcessID,
1362 gcvDB_VIDEO_MEMORY,
1363 &Interface->u.Database.vidMem));
1364
1365 /* Query non-paged memory. */
1366 gcmkONERROR(
1367 gckKERNEL_QueryProcessDB(Kernel,
1368 Interface->u.Database.processID,
1369 !Interface->u.Database.validProcessID,
1370 gcvDB_NON_PAGED,
1371 &Interface->u.Database.nonPaged));
1372
1373 /* Query contiguous memory. */
1374 gcmkONERROR(
1375 gckKERNEL_QueryProcessDB(Kernel,
1376 Interface->u.Database.processID,
1377 !Interface->u.Database.validProcessID,
1378 gcvDB_CONTIGUOUS,
1379 &Interface->u.Database.contiguous));
1380
1381 /* Query GPU idle time. */
1382 gcmkONERROR(
1383 gckKERNEL_QueryProcessDB(Kernel,
1384 Interface->u.Database.processID,
1385 !Interface->u.Database.validProcessID,
1386 gcvDB_IDLE,
1387 &Interface->u.Database.gpuIdle));
1388 for (i = 0; i < 3; i++)
1389 {
1390 /* Query each video memory pool. */
1391 gcmkONERROR(
1392 gckKERNEL_QueryProcessDB(Kernel,
1393 Interface->u.Database.processID,
1394 !Interface->u.Database.validProcessID,
1395 type[i],
1396 &Interface->u.Database.vidMemPool[i]));
1397 }
1398
1399 /* Query virtual command buffer pool. */
1400 gcmkONERROR(
1401 gckKERNEL_QueryProcessDB(Kernel,
1402 Interface->u.Database.processID,
1403 !Interface->u.Database.validProcessID,
1404 gcvDB_COMMAND_BUFFER,
1405 &Interface->u.Database.vidMemPool[2]));
1406
1407#if gcmIS_DEBUG(gcdDEBUG_TRACE)
1408 gckKERNEL_DumpVidMemUsage(Kernel, Interface->u.Database.processID);
1409#endif
1410
1411 gcmkFOOTER_NO();
1412 return gcvSTATUS_OK;
1413
1414OnError:
1415 gcmkFOOTER();
1416 return status;
1417}
1418
1419gceSTATUS
1420gckKERNEL_ConfigPowerManagement(
1421 IN gckKERNEL Kernel,
1422 IN OUT gcsHAL_INTERFACE * Interface
1423)
1424{
1425 gceSTATUS status;
1426 gctBOOL enable = Interface->u.ConfigPowerManagement.enable;
1427
1428 gcmkHEADER();
1429
1430 gcmkONERROR(gckHARDWARE_SetPowerManagement(Kernel->hardware, enable));
1431
1432 if (enable == gcvFALSE)
1433 {
1434 gcmkONERROR(
1435 gckHARDWARE_SetPowerManagementState(Kernel->hardware, gcvPOWER_ON));
1436 }
1437
1438 gcmkFOOTER_NO();
1439 return gcvSTATUS_OK;
1440
1441OnError:
1442 gcmkFOOTER();
1443 return status;
1444}
1445
1446gceSTATUS
1447gckKERNEL_WrapUserMemory(
1448 IN gckKERNEL Kernel,
1449 IN gctUINT32 ProcessID,
1450 IN gcsUSER_MEMORY_DESC_PTR Desc,
1451 OUT gctUINT32 * Node
1452 )
1453{
1454 gceSTATUS status;
1455 gcuVIDMEM_NODE_PTR node = gcvNULL;
1456 gctUINT32 handle;
1457 gceDATABASE_TYPE databaseRecordType;
1458
1459 gcmkHEADER_ARG("Kernel=0x%X Desc=%x", Kernel, Desc);
1460
1461 gcmkONERROR(gckVIDMEM_ConstructVirtualFromUserMemory(
1462 Kernel,
1463 Desc,
1464 &node
1465 ));
1466
1467 /* Allocate handle for this video memory. */
1468 gcmkONERROR(gckVIDMEM_NODE_Allocate(
1469 Kernel,
1470 node,
1471 gcvSURF_BITMAP,
1472 gcvPOOL_VIRTUAL,
1473 &handle
1474 ));
1475
1476 /* Wrapped node is treated as gcvPOOL_VIRTUAL, but in statistic view,
1477 * it is gcvPOOL_USER.
1478 */
1479 databaseRecordType
1480 = gcvDB_VIDEO_MEMORY
1481 | (gcvSURF_BITMAP << gcdDB_VIDEO_MEMORY_TYPE_SHIFT)
1482 | (gcvPOOL_USER << gcdDB_VIDEO_MEMORY_POOL_SHIFT)
1483 ;
1484
1485 /* Record in process db. */
1486 gcmkONERROR(gckKERNEL_AddProcessDB(
1487 Kernel,
1488 ProcessID,
1489 databaseRecordType,
1490 gcmINT2PTR(handle),
1491 gcvNULL,
1492 node->Virtual.bytes
1493 ));
1494
1495 /* Return handle of the node. */
1496 *Node = handle;
1497
1498 gcmkFOOTER_NO();
1499 return gcvSTATUS_OK;
1500
1501OnError:
1502 gcmkFOOTER();
1503 return status;
1504}
1505
1506/*******************************************************************************
1507**
1508** gckKERNEL_Dispatch
1509**
1510** Dispatch a command received from the user HAL layer.
1511**
1512** INPUT:
1513**
1514** gckKERNEL Kernel
1515** Pointer to an gckKERNEL object.
1516**
1517** gctBOOL FromUser
1518** whether the call is from the user space.
1519**
1520** gcsHAL_INTERFACE * Interface
1521** Pointer to a gcsHAL_INTERFACE structure that defines the command to
1522** be dispatched.
1523**
1524** OUTPUT:
1525**
1526** gcsHAL_INTERFACE * Interface
1527** Pointer to a gcsHAL_INTERFACE structure that receives any data to be
1528** returned.
1529*/
1530gceSTATUS
1531gckKERNEL_Dispatch(
1532 IN gckKERNEL Kernel,
1533 IN gctBOOL FromUser,
1534 IN OUT gcsHAL_INTERFACE * Interface
1535 )
1536{
1537 gceSTATUS status = gcvSTATUS_OK;
1538 gctPHYS_ADDR physical = gcvNULL;
1539 gctSIZE_T bytes;
1540 gctPOINTER logical = gcvNULL;
1541 gctPOINTER info = gcvNULL;
1542 gckCONTEXT context = gcvNULL;
1543 gckKERNEL kernel = Kernel;
1544 gctUINT32 address;
1545 gctUINT32 processID;
1546#if gcdSECURE_USER
1547 gcskSECURE_CACHE_PTR cache;
1548 gctPOINTER logical;
1549#endif
1550 gctUINT64 paddr = gcvINVALID_ADDRESS;
1551#if !USE_NEW_LINUX_SIGNAL
1552 gctSIGNAL signal;
1553#endif
1554 gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
1555
1556 gckVIDMEM_NODE nodeObject;
1557 gctBOOL powerMutexAcquired = gcvFALSE;
1558
1559 gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
1560 Kernel, FromUser, Interface);
1561
1562 /* Verify the arguments. */
1563 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1564 gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
1565
1566#if gcmIS_DEBUG(gcdDEBUG_TRACE)
1567 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
1568 "Dispatching command %d (%s)",
1569 Interface->command, _DispatchText[Interface->command]);
1570#endif
1571#if QNX_SINGLE_THREADED_DEBUGGING
1572 gckOS_AcquireMutex(Kernel->os, Kernel->debugMutex, gcvINFINITE);
1573#endif
1574
1575 /* Get the current process ID. */
1576 gcmkONERROR(gckOS_GetProcessID(&processID));
1577
1578#if gcdSECURE_USER
1579 gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
1580#endif
1581
1582 /* Dispatch on command. */
1583 switch (Interface->command)
1584 {
1585 case gcvHAL_GET_BASE_ADDRESS:
1586 /* Get base address. */
1587 gcmkONERROR(
1588 gckOS_GetBaseAddress(Kernel->os,
1589 &Interface->u.GetBaseAddress.baseAddress));
1590 break;
1591
1592 case gcvHAL_QUERY_VIDEO_MEMORY:
1593 /* Query video memory size. */
1594 gcmkONERROR(gckKERNEL_QueryVideoMemory(Kernel, Interface));
1595 break;
1596
1597 case gcvHAL_QUERY_CHIP_IDENTITY:
1598 /* Query chip identity. */
1599 gcmkONERROR(
1600 gckHARDWARE_QueryChipIdentity(
1601 Kernel->hardware,
1602 &Interface->u.QueryChipIdentity));
1603 break;
1604
1605 case gcvHAL_MAP_MEMORY:
1606 physical = gcmINT2PTR(Interface->u.MapMemory.physical);
1607
1608 /* Map memory. */
1609 gcmkONERROR(
1610 gckKERNEL_MapMemory(Kernel,
1611 physical,
1612 (gctSIZE_T) Interface->u.MapMemory.bytes,
1613 &logical));
1614
1615 Interface->u.MapMemory.logical = gcmPTR_TO_UINT64(logical);
1616
1617 gcmkVERIFY_OK(
1618 gckKERNEL_AddProcessDB(Kernel,
1619 processID, gcvDB_MAP_MEMORY,
1620 logical,
1621 physical,
1622 (gctSIZE_T) Interface->u.MapMemory.bytes));
1623 break;
1624
1625 case gcvHAL_UNMAP_MEMORY:
1626 physical = gcmINT2PTR(Interface->u.UnmapMemory.physical);
1627
1628 gcmkVERIFY_OK(
1629 gckKERNEL_RemoveProcessDB(Kernel,
1630 processID, gcvDB_MAP_MEMORY,
1631 gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
1632
1633 /* Unmap memory. */
1634 gcmkONERROR(
1635 gckKERNEL_UnmapMemory(Kernel,
1636 physical,
1637 (gctSIZE_T) Interface->u.UnmapMemory.bytes,
1638 gcmUINT64_TO_PTR(Interface->u.UnmapMemory.logical)));
1639 break;
1640
1641 case gcvHAL_ALLOCATE_NON_PAGED_MEMORY:
1642 bytes = (gctSIZE_T) Interface->u.AllocateNonPagedMemory.bytes;
1643
1644 /* Allocate non-paged memory. */
1645 gcmkONERROR(
1646 gckOS_AllocateNonPagedMemory(
1647 Kernel->os,
1648 FromUser,
1649 &bytes,
1650 &physical,
1651 &logical));
1652
1653 Interface->u.AllocateNonPagedMemory.bytes = bytes;
1654 Interface->u.AllocateNonPagedMemory.logical = gcmPTR_TO_UINT64(logical);
1655 Interface->u.AllocateNonPagedMemory.physical = gcmPTR_TO_NAME(physical);
1656
1657 gcmkVERIFY_OK(
1658 gckKERNEL_AddProcessDB(Kernel,
1659 processID, gcvDB_NON_PAGED,
1660 logical,
1661 gcmINT2PTR(Interface->u.AllocateNonPagedMemory.physical),
1662 bytes));
1663 break;
1664
1665 case gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER:
1666 bytes = (gctSIZE_T) Interface->u.AllocateVirtualCommandBuffer.bytes;
1667
1668 gcmkONERROR(
1669 gckKERNEL_AllocateVirtualCommandBuffer(
1670 Kernel,
1671 FromUser,
1672 &bytes,
1673 &physical,
1674 &logical));
1675
1676 Interface->u.AllocateVirtualCommandBuffer.bytes = bytes;
1677 Interface->u.AllocateVirtualCommandBuffer.logical = gcmPTR_TO_UINT64(logical);
1678 Interface->u.AllocateVirtualCommandBuffer.physical = gcmPTR_TO_NAME(physical);
1679
1680 gcmkVERIFY_OK(
1681 gckKERNEL_AddProcessDB(Kernel,
1682 processID, gcvDB_COMMAND_BUFFER,
1683 logical,
1684 gcmINT2PTR(Interface->u.AllocateVirtualCommandBuffer.physical),
1685 bytes));
1686 break;
1687
1688 case gcvHAL_FREE_NON_PAGED_MEMORY:
1689 physical = gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical);
1690
1691 gcmkVERIFY_OK(
1692 gckKERNEL_RemoveProcessDB(Kernel,
1693 processID, gcvDB_NON_PAGED,
1694 gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
1695
1696 /* Unmap user logical out of physical memory first. */
1697 gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
1698 physical,
1699 (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
1700 gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
1701
1702 /* Free non-paged memory. */
1703 gcmkONERROR(
1704 gckOS_FreeNonPagedMemory(Kernel->os,
1705 (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
1706 physical,
1707 gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
1708
1709#if gcdSECURE_USER
1710 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
1711 Kernel,
1712 cache,
1713 gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical),
1714 (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes));
1715#endif
1716
1717 gcmRELEASE_NAME(Interface->u.FreeNonPagedMemory.physical);
1718 break;
1719
1720 case gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY:
1721 bytes = (gctSIZE_T) Interface->u.AllocateContiguousMemory.bytes;
1722
1723 /* Allocate contiguous memory. */
1724 gcmkONERROR(gckOS_AllocateContiguous(
1725 Kernel->os,
1726 FromUser,
1727 &bytes,
1728 &physical,
1729 &logical));
1730
1731 Interface->u.AllocateContiguousMemory.bytes = bytes;
1732 Interface->u.AllocateContiguousMemory.logical = gcmPTR_TO_UINT64(logical);
1733 Interface->u.AllocateContiguousMemory.physical = gcmPTR_TO_NAME(physical);
1734
1735 gcmkONERROR(gckHARDWARE_ConvertLogical(
1736 Kernel->hardware,
1737 logical,
1738 gcvTRUE,
1739 &Interface->u.AllocateContiguousMemory.address));
1740
1741 gcmkVERIFY_OK(gckKERNEL_AddProcessDB(
1742 Kernel,
1743 processID, gcvDB_CONTIGUOUS,
1744 logical,
1745 gcmINT2PTR(Interface->u.AllocateContiguousMemory.physical),
1746 bytes));
1747 break;
1748
1749 case gcvHAL_FREE_CONTIGUOUS_MEMORY:
1750 physical = gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical);
1751
1752 gcmkVERIFY_OK(
1753 gckKERNEL_RemoveProcessDB(Kernel,
1754 processID, gcvDB_CONTIGUOUS,
1755 gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
1756
1757 /* Unmap user logical out of physical memory first. */
1758 gcmkONERROR(gckOS_UnmapUserLogical(Kernel->os,
1759 physical,
1760 (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
1761 gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
1762
1763 /* Free contiguous memory. */
1764 gcmkONERROR(
1765 gckOS_FreeContiguous(Kernel->os,
1766 physical,
1767 gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
1768 (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
1769
1770#if gcdSECURE_USER
1771 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
1772 Kernel,
1773 cache,
1774 gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical),
1775 (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes));
1776#endif
1777
1778 gcmRELEASE_NAME(Interface->u.FreeContiguousMemory.physical);
1779 break;
1780
1781 case gcvHAL_ALLOCATE_VIDEO_MEMORY:
1782
1783 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
1784
1785 break;
1786
1787 case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
1788 /* Allocate memory. */
1789 gcmkONERROR(
1790 gckKERNEL_AllocateLinearMemory(Kernel, processID,
1791 &Interface->u.AllocateLinearVideoMemory.pool,
1792 Interface->u.AllocateLinearVideoMemory.bytes,
1793 Interface->u.AllocateLinearVideoMemory.alignment,
1794 Interface->u.AllocateLinearVideoMemory.type,
1795 Interface->u.AllocateLinearVideoMemory.flag,
1796 &Interface->u.AllocateLinearVideoMemory.node));
1797 break;
1798
1799 case gcvHAL_RELEASE_VIDEO_MEMORY:
1800 /* Release video memory. */
1801 gcmkONERROR(gckKERNEL_ReleaseVideoMemory(
1802 Kernel, processID,
1803 (gctUINT32)Interface->u.ReleaseVideoMemory.node
1804 ));
1805 break;
1806
1807 case gcvHAL_LOCK_VIDEO_MEMORY:
1808 /* Lock video memory. */
1809 gcmkONERROR(gckKERNEL_LockVideoMemory(Kernel, Kernel->core, processID, FromUser, Interface));
1810 break;
1811
1812 case gcvHAL_UNLOCK_VIDEO_MEMORY:
1813 /* Unlock video memory. */
1814 gcmkONERROR(gckKERNEL_UnlockVideoMemory(Kernel, processID, Interface));
1815 break;
1816
1817 case gcvHAL_EVENT_COMMIT:
1818 /* Commit an event queue. */
1819 gcmkONERROR(
1820 gckEVENT_Commit(Kernel->eventObj,
1821 gcmUINT64_TO_PTR(Interface->u.Event.queue)));
1822 break;
1823
1824 case gcvHAL_COMMIT:
1825 /* Commit a command and context buffer. */
1826 gcmkONERROR(
1827 gckCOMMAND_Commit(Kernel->command,
1828 Interface->u.Commit.context ?
1829 gcmNAME_TO_PTR(Interface->u.Commit.context) : gcvNULL,
1830 gcmUINT64_TO_PTR(Interface->u.Commit.commandBuffer),
1831 gcmUINT64_TO_PTR(Interface->u.Commit.delta),
1832 gcmUINT64_TO_PTR(Interface->u.Commit.queue),
1833 processID));
1834
1835 break;
1836
1837 case gcvHAL_STALL:
1838 /* Stall the command queue. */
1839 gcmkONERROR(gckCOMMAND_Stall(Kernel->command, gcvFALSE));
1840 break;
1841
1842 case gcvHAL_MAP_USER_MEMORY:
1843 /* Map user memory to DMA. */
1844 gcmkONERROR(
1845 gckOS_MapUserMemory(Kernel->os,
1846 Kernel->core,
1847 gcmUINT64_TO_PTR(Interface->u.MapUserMemory.memory),
1848 Interface->u.MapUserMemory.physical,
1849 (gctSIZE_T) Interface->u.MapUserMemory.size,
1850 &info,
1851 &Interface->u.MapUserMemory.address));
1852
1853 Interface->u.MapUserMemory.info = gcmPTR_TO_NAME(info);
1854
1855 gcmkVERIFY_OK(
1856 gckKERNEL_AddProcessDB(Kernel,
1857 processID, gcvDB_MAP_USER_MEMORY,
1858 gcmINT2PTR(Interface->u.MapUserMemory.info),
1859 gcmUINT64_TO_PTR(Interface->u.MapUserMemory.memory),
1860 (gctSIZE_T) Interface->u.MapUserMemory.size));
1861 break;
1862
1863 case gcvHAL_UNMAP_USER_MEMORY:
1864 address = Interface->u.UnmapUserMemory.address;
1865 info = gcmNAME_TO_PTR(Interface->u.UnmapUserMemory.info);
1866
1867 gcmkVERIFY_OK(
1868 gckKERNEL_RemoveProcessDB(Kernel,
1869 processID, gcvDB_MAP_USER_MEMORY,
1870 gcmINT2PTR(Interface->u.UnmapUserMemory.info)));
1871 /* Unmap user memory. */
1872 gcmkONERROR(
1873 gckOS_UnmapUserMemory(Kernel->os,
1874 Kernel->core,
1875 gcmUINT64_TO_PTR(Interface->u.UnmapUserMemory.memory),
1876 (gctSIZE_T) Interface->u.UnmapUserMemory.size,
1877 info,
1878 address));
1879
1880#if gcdSECURE_USER
1881 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
1882 Kernel,
1883 cache,
1884 gcmUINT64_TO_PTR(Interface->u.UnmapUserMemory.memory),
1885 (gctSIZE_T) Interface->u.UnmapUserMemory.size));
1886#endif
1887
1888 gcmRELEASE_NAME(Interface->u.UnmapUserMemory.info);
1889 break;
1890
1891#if !USE_NEW_LINUX_SIGNAL
1892 case gcvHAL_USER_SIGNAL:
1893 /* Dispatch depends on the user signal subcommands. */
1894 switch(Interface->u.UserSignal.command)
1895 {
1896 case gcvUSER_SIGNAL_CREATE:
1897 /* Create a signal used in the user space. */
1898 gcmkONERROR(
1899 gckOS_CreateUserSignal(Kernel->os,
1900 Interface->u.UserSignal.manualReset,
1901 &Interface->u.UserSignal.id));
1902
1903 gcmkVERIFY_OK(
1904 gckKERNEL_AddProcessDB(Kernel,
1905 processID, gcvDB_SIGNAL,
1906 gcmINT2PTR(Interface->u.UserSignal.id),
1907 gcvNULL,
1908 0));
1909 break;
1910
1911 case gcvUSER_SIGNAL_DESTROY:
1912 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
1913 Kernel,
1914 processID, gcvDB_SIGNAL,
1915 gcmINT2PTR(Interface->u.UserSignal.id)));
1916
1917 /* Destroy the signal. */
1918 gcmkONERROR(
1919 gckOS_DestroyUserSignal(Kernel->os,
1920 Interface->u.UserSignal.id));
1921 break;
1922
1923 case gcvUSER_SIGNAL_SIGNAL:
1924 /* Signal the signal. */
1925 gcmkONERROR(
1926 gckOS_SignalUserSignal(Kernel->os,
1927 Interface->u.UserSignal.id,
1928 Interface->u.UserSignal.state));
1929 break;
1930
1931 case gcvUSER_SIGNAL_WAIT:
1932 /* Wait on the signal. */
1933 status = gckOS_WaitUserSignal(Kernel->os,
1934 Interface->u.UserSignal.id,
1935 Interface->u.UserSignal.wait);
1936
1937 break;
1938
1939 case gcvUSER_SIGNAL_MAP:
1940 gcmkONERROR(
1941 gckOS_MapSignal(Kernel->os,
1942 (gctSIGNAL)(gctUINTPTR_T)Interface->u.UserSignal.id,
1943 (gctHANDLE)(gctUINTPTR_T)processID,
1944 &signal));
1945
1946 gcmkVERIFY_OK(
1947 gckKERNEL_AddProcessDB(Kernel,
1948 processID, gcvDB_SIGNAL,
1949 gcmINT2PTR(Interface->u.UserSignal.id),
1950 gcvNULL,
1951 0));
1952 break;
1953
1954 case gcvUSER_SIGNAL_UNMAP:
1955 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
1956 Kernel,
1957 processID, gcvDB_SIGNAL,
1958 gcmINT2PTR(Interface->u.UserSignal.id)));
1959
1960 /* Destroy the signal. */
1961 gcmkONERROR(
1962 gckOS_DestroyUserSignal(Kernel->os,
1963 Interface->u.UserSignal.id));
1964 break;
1965
1966 default:
1967 /* Invalid user signal command. */
1968 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
1969 }
1970 break;
1971#endif
1972
1973 case gcvHAL_SET_POWER_MANAGEMENT_STATE:
1974 /* Set the power management state. */
1975 gcmkONERROR(
1976 gckHARDWARE_SetPowerManagementState(
1977 Kernel->hardware,
1978 Interface->u.SetPowerManagement.state));
1979 break;
1980
1981 case gcvHAL_QUERY_POWER_MANAGEMENT_STATE:
1982 /* Chip is not idle. */
1983 Interface->u.QueryPowerManagement.isIdle = gcvFALSE;
1984
1985 /* Query the power management state. */
1986 gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
1987 Kernel->hardware,
1988 &Interface->u.QueryPowerManagement.state));
1989
1990 /* Query the idle state. */
1991 gcmkONERROR(
1992 gckHARDWARE_QueryIdle(Kernel->hardware,
1993 &Interface->u.QueryPowerManagement.isIdle));
1994 break;
1995
1996 case gcvHAL_READ_REGISTER:
1997#if gcdREGISTER_ACCESS_FROM_USER
1998 {
1999 gceCHIPPOWERSTATE power;
2000
2001 gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
2002 powerMutexAcquired = gcvTRUE;
2003 gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
2004 &power));
2005 if (power == gcvPOWER_ON)
2006 {
2007 /* Read a register. */
2008 gcmkONERROR(gckOS_ReadRegisterEx(
2009 Kernel->os,
2010 Kernel->core,
2011 Interface->u.ReadRegisterData.address,
2012 &Interface->u.ReadRegisterData.data));
2013 }
2014 else
2015 {
2016 /* Chip is in power-state. */
2017 Interface->u.ReadRegisterData.data = 0;
2018 status = gcvSTATUS_CHIP_NOT_READY;
2019 }
2020 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
2021 powerMutexAcquired = gcvFALSE;
2022 }
2023#else
2024 /* No access from user land to read registers. */
2025 Interface->u.ReadRegisterData.data = 0;
2026 status = gcvSTATUS_NOT_SUPPORTED;
2027#endif
2028 break;
2029
2030
2031 case gcvHAL_WRITE_REGISTER:
2032#if gcdREGISTER_ACCESS_FROM_USER
2033 {
2034 gceCHIPPOWERSTATE power;
2035
2036 gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->hardware->powerMutex, gcvINFINITE));
2037 powerMutexAcquired = gcvTRUE;
2038 gcmkONERROR(gckHARDWARE_QueryPowerManagementState(Kernel->hardware,
2039 &power));
2040 if (power == gcvPOWER_ON)
2041 {
2042 /* Write a register. */
2043 gcmkONERROR(
2044 gckOS_WriteRegisterEx(Kernel->os,
2045 Kernel->core,
2046 Interface->u.WriteRegisterData.address,
2047 Interface->u.WriteRegisterData.data));
2048 }
2049 else
2050 {
2051 /* Chip is in power-state. */
2052 Interface->u.WriteRegisterData.data = 0;
2053 status = gcvSTATUS_CHIP_NOT_READY;
2054 }
2055 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
2056 powerMutexAcquired = gcvFALSE;
2057 }
2058#else
2059 /* No access from user land to write registers. */
2060 status = gcvSTATUS_NOT_SUPPORTED;
2061#endif
2062 break;
2063
2064 case gcvHAL_READ_ALL_PROFILE_REGISTERS:
2065#if VIVANTE_PROFILER && VIVANTE_PROFILER_CONTEXT
2066 /* Read profile data according to the context. */
2067 gcmkONERROR(
2068 gckHARDWARE_QueryContextProfile(
2069 Kernel->hardware,
2070 Kernel->profileCleanRegister,
2071 gcmNAME_TO_PTR(Interface->u.RegisterProfileData.context),
2072 &Interface->u.RegisterProfileData.counters));
2073#elif VIVANTE_PROFILER
2074 /* Read all 3D profile registers. */
2075 gcmkONERROR(
2076 gckHARDWARE_QueryProfileRegisters(
2077 Kernel->hardware,
2078 Kernel->profileCleanRegister,
2079 &Interface->u.RegisterProfileData.counters));
2080#else
2081 status = gcvSTATUS_OK;
2082#endif
2083 break;
2084
2085 case gcvHAL_PROFILE_REGISTERS_2D:
2086#if VIVANTE_PROFILER
2087 /* Read all 2D profile registers. */
2088 gcmkONERROR(
2089 gckHARDWARE_ProfileEngine2D(
2090 Kernel->hardware,
2091 gcmUINT64_TO_PTR(Interface->u.RegisterProfileData2D.hwProfile2D)));
2092#else
2093 status = gcvSTATUS_OK;
2094#endif
2095 break;
2096
2097 case gcvHAL_GET_PROFILE_SETTING:
2098#if VIVANTE_PROFILER
2099 /* Get profile setting */
2100 Interface->u.GetProfileSetting.enable = Kernel->profileEnable;
2101#endif
2102
2103 status = gcvSTATUS_OK;
2104 break;
2105
2106 case gcvHAL_SET_PROFILE_SETTING:
2107#if VIVANTE_PROFILER
2108 /* Set profile setting */
2109 if(Kernel->hardware->gpuProfiler)
2110 {
2111 Kernel->profileEnable = Interface->u.SetProfileSetting.enable;
2112
2113 if ((Kernel->hardware->identity.chipModel == gcv1500 && Kernel->hardware->identity.chipRevision == 0x5246) ||
2114 (Kernel->hardware->identity.chipModel == gcv3000 && Kernel->hardware->identity.chipRevision == 0x5450))
2115 gcmkONERROR(gckHARDWARE_InitProfiler(Kernel->hardware));
2116
2117#if VIVANTE_PROFILER_NEW
2118 if (Kernel->profileEnable)
2119 gckHARDWARE_InitProfiler(Kernel->hardware);
2120#endif
2121 }
2122 else
2123 {
2124 status = gcvSTATUS_NOT_SUPPORTED;
2125 break;
2126 }
2127#endif
2128
2129 status = gcvSTATUS_OK;
2130 break;
2131
2132#if VIVANTE_PROFILER_PERDRAW
2133 case gcvHAL_READ_PROFILER_REGISTER_SETTING:
2134 #if VIVANTE_PROFILER
2135 Kernel->profileCleanRegister = Interface->u.SetProfilerRegisterClear.bclear;
2136 #endif
2137 status = gcvSTATUS_OK;
2138 break;
2139#endif
2140
2141 case gcvHAL_QUERY_KERNEL_SETTINGS:
2142 /* Get kernel settings. */
2143 gcmkONERROR(
2144 gckKERNEL_QuerySettings(Kernel,
2145 &Interface->u.QueryKernelSettings.settings));
2146 break;
2147
2148 case gcvHAL_RESET:
2149 /* Reset the hardware. */
2150 gcmkONERROR(
2151 gckHARDWARE_Reset(Kernel->hardware));
2152 break;
2153
2154 case gcvHAL_DEBUG:
2155 /* Set debug level and zones. */
2156 if (Interface->u.Debug.set)
2157 {
2158 gckOS_SetDebugLevel(Interface->u.Debug.level);
2159 gckOS_SetDebugZones(Interface->u.Debug.zones,
2160 Interface->u.Debug.enable);
2161 }
2162
2163 if (Interface->u.Debug.message[0] != '\0')
2164 {
2165 /* Print a message to the debugger. */
2166 if (Interface->u.Debug.type == gcvMESSAGE_TEXT)
2167 {
2168 gckOS_CopyPrint(Interface->u.Debug.message);
2169 }
2170 else
2171 {
2172 gckOS_DumpBuffer(Kernel->os,
2173 Interface->u.Debug.message,
2174 Interface->u.Debug.messageSize,
2175 gceDUMP_BUFFER_FROM_USER,
2176 gcvTRUE);
2177 }
2178 }
2179 status = gcvSTATUS_OK;
2180 break;
2181
2182 case gcvHAL_DUMP_GPU_STATE:
2183 {
2184 gceCHIPPOWERSTATE power;
2185
2186 _DumpDriverConfigure(Kernel);
2187
2188 gcmkONERROR(gckHARDWARE_QueryPowerManagementState(
2189 Kernel->hardware,
2190 &power
2191 ));
2192
2193 if (power == gcvPOWER_ON)
2194 {
2195 Interface->u.ReadRegisterData.data = 1;
2196
2197 _DumpState(Kernel);
2198 }
2199 else
2200 {
2201 Interface->u.ReadRegisterData.data = 0;
2202 status = gcvSTATUS_CHIP_NOT_READY;
2203
2204 gcmkPRINT("[galcore]: Can't dump state if GPU isn't POWER ON.");
2205 }
2206 }
2207 break;
2208
2209 case gcvHAL_DUMP_EVENT:
2210 break;
2211
2212 case gcvHAL_CACHE:
2213
2214 logical = gcmUINT64_TO_PTR(Interface->u.Cache.logical);
2215
2216 if (Interface->u.Cache.node)
2217 {
2218 gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
2219 Kernel,
2220 processID,
2221 Interface->u.Cache.node,
2222 &nodeObject));
2223
2224 if (nodeObject->node->VidMem.memory->object.type == gcvOBJ_VIDMEM
2225 || nodeObject->node->Virtual.contiguous
2226 )
2227 {
2228 /* If memory is contiguous, get physical address. */
2229 gcmkONERROR(gckOS_UserLogicalToPhysical(
2230 Kernel->os, logical, &paddr));
2231 }
2232 }
2233
2234 bytes = (gctSIZE_T) Interface->u.Cache.bytes;
2235 switch(Interface->u.Cache.operation)
2236 {
2237 case gcvCACHE_FLUSH:
2238 /* Clean and invalidate the cache. */
2239 status = gckOS_CacheFlush(Kernel->os,
2240 processID,
2241 physical,
2242 paddr,
2243 logical,
2244 bytes);
2245 break;
2246 case gcvCACHE_CLEAN:
2247 /* Clean the cache. */
2248 status = gckOS_CacheClean(Kernel->os,
2249 processID,
2250 physical,
2251 paddr,
2252 logical,
2253 bytes);
2254 break;
2255 case gcvCACHE_INVALIDATE:
2256 /* Invalidate the cache. */
2257 status = gckOS_CacheInvalidate(Kernel->os,
2258 processID,
2259 physical,
2260 paddr,
2261 logical,
2262 bytes);
2263 break;
2264
2265 case gcvCACHE_MEMORY_BARRIER:
2266 status = gckOS_MemoryBarrier(Kernel->os,
2267 logical);
2268 break;
2269 default:
2270 status = gcvSTATUS_INVALID_ARGUMENT;
2271 break;
2272 }
2273 break;
2274
2275 case gcvHAL_TIMESTAMP:
2276 /* Check for invalid timer. */
2277 if ((Interface->u.TimeStamp.timer >= gcmCOUNTOF(Kernel->timers))
2278 || (Interface->u.TimeStamp.request != 2))
2279 {
2280 Interface->u.TimeStamp.timeDelta = 0;
2281 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
2282 }
2283
2284 /* Return timer results and reset timer. */
2285 {
2286 gcsTIMER_PTR timer = &(Kernel->timers[Interface->u.TimeStamp.timer]);
2287 gctUINT64 timeDelta = 0;
2288
2289 if (timer->stopTime < timer->startTime )
2290 {
2291 Interface->u.TimeStamp.timeDelta = 0;
2292 gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
2293 }
2294
2295 timeDelta = timer->stopTime - timer->startTime;
2296
2297 /* Check truncation overflow. */
2298 Interface->u.TimeStamp.timeDelta = (gctINT32) timeDelta;
2299 /*bit0~bit30 is available*/
2300 if (timeDelta>>31)
2301 {
2302 Interface->u.TimeStamp.timeDelta = 0;
2303 gcmkONERROR(gcvSTATUS_TIMER_OVERFLOW);
2304 }
2305
2306 status = gcvSTATUS_OK;
2307 }
2308 break;
2309
2310 case gcvHAL_DATABASE:
2311 gcmkONERROR(gckKERNEL_QueryDatabase(Kernel, processID, Interface));
2312 break;
2313
2314 case gcvHAL_VERSION:
2315 Interface->u.Version.major = gcvVERSION_MAJOR;
2316 Interface->u.Version.minor = gcvVERSION_MINOR;
2317 Interface->u.Version.patch = gcvVERSION_PATCH;
2318 Interface->u.Version.build = gcvVERSION_BUILD;
2319#if gcmIS_DEBUG(gcdDEBUG_TRACE)
2320 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
2321 "KERNEL version %d.%d.%d build %u",
2322 gcvVERSION_MAJOR, gcvVERSION_MINOR,
2323 gcvVERSION_PATCH, gcvVERSION_BUILD);
2324#endif
2325 break;
2326
2327 case gcvHAL_CHIP_INFO:
2328 /* Only if not support multi-core */
2329 Interface->u.ChipInfo.count = 1;
2330 Interface->u.ChipInfo.types[0] = Kernel->hardware->type;
2331 break;
2332
2333 case gcvHAL_ATTACH:
2334 /* Attach user process. */
2335 gcmkONERROR(
2336 gckCOMMAND_Attach(Kernel->command,
2337 &context,
2338 &bytes,
2339 &Interface->u.Attach.numStates,
2340 processID));
2341
2342 Interface->u.Attach.maxState = bytes;
2343 Interface->u.Attach.context = gcmPTR_TO_NAME(context);
2344
2345 if (Interface->u.Attach.map == gcvTRUE)
2346 {
2347 gcmkVERIFY_OK(
2348 gckCONTEXT_MapBuffer(context,
2349 Interface->u.Attach.physicals,
2350 Interface->u.Attach.logicals,
2351 &Interface->u.Attach.bytes));
2352 }
2353
2354 gcmkVERIFY_OK(
2355 gckKERNEL_AddProcessDB(Kernel,
2356 processID, gcvDB_CONTEXT,
2357 gcmINT2PTR(Interface->u.Attach.context),
2358 gcvNULL,
2359 0));
2360 break;
2361
2362 case gcvHAL_DETACH:
2363 gcmkVERIFY_OK(
2364 gckKERNEL_RemoveProcessDB(Kernel,
2365 processID, gcvDB_CONTEXT,
2366 gcmINT2PTR(Interface->u.Detach.context)));
2367
2368 /* Detach user process. */
2369 gcmkONERROR(
2370 gckCOMMAND_Detach(Kernel->command,
2371 gcmNAME_TO_PTR(Interface->u.Detach.context)));
2372
2373 gcmRELEASE_NAME(Interface->u.Detach.context);
2374 break;
2375
2376 case gcvHAL_COMPOSE:
2377 Interface->u.Compose.physical = gcmPTR_TO_UINT64(gcmNAME_TO_PTR(Interface->u.Compose.physical));
2378 /* Start composition. */
2379 gcmkONERROR(
2380 gckEVENT_Compose(Kernel->eventObj,
2381 &Interface->u.Compose));
2382 break;
2383
2384 case gcvHAL_SET_TIMEOUT:
2385 /* set timeOut value from user */
2386 gckKERNEL_SetTimeOut(Kernel, Interface->u.SetTimeOut.timeOut);
2387 break;
2388
2389 case gcvHAL_GET_FRAME_INFO:
2390 gcmkONERROR(gckHARDWARE_GetFrameInfo(
2391 Kernel->hardware,
2392 gcmUINT64_TO_PTR(Interface->u.GetFrameInfo.frameInfo)));
2393 break;
2394
2395 case gcvHAL_SET_FSCALE_VALUE:
2396#if gcdENABLE_FSCALE_VAL_ADJUST
2397 status = gckHARDWARE_SetFscaleValue(Kernel->hardware,
2398 Interface->u.SetFscaleValue.value);
2399#else
2400 status = gcvSTATUS_NOT_SUPPORTED;
2401#endif
2402 break;
2403 case gcvHAL_GET_FSCALE_VALUE:
2404#if gcdENABLE_FSCALE_VAL_ADJUST
2405 status = gckHARDWARE_GetFscaleValue(Kernel->hardware,
2406 &Interface->u.GetFscaleValue.value,
2407 &Interface->u.GetFscaleValue.minValue,
2408 &Interface->u.GetFscaleValue.maxValue);
2409#else
2410 status = gcvSTATUS_NOT_SUPPORTED;
2411#endif
2412 break;
2413
2414 case gcvHAL_NAME_VIDEO_MEMORY:
2415 gcmkONERROR(gckVIDMEM_NODE_Name(Kernel,
2416 Interface->u.NameVideoMemory.handle,
2417 &Interface->u.NameVideoMemory.name));
2418 break;
2419
2420 case gcvHAL_IMPORT_VIDEO_MEMORY:
2421 gcmkONERROR(gckVIDMEM_NODE_Import(Kernel,
2422 Interface->u.ImportVideoMemory.name,
2423 &Interface->u.ImportVideoMemory.handle));
2424
2425 gcmkONERROR(
2426 gckKERNEL_AddProcessDB(Kernel,
2427 processID, gcvDB_VIDEO_MEMORY,
2428 gcmINT2PTR(Interface->u.ImportVideoMemory.handle),
2429 gcvNULL,
2430 0));
2431 break;
2432
2433 case gcvHAL_GET_VIDEO_MEMORY_FD:
2434 gcmkONERROR(gckVIDMEM_NODE_GetFd(
2435 Kernel,
2436 Interface->u.GetVideoMemoryFd.handle,
2437 &Interface->u.GetVideoMemoryFd.fd
2438 ));
2439
2440 /* No need to add it to processDB because OS will release all fds when
2441 ** process quits.
2442 */
2443 break;
2444
2445 case gcvHAL_QUERY_RESET_TIME_STAMP:
2446 Interface->u.QueryResetTimeStamp.timeStamp = Kernel->resetTimeStamp;
2447 break;
2448
2449 case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
2450 buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)gcmNAME_TO_PTR(Interface->u.FreeVirtualCommandBuffer.physical);
2451
2452 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
2453 Kernel,
2454 processID,
2455 gcvDB_COMMAND_BUFFER,
2456 gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
2457
2458 gcmkONERROR(gckOS_DestroyUserVirtualMapping(
2459 Kernel->os,
2460 buffer->physical,
2461 (gctSIZE_T)Interface->u.FreeVirtualCommandBuffer.bytes,
2462 gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
2463
2464 gcmkONERROR(gckKERNEL_DestroyVirtualCommandBuffer(
2465 Kernel,
2466 (gctSIZE_T)Interface->u.FreeVirtualCommandBuffer.bytes,
2467 (gctPHYS_ADDR)buffer,
2468 gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
2469
2470 gcmRELEASE_NAME(Interface->u.FreeVirtualCommandBuffer.physical);
2471 break;
2472
2473#if gcdANDROID_NATIVE_FENCE_SYNC
2474 case gcvHAL_SYNC_POINT:
2475 {
2476 gctSYNC_POINT syncPoint;
2477
2478 switch (Interface->u.SyncPoint.command)
2479 {
2480 case gcvSYNC_POINT_CREATE:
2481 gcmkONERROR(gckOS_CreateSyncPoint(Kernel->os, &syncPoint));
2482
2483 Interface->u.SyncPoint.syncPoint = gcmPTR_TO_UINT64(syncPoint);
2484
2485 gcmkVERIFY_OK(
2486 gckKERNEL_AddProcessDB(Kernel,
2487 processID, gcvDB_SYNC_POINT,
2488 syncPoint,
2489 gcvNULL,
2490 0));
2491 break;
2492
2493 case gcvSYNC_POINT_DESTROY:
2494 syncPoint = gcmUINT64_TO_PTR(Interface->u.SyncPoint.syncPoint);
2495
2496 gcmkONERROR(gckOS_DestroySyncPoint(Kernel->os, syncPoint));
2497
2498 gcmkVERIFY_OK(
2499 gckKERNEL_RemoveProcessDB(Kernel,
2500 processID, gcvDB_SYNC_POINT,
2501 syncPoint));
2502 break;
2503
2504 default:
2505 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
2506 break;
2507 }
2508 }
2509 break;
2510
2511 case gcvHAL_CREATE_NATIVE_FENCE:
2512 {
2513 gctINT fenceFD;
2514 gctSYNC_POINT syncPoint =
2515 gcmUINT64_TO_PTR(Interface->u.CreateNativeFence.syncPoint);
2516
2517 gcmkONERROR(
2518 gckOS_CreateNativeFence(Kernel->os,
2519 Kernel->timeline,
2520 syncPoint,
2521 &fenceFD));
2522
2523 Interface->u.CreateNativeFence.fenceFD = fenceFD;
2524 }
2525 break;
2526
2527 case gcvHAL_WAIT_NATIVE_FENCE:
2528 {
2529 gctINT fenceFD;
2530 gctUINT32 timeout;
2531
2532 fenceFD = Interface->u.WaitNativeFence.fenceFD;
2533 timeout = Interface->u.WaitNativeFence.timeout;
2534
2535 gcmkONERROR(
2536 gckOS_WaitNativeFence(Kernel->os,
2537 Kernel->timeline,
2538 fenceFD,
2539 timeout));
2540 }
2541 break;
2542#endif
2543
2544 case gcvHAL_SHBUF:
2545 {
2546 gctSHBUF shBuf;
2547 gctPOINTER uData;
2548 gctUINT32 bytes;
2549
2550 switch (Interface->u.ShBuf.command)
2551 {
2552 case gcvSHBUF_CREATE:
2553 bytes = Interface->u.ShBuf.bytes;
2554
2555 /* Create. */
2556 gcmkONERROR(gckKERNEL_CreateShBuffer(Kernel, bytes, &shBuf));
2557
2558 Interface->u.ShBuf.id = gcmPTR_TO_UINT64(shBuf);
2559
2560 gcmkVERIFY_OK(
2561 gckKERNEL_AddProcessDB(Kernel,
2562 processID,
2563 gcvDB_SHBUF,
2564 shBuf,
2565 gcvNULL,
2566 0));
2567 break;
2568
2569 case gcvSHBUF_DESTROY:
2570 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
2571
2572 /* Check db first to avoid illegal destroy in the process. */
2573 gcmkONERROR(
2574 gckKERNEL_RemoveProcessDB(Kernel,
2575 processID,
2576 gcvDB_SHBUF,
2577 shBuf));
2578
2579 gcmkONERROR(gckKERNEL_DestroyShBuffer(Kernel, shBuf));
2580 break;
2581
2582 case gcvSHBUF_MAP:
2583 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
2584
2585 /* Map for current process access. */
2586 gcmkONERROR(gckKERNEL_MapShBuffer(Kernel, shBuf));
2587
2588 gcmkVERIFY_OK(
2589 gckKERNEL_AddProcessDB(Kernel,
2590 processID,
2591 gcvDB_SHBUF,
2592 shBuf,
2593 gcvNULL,
2594 0));
2595 break;
2596
2597 case gcvSHBUF_WRITE:
2598 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
2599 uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
2600 bytes = Interface->u.ShBuf.bytes;
2601
2602 /* Write. */
2603 gcmkONERROR(
2604 gckKERNEL_WriteShBuffer(Kernel, shBuf, uData, bytes));
2605 break;
2606
2607 case gcvSHBUF_READ:
2608 shBuf = gcmUINT64_TO_PTR(Interface->u.ShBuf.id);
2609 uData = gcmUINT64_TO_PTR(Interface->u.ShBuf.data);
2610 bytes = Interface->u.ShBuf.bytes;
2611
2612 /* Read. */
2613 gcmkONERROR(
2614 gckKERNEL_ReadShBuffer(Kernel,
2615 shBuf,
2616 uData,
2617 bytes,
2618 &bytes));
2619
2620 /* Return copied size. */
2621 Interface->u.ShBuf.bytes = bytes;
2622 break;
2623
2624 default:
2625 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
2626 break;
2627 }
2628 }
2629 break;
2630
2631 case gcvHAL_CONFIG_POWER_MANAGEMENT:
2632 gcmkONERROR(gckKERNEL_ConfigPowerManagement(Kernel, Interface));
2633 break;
2634
2635 case gcvHAL_WRAP_USER_MEMORY:
2636 gcmkONERROR(gckKERNEL_WrapUserMemory(
2637 Kernel,
2638 processID,
2639 &Interface->u.WrapUserMemory.desc,
2640 &Interface->u.WrapUserMemory.node
2641 ));
2642 break;
2643
2644#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
2645 case gcvHAL_DEC300_READ:
2646 gcmkONERROR(viv_dec300_read(
2647 Interface->u.DEC300Read.enable,
2648 Interface->u.DEC300Read.readId,
2649 Interface->u.DEC300Read.format,
2650 Interface->u.DEC300Read.strides,
2651 Interface->u.DEC300Read.is3D,
2652 Interface->u.DEC300Read.isMSAA,
2653 Interface->u.DEC300Read.clearValue,
2654 Interface->u.DEC300Read.isTPC,
2655 Interface->u.DEC300Read.isTPCCompressed,
2656 Interface->u.DEC300Read.surfAddrs,
2657 Interface->u.DEC300Read.tileAddrs
2658 ));
2659 break;
2660
2661 case gcvHAL_DEC300_WRITE:
2662 gcmkONERROR(viv_dec300_write(
2663 Interface->u.DEC300Write.enable,
2664 Interface->u.DEC300Write.readId,
2665 Interface->u.DEC300Write.writeId,
2666 Interface->u.DEC300Write.format,
2667 Interface->u.DEC300Write.surfAddr,
2668 Interface->u.DEC300Write.tileAddr
2669 ));
2670 break;
2671
2672 case gcvHAL_DEC300_FLUSH:
2673 gcmkONERROR(viv_dec300_flush(0));
2674 break;
2675
2676 case gcvHAL_DEC300_FLUSH_WAIT:
2677 gcmkONERROR(viv_dec300_flush_done(&Interface->u.DEC300FlushWait.done));
2678 break;
2679#endif
2680
2681 default:
2682 /* Invalid command. */
2683 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
2684 }
2685
2686OnError:
2687 /* Save status. */
2688 Interface->status = status;
2689
2690#if QNX_SINGLE_THREADED_DEBUGGING
2691 gckOS_ReleaseMutex(Kernel->os, Kernel->debugMutex);
2692#endif
2693
2694 if (powerMutexAcquired == gcvTRUE)
2695 {
2696 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->hardware->powerMutex));
2697 }
2698
2699 /* Return the status. */
2700 gcmkFOOTER();
2701 return status;
2702}
2703
2704/*******************************************************************************
2705** gckKERNEL_AttachProcess
2706**
2707** Attach or detach a process.
2708**
2709** INPUT:
2710**
2711** gckKERNEL Kernel
2712** Pointer to an gckKERNEL object.
2713**
2714** gctBOOL Attach
2715** gcvTRUE if a new process gets attached or gcFALSE when a process
2716** gets detatched.
2717**
2718** OUTPUT:
2719**
2720** Nothing.
2721*/
2722gceSTATUS
2723gckKERNEL_AttachProcess(
2724 IN gckKERNEL Kernel,
2725 IN gctBOOL Attach
2726 )
2727{
2728 gceSTATUS status;
2729 gctUINT32 processID;
2730
2731 gcmkHEADER_ARG("Kernel=0x%x Attach=%d", Kernel, Attach);
2732
2733 /* Verify the arguments. */
2734 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
2735
2736 /* Get current process ID. */
2737 gcmkONERROR(gckOS_GetProcessID(&processID));
2738
2739 gcmkONERROR(gckKERNEL_AttachProcessEx(Kernel, Attach, processID));
2740
2741 /* Success. */
2742 gcmkFOOTER_NO();
2743 return gcvSTATUS_OK;
2744
2745OnError:
2746 /* Return the status. */
2747 gcmkFOOTER();
2748 return status;
2749}
2750
2751/*******************************************************************************
2752** gckKERNEL_AttachProcessEx
2753**
2754** Attach or detach a process with the given PID. Can be paired with gckKERNEL_AttachProcess
2755** provided the programmer is aware of the consequences.
2756**
2757** INPUT:
2758**
2759** gckKERNEL Kernel
2760** Pointer to an gckKERNEL object.
2761**
2762** gctBOOL Attach
2763** gcvTRUE if a new process gets attached or gcFALSE when a process
2764** gets detatched.
2765**
2766** gctUINT32 PID
2767** PID of the process to attach or detach.
2768**
2769** OUTPUT:
2770**
2771** Nothing.
2772*/
2773gceSTATUS
2774gckKERNEL_AttachProcessEx(
2775 IN gckKERNEL Kernel,
2776 IN gctBOOL Attach,
2777 IN gctUINT32 PID
2778 )
2779{
2780 gceSTATUS status;
2781 gctINT32 old;
2782
2783 gcmkHEADER_ARG("Kernel=0x%x Attach=%d PID=%d", Kernel, Attach, PID);
2784
2785 /* Verify the arguments. */
2786 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
2787
2788 if (Attach)
2789 {
2790 /* Increment the number of clients attached. */
2791 gcmkONERROR(
2792 gckOS_AtomIncrement(Kernel->os, Kernel->atomClients, &old));
2793
2794 if (old == 0)
2795 {
2796 {
2797 gcmkONERROR(gckOS_Broadcast(Kernel->os,
2798 Kernel->hardware,
2799 gcvBROADCAST_FIRST_PROCESS));
2800 }
2801 }
2802
2803 if (Kernel->dbCreated)
2804 {
2805 /* Create the process database. */
2806 gcmkONERROR(gckKERNEL_CreateProcessDB(Kernel, PID));
2807 }
2808
2809#if gcdPROCESS_ADDRESS_SPACE
2810 /* Map kernel command buffer in the process's own MMU. */
2811 gcmkONERROR(_MapCommandBuffer(Kernel));
2812#endif
2813 }
2814 else
2815 {
2816 if (Kernel->dbCreated)
2817 {
2818 /* Clean up the process database. */
2819 gcmkONERROR(gckKERNEL_DestroyProcessDB(Kernel, PID));
2820
2821 /* Save the last know process ID. */
2822 Kernel->db->lastProcessID = PID;
2823 }
2824
2825 {
2826 status = gckEVENT_Submit(Kernel->eventObj, gcvTRUE, gcvFALSE);
2827
2828 if (status == gcvSTATUS_INTERRUPTED && Kernel->eventObj->submitTimer)
2829 {
2830 gcmkONERROR(gckOS_StartTimer(Kernel->os,
2831 Kernel->eventObj->submitTimer,
2832 1));
2833 }
2834 else
2835 {
2836 gcmkONERROR(status);
2837 }
2838 }
2839
2840 /* Decrement the number of clients attached. */
2841 gcmkONERROR(
2842 gckOS_AtomDecrement(Kernel->os, Kernel->atomClients, &old));
2843
2844 if (old == 1)
2845 {
2846 {
2847 /* Last client detached, switch to SUSPEND power state. */
2848 gcmkONERROR(gckOS_Broadcast(Kernel->os,
2849 Kernel->hardware,
2850 gcvBROADCAST_LAST_PROCESS));
2851 }
2852
2853 /* Flush the debug cache. */
2854 gcmkDEBUGFLUSH(~0U);
2855 }
2856 }
2857
2858 /* Success. */
2859 gcmkFOOTER_NO();
2860 return gcvSTATUS_OK;
2861
2862OnError:
2863 /* Return the status. */
2864 gcmkFOOTER();
2865 return status;
2866}
2867
2868#if gcdSECURE_USER
2869gceSTATUS
2870gckKERNEL_MapLogicalToPhysical(
2871 IN gckKERNEL Kernel,
2872 IN gcskSECURE_CACHE_PTR Cache,
2873 IN OUT gctPOINTER * Data
2874 )
2875{
2876 gceSTATUS status;
2877 static gctBOOL baseAddressValid = gcvFALSE;
2878 static gctUINT32 baseAddress;
2879 gctBOOL needBase;
2880 gcskLOGICAL_CACHE_PTR slot;
2881
2882 gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x *Data=0x%x",
2883 Kernel, Cache, gcmOPT_POINTER(Data));
2884
2885 /* Verify the arguments. */
2886 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
2887
2888 if (!baseAddressValid)
2889 {
2890 /* Get base address. */
2891 gcmkONERROR(gckHARDWARE_GetBaseAddress(Kernel->hardware, &baseAddress));
2892
2893 baseAddressValid = gcvTRUE;
2894 }
2895
2896 /* Does this state load need a base address? */
2897 gcmkONERROR(gckHARDWARE_NeedBaseAddress(Kernel->hardware,
2898 ((gctUINT32_PTR) Data)[-1],
2899 &needBase));
2900
2901#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
2902 {
2903 gcskLOGICAL_CACHE_PTR next;
2904 gctINT i;
2905
2906 /* Walk all used cache slots. */
2907 for (i = 1, slot = Cache->cache[0].next, next = gcvNULL;
2908 (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
2909 ++i, slot = slot->next
2910 )
2911 {
2912 if (slot->logical == *Data)
2913 {
2914 /* Bail out. */
2915 next = slot;
2916 break;
2917 }
2918 }
2919
2920 /* See if we had a miss. */
2921 if (next == gcvNULL)
2922 {
2923 /* Use the tail of the cache. */
2924 slot = Cache->cache[0].prev;
2925
2926 /* Initialize the cache line. */
2927 slot->logical = *Data;
2928
2929 /* Map the logical address to a DMA address. */
2930 gcmkONERROR(
2931 gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
2932 }
2933
2934 /* Move slot to head of list. */
2935 if (slot != Cache->cache[0].next)
2936 {
2937 /* Unlink. */
2938 slot->prev->next = slot->next;
2939 slot->next->prev = slot->prev;
2940
2941 /* Move to head of chain. */
2942 slot->prev = &Cache->cache[0];
2943 slot->next = Cache->cache[0].next;
2944 slot->prev->next = slot;
2945 slot->next->prev = slot;
2946 }
2947 }
2948#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
2949 {
2950 gctINT i;
2951 gcskLOGICAL_CACHE_PTR next = gcvNULL;
2952 gcskLOGICAL_CACHE_PTR oldestSlot = gcvNULL;
2953 slot = gcvNULL;
2954
2955 if (Cache->cacheIndex != gcvNULL)
2956 {
2957 /* Walk the cache forwards. */
2958 for (i = 1, slot = Cache->cacheIndex;
2959 (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
2960 ++i, slot = slot->next)
2961 {
2962 if (slot->logical == *Data)
2963 {
2964 /* Bail out. */
2965 next = slot;
2966 break;
2967 }
2968
2969 /* Determine age of this slot. */
2970 if ((oldestSlot == gcvNULL)
2971 || (oldestSlot->stamp > slot->stamp)
2972 )
2973 {
2974 oldestSlot = slot;
2975 }
2976 }
2977
2978 if (next == gcvNULL)
2979 {
2980 /* Walk the cache backwards. */
2981 for (slot = Cache->cacheIndex->prev;
2982 (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
2983 ++i, slot = slot->prev)
2984 {
2985 if (slot->logical == *Data)
2986 {
2987 /* Bail out. */
2988 next = slot;
2989 break;
2990 }
2991
2992 /* Determine age of this slot. */
2993 if ((oldestSlot == gcvNULL)
2994 || (oldestSlot->stamp > slot->stamp)
2995 )
2996 {
2997 oldestSlot = slot;
2998 }
2999 }
3000 }
3001 }
3002
3003 /* See if we had a miss. */
3004 if (next == gcvNULL)
3005 {
3006 if (Cache->cacheFree != 0)
3007 {
3008 slot = &Cache->cache[Cache->cacheFree];
3009 gcmkASSERT(slot->logical == gcvNULL);
3010
3011 ++ Cache->cacheFree;
3012 if (Cache->cacheFree >= gcmCOUNTOF(Cache->cache))
3013 {
3014 Cache->cacheFree = 0;
3015 }
3016 }
3017 else
3018 {
3019 /* Use the oldest cache slot. */
3020 gcmkASSERT(oldestSlot != gcvNULL);
3021 slot = oldestSlot;
3022
3023 /* Unlink from the chain. */
3024 slot->prev->next = slot->next;
3025 slot->next->prev = slot->prev;
3026
3027 /* Append to the end. */
3028 slot->prev = Cache->cache[0].prev;
3029 slot->next = &Cache->cache[0];
3030 slot->prev->next = slot;
3031 slot->next->prev = slot;
3032 }
3033
3034 /* Initialize the cache line. */
3035 slot->logical = *Data;
3036
3037 /* Map the logical address to a DMA address. */
3038 gcmkONERROR(
3039 gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
3040 }
3041
3042 /* Save time stamp. */
3043 slot->stamp = ++ Cache->cacheStamp;
3044
3045 /* Save current slot for next lookup. */
3046 Cache->cacheIndex = slot;
3047 }
3048#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
3049 {
3050 gctINT i;
3051 gctUINT32 data = gcmPTR2INT32(*Data);
3052 gctUINT32 key, index;
3053 gcskLOGICAL_CACHE_PTR hash;
3054
3055 /* Generate a hash key. */
3056 key = (data >> 24) + (data >> 16) + (data >> 8) + data;
3057 index = key % gcmCOUNTOF(Cache->hash);
3058
3059 /* Get the hash entry. */
3060 hash = &Cache->hash[index];
3061
3062 for (slot = hash->nextHash, i = 0;
3063 (slot != gcvNULL) && (i < gcdSECURE_CACHE_SLOTS);
3064 slot = slot->nextHash, ++i
3065 )
3066 {
3067 if (slot->logical == (*Data))
3068 {
3069 break;
3070 }
3071 }
3072
3073 if (slot == gcvNULL)
3074 {
3075 /* Grab from the tail of the cache. */
3076 slot = Cache->cache[0].prev;
3077
3078 /* Unlink slot from any hash table it is part of. */
3079 if (slot->prevHash != gcvNULL)
3080 {
3081 slot->prevHash->nextHash = slot->nextHash;
3082 }
3083 if (slot->nextHash != gcvNULL)
3084 {
3085 slot->nextHash->prevHash = slot->prevHash;
3086 }
3087
3088 /* Initialize the cache line. */
3089 slot->logical = *Data;
3090
3091 /* Map the logical address to a DMA address. */
3092 gcmkONERROR(
3093 gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
3094
3095 if (hash->nextHash != gcvNULL)
3096 {
3097 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
3098 "Hash Collision: logical=0x%x key=0x%08x",
3099 *Data, key);
3100 }
3101
3102 /* Insert the slot at the head of the hash list. */
3103 slot->nextHash = hash->nextHash;
3104 if (slot->nextHash != gcvNULL)
3105 {
3106 slot->nextHash->prevHash = slot;
3107 }
3108 slot->prevHash = hash;
3109 hash->nextHash = slot;
3110 }
3111
3112 /* Move slot to head of list. */
3113 if (slot != Cache->cache[0].next)
3114 {
3115 /* Unlink. */
3116 slot->prev->next = slot->next;
3117 slot->next->prev = slot->prev;
3118
3119 /* Move to head of chain. */
3120 slot->prev = &Cache->cache[0];
3121 slot->next = Cache->cache[0].next;
3122 slot->prev->next = slot;
3123 slot->next->prev = slot;
3124 }
3125 }
3126#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
3127 {
3128 gctUINT32 index = (gcmPTR2INT32(*Data) % gcdSECURE_CACHE_SLOTS) + 1;
3129
3130 /* Get cache slot. */
3131 slot = &Cache->cache[index];
3132
3133 /* Check for cache miss. */
3134 if (slot->logical != *Data)
3135 {
3136 /* Initialize the cache line. */
3137 slot->logical = *Data;
3138
3139 /* Map the logical address to a DMA address. */
3140 gcmkONERROR(
3141 gckOS_GetPhysicalAddress(Kernel->os, *Data, &slot->dma));
3142 }
3143 }
3144#endif
3145
3146 /* Return DMA address. */
3147 *Data = gcmINT2PTR(slot->dma + (needBase ? baseAddress : 0));
3148
3149 /* Success. */
3150 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
3151 return gcvSTATUS_OK;
3152
3153OnError:
3154 /* Return the status. */
3155 gcmkFOOTER();
3156 return status;
3157}
3158
3159gceSTATUS
3160gckKERNEL_FlushTranslationCache(
3161 IN gckKERNEL Kernel,
3162 IN gcskSECURE_CACHE_PTR Cache,
3163 IN gctPOINTER Logical,
3164 IN gctSIZE_T Bytes
3165 )
3166{
3167 gctINT i;
3168 gcskLOGICAL_CACHE_PTR slot;
3169 gctUINT8_PTR ptr;
3170
3171 gcmkHEADER_ARG("Kernel=0x%x Cache=0x%x Logical=0x%x Bytes=%lu",
3172 Kernel, Cache, Logical, Bytes);
3173
3174 /* Do we need to flush the entire cache? */
3175 if (Logical == gcvNULL)
3176 {
3177 /* Clear all cache slots. */
3178 for (i = 1; i <= gcdSECURE_CACHE_SLOTS; ++i)
3179 {
3180 Cache->cache[i].logical = gcvNULL;
3181
3182#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
3183 Cache->cache[i].nextHash = gcvNULL;
3184 Cache->cache[i].prevHash = gcvNULL;
3185#endif
3186}
3187
3188#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
3189 /* Zero the hash table. */
3190 for (i = 0; i < gcmCOUNTOF(Cache->hash); ++i)
3191 {
3192 Cache->hash[i].nextHash = gcvNULL;
3193 }
3194#endif
3195
3196 /* Reset the cache functionality. */
3197 Cache->cacheIndex = gcvNULL;
3198 Cache->cacheFree = 1;
3199 Cache->cacheStamp = 0;
3200 }
3201
3202 else
3203 {
3204 gctUINT8_PTR low = (gctUINT8_PTR) Logical;
3205 gctUINT8_PTR high = low + Bytes;
3206
3207#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LRU
3208 gcskLOGICAL_CACHE_PTR next;
3209
3210 /* Walk all used cache slots. */
3211 for (i = 1, slot = Cache->cache[0].next;
3212 (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
3213 ++i, slot = next
3214 )
3215 {
3216 /* Save pointer to next slot. */
3217 next = slot->next;
3218
3219 /* Test if this slot falls within the range to flush. */
3220 ptr = (gctUINT8_PTR) slot->logical;
3221 if ((ptr >= low) && (ptr < high))
3222 {
3223 /* Unlink slot. */
3224 slot->prev->next = slot->next;
3225 slot->next->prev = slot->prev;
3226
3227 /* Append slot to tail of cache. */
3228 slot->prev = Cache->cache[0].prev;
3229 slot->next = &Cache->cache[0];
3230 slot->prev->next = slot;
3231 slot->next->prev = slot;
3232
3233 /* Mark slot as empty. */
3234 slot->logical = gcvNULL;
3235 }
3236 }
3237
3238#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
3239 gcskLOGICAL_CACHE_PTR next;
3240
3241 for (i = 1, slot = Cache->cache[0].next;
3242 (i <= gcdSECURE_CACHE_SLOTS) && (slot->logical != gcvNULL);
3243 ++i, slot = next)
3244 {
3245 /* Save pointer to next slot. */
3246 next = slot->next;
3247
3248 /* Test if this slot falls within the range to flush. */
3249 ptr = (gctUINT8_PTR) slot->logical;
3250 if ((ptr >= low) && (ptr < high))
3251 {
3252 /* Test if this slot is the current slot. */
3253 if (slot == Cache->cacheIndex)
3254 {
3255 /* Move to next or previous slot. */
3256 Cache->cacheIndex = (slot->next->logical != gcvNULL)
3257 ? slot->next
3258 : (slot->prev->logical != gcvNULL)
3259 ? slot->prev
3260 : gcvNULL;
3261 }
3262
3263 /* Unlink slot from cache. */
3264 slot->prev->next = slot->next;
3265 slot->next->prev = slot->prev;
3266
3267 /* Insert slot to head of cache. */
3268 slot->prev = &Cache->cache[0];
3269 slot->next = Cache->cache[0].next;
3270 slot->prev->next = slot;
3271 slot->next->prev = slot;
3272
3273 /* Mark slot as empty. */
3274 slot->logical = gcvNULL;
3275 slot->stamp = 0;
3276 }
3277 }
3278
3279#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
3280 gctINT j;
3281 gcskLOGICAL_CACHE_PTR hash, next;
3282
3283 /* Walk all hash tables. */
3284 for (i = 0, hash = Cache->hash;
3285 i < gcmCOUNTOF(Cache->hash);
3286 ++i, ++hash)
3287 {
3288 /* Walk all slots in the hash. */
3289 for (j = 0, slot = hash->nextHash;
3290 (j < gcdSECURE_CACHE_SLOTS) && (slot != gcvNULL);
3291 ++j, slot = next)
3292 {
3293 /* Save pointer to next slot. */
3294 next = slot->next;
3295
3296 /* Test if this slot falls within the range to flush. */
3297 ptr = (gctUINT8_PTR) slot->logical;
3298 if ((ptr >= low) && (ptr < high))
3299 {
3300 /* Unlink slot from hash table. */
3301 if (slot->prevHash == hash)
3302 {
3303 hash->nextHash = slot->nextHash;
3304 }
3305 else
3306 {
3307 slot->prevHash->nextHash = slot->nextHash;
3308 }
3309
3310 if (slot->nextHash != gcvNULL)
3311 {
3312 slot->nextHash->prevHash = slot->prevHash;
3313 }
3314
3315 /* Unlink slot from cache. */
3316 slot->prev->next = slot->next;
3317 slot->next->prev = slot->prev;
3318
3319 /* Append slot to tail of cache. */
3320 slot->prev = Cache->cache[0].prev;
3321 slot->next = &Cache->cache[0];
3322 slot->prev->next = slot;
3323 slot->next->prev = slot;
3324
3325 /* Mark slot as empty. */
3326 slot->logical = gcvNULL;
3327 slot->prevHash = gcvNULL;
3328 slot->nextHash = gcvNULL;
3329 }
3330 }
3331 }
3332
3333#elif gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_TABLE
3334 gctUINT32 index;
3335
3336 /* Loop while inside the range. */
3337 for (i = 1; (low < high) && (i <= gcdSECURE_CACHE_SLOTS); ++i)
3338 {
3339 /* Get index into cache for this range. */
3340 index = (gcmPTR2INT32(low) % gcdSECURE_CACHE_SLOTS) + 1;
3341 slot = &Cache->cache[index];
3342
3343 /* Test if this slot falls within the range to flush. */
3344 ptr = (gctUINT8_PTR) slot->logical;
3345 if ((ptr >= low) && (ptr < high))
3346 {
3347 /* Remove entry from cache. */
3348 slot->logical = gcvNULL;
3349 }
3350
3351 /* Next block. */
3352 low += gcdSECURE_CACHE_SLOTS;
3353 }
3354#endif
3355 }
3356
3357 /* Success. */
3358 gcmkFOOTER_NO();
3359 return gcvSTATUS_OK;
3360}
3361#endif
3362
3363/*******************************************************************************
3364**
3365** gckKERNEL_Recovery
3366**
3367** Try to recover the GPU from a fatal error.
3368**
3369** INPUT:
3370**
3371** gckKERNEL Kernel
3372** Pointer to an gckKERNEL object.
3373**
3374** OUTPUT:
3375**
3376** Nothing.
3377*/
3378gceSTATUS
3379gckKERNEL_Recovery(
3380 IN gckKERNEL Kernel
3381 )
3382{
3383 gceSTATUS status;
3384 gckEVENT eventObj;
3385 gckHARDWARE hardware;
3386#if gcdSECURE_USER
3387 gctUINT32 processID;
3388 gcskSECURE_CACHE_PTR cache;
3389#endif
3390 gctUINT32 mask = 0;
3391 gckCOMMAND command;
3392 gckENTRYDATA data;
3393 gctUINT32 i = 0, count = 0;
3394#if gcdINTERRUPT_STATISTIC
3395 gctINT32 oldValue;
3396#endif
3397
3398 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
3399
3400 /* Validate the arguemnts. */
3401 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
3402
3403 /* Grab gckEVENT object. */
3404 eventObj = Kernel->eventObj;
3405 gcmkVERIFY_OBJECT(eventObj, gcvOBJ_EVENT);
3406
3407 /* Grab gckHARDWARE object. */
3408 hardware = Kernel->hardware;
3409 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
3410
3411 /* Grab gckCOMMAND object. */
3412 command = Kernel->command;
3413 gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
3414
3415#if gcdSECURE_USER
3416 /* Flush the secure mapping cache. */
3417 gcmkONERROR(gckOS_GetProcessID(&processID));
3418 gcmkONERROR(gckKERNEL_GetProcessDBCache(Kernel, processID, &cache));
3419 gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel, cache, gcvNULL, 0));
3420#endif
3421
3422 if (Kernel->stuckDump == gcvSTUCK_DUMP_NONE)
3423 {
3424 gcmkPRINT("[galcore]: GPU[%d] hang, automatic recovery.", Kernel->core);
3425 }
3426 else
3427 {
3428 _DumpDriverConfigure(Kernel);
3429 _DumpState(Kernel);
3430 }
3431
3432 if (Kernel->recovery == gcvFALSE)
3433 {
3434 gcmkPRINT("[galcore]: Stop driver to keep scene.");
3435
3436 for (;;)
3437 {
3438 gckOS_Delay(Kernel->os, 10000);
3439 }
3440 }
3441
3442 /* Clear queue. */
3443 do
3444 {
3445 status = gckENTRYQUEUE_Dequeue(&command->queue, &data);
3446 }
3447 while (status == gcvSTATUS_OK);
3448
3449 /* Issuing a soft reset for the GPU. */
3450 gcmkONERROR(gckHARDWARE_Reset(hardware));
3451
3452 mask = Kernel->restoreMask;
3453
3454 for (i = 0; i < 32; i++)
3455 {
3456 if (mask & (1 << i))
3457 {
3458 count++;
3459 }
3460 }
3461
3462 /* Handle all outstanding events now. */
3463#if gcdSMP
3464 gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, mask));
3465#else
3466 eventObj->pending = mask;
3467#endif
3468
3469#if gcdINTERRUPT_STATISTIC
3470 while (count--)
3471 {
3472 gcmkONERROR(gckOS_AtomDecrement(
3473 Kernel->os,
3474 eventObj->interruptCount,
3475 &oldValue
3476 ));
3477 }
3478
3479 gckOS_AtomClearMask(Kernel->hardware->pendingEvent, mask);
3480#endif
3481
3482 gcmkONERROR(gckEVENT_Notify(eventObj, 1));
3483
3484 gcmkVERIFY_OK(gckOS_GetTime(&Kernel->resetTimeStamp));
3485
3486 /* Success. */
3487 gcmkFOOTER_NO();
3488 return gcvSTATUS_OK;
3489
3490OnError:
3491 /* Return the status. */
3492 gcmkFOOTER();
3493 return status;
3494}
3495
3496/*******************************************************************************
3497**
3498** gckKERNEL_OpenUserData
3499**
3500** Get access to the user data.
3501**
3502** INPUT:
3503**
3504** gckKERNEL Kernel
3505** Pointer to an gckKERNEL object.
3506**
3507** gctBOOL NeedCopy
3508** The flag indicating whether or not the data should be copied.
3509**
3510** gctPOINTER StaticStorage
3511** Pointer to the kernel storage where the data is to be copied if
3512** NeedCopy is gcvTRUE.
3513**
3514** gctPOINTER UserPointer
3515** User pointer to the data.
3516**
3517** gctSIZE_T Size
3518** Size of the data.
3519**
3520** OUTPUT:
3521**
3522** gctPOINTER * KernelPointer
3523** Pointer to the kernel pointer that will be pointing to the data.
3524*/
3525gceSTATUS
3526gckKERNEL_OpenUserData(
3527 IN gckKERNEL Kernel,
3528 IN gctBOOL NeedCopy,
3529 IN gctPOINTER StaticStorage,
3530 IN gctPOINTER UserPointer,
3531 IN gctSIZE_T Size,
3532 OUT gctPOINTER * KernelPointer
3533 )
3534{
3535 gceSTATUS status;
3536
3537 gcmkHEADER_ARG(
3538 "Kernel=0x%08X NeedCopy=%d StaticStorage=0x%08X "
3539 "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
3540 Kernel, NeedCopy, StaticStorage, UserPointer, Size, KernelPointer
3541 );
3542
3543 /* Validate the arguemnts. */
3544 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
3545 gcmkVERIFY_ARGUMENT(!NeedCopy || (StaticStorage != gcvNULL));
3546 gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
3547 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
3548 gcmkVERIFY_ARGUMENT(Size > 0);
3549
3550 if (NeedCopy)
3551 {
3552 /* Copy the user data to the static storage. */
3553 gcmkONERROR(gckOS_CopyFromUserData(
3554 Kernel->os, StaticStorage, UserPointer, Size
3555 ));
3556
3557 /* Set the kernel pointer. */
3558 * KernelPointer = StaticStorage;
3559 }
3560 else
3561 {
3562 gctPOINTER pointer = gcvNULL;
3563
3564 /* Map the user pointer. */
3565 gcmkONERROR(gckOS_MapUserPointer(
3566 Kernel->os, UserPointer, Size, &pointer
3567 ));
3568
3569 /* Set the kernel pointer. */
3570 * KernelPointer = pointer;
3571 }
3572
3573OnError:
3574 /* Return the status. */
3575 gcmkFOOTER();
3576 return status;
3577}
3578
3579/*******************************************************************************
3580**
3581** gckKERNEL_CloseUserData
3582**
3583** Release resources associated with the user data connection opened by
3584** gckKERNEL_OpenUserData.
3585**
3586** INPUT:
3587**
3588** gckKERNEL Kernel
3589** Pointer to an gckKERNEL object.
3590**
3591** gctBOOL NeedCopy
3592** The flag indicating whether or not the data should be copied.
3593**
3594** gctBOOL FlushData
3595** If gcvTRUE, the data is written back to the user.
3596**
3597** gctPOINTER UserPointer
3598** User pointer to the data.
3599**
3600** gctSIZE_T Size
3601** Size of the data.
3602**
3603** OUTPUT:
3604**
3605** gctPOINTER * KernelPointer
3606** Kernel pointer to the data.
3607*/
3608gceSTATUS
3609gckKERNEL_CloseUserData(
3610 IN gckKERNEL Kernel,
3611 IN gctBOOL NeedCopy,
3612 IN gctBOOL FlushData,
3613 IN gctPOINTER UserPointer,
3614 IN gctSIZE_T Size,
3615 OUT gctPOINTER * KernelPointer
3616 )
3617{
3618 gceSTATUS status = gcvSTATUS_OK;
3619 gctPOINTER pointer;
3620
3621 gcmkHEADER_ARG(
3622 "Kernel=0x%08X NeedCopy=%d FlushData=%d "
3623 "UserPointer=0x%08X Size=%lu KernelPointer=0x%08X",
3624 Kernel, NeedCopy, FlushData, UserPointer, Size, KernelPointer
3625 );
3626
3627 /* Validate the arguemnts. */
3628 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
3629 gcmkVERIFY_ARGUMENT(UserPointer != gcvNULL);
3630 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
3631 gcmkVERIFY_ARGUMENT(Size > 0);
3632
3633 /* Get a shortcut to the kernel pointer. */
3634 pointer = * KernelPointer;
3635
3636 if (pointer != gcvNULL)
3637 {
3638 if (NeedCopy)
3639 {
3640 if (FlushData)
3641 {
3642 gcmkONERROR(gckOS_CopyToUserData(
3643 Kernel->os, * KernelPointer, UserPointer, Size
3644 ));
3645 }
3646 }
3647 else
3648 {
3649 /* Unmap record from kernel memory. */
3650 gcmkONERROR(gckOS_UnmapUserPointer(
3651 Kernel->os,
3652 UserPointer,
3653 Size,
3654 * KernelPointer
3655 ));
3656 }
3657
3658 /* Reset the kernel pointer. */
3659 * KernelPointer = gcvNULL;
3660 }
3661
3662OnError:
3663 /* Return the status. */
3664 gcmkFOOTER();
3665 return status;
3666}
3667
3668void
3669gckKERNEL_SetTimeOut(
3670 IN gckKERNEL Kernel,
3671 IN gctUINT32 timeOut
3672 )
3673{
3674 gcmkHEADER_ARG("Kernel=0x%x timeOut=%d", Kernel, timeOut);
3675#if gcdGPU_TIMEOUT
3676 Kernel->timeOut = timeOut;
3677#endif
3678 gcmkFOOTER_NO();
3679}
3680
3681gceSTATUS
3682gckKERNEL_AllocateVirtualCommandBuffer(
3683 IN gckKERNEL Kernel,
3684 IN gctBOOL InUserSpace,
3685 IN OUT gctSIZE_T * Bytes,
3686 OUT gctPHYS_ADDR * Physical,
3687 OUT gctPOINTER * Logical
3688 )
3689{
3690 gckOS os = Kernel->os;
3691 gceSTATUS status;
3692 gctPOINTER logical = gcvNULL;
3693 gctSIZE_T pageCount;
3694 gctSIZE_T bytes = *Bytes;
3695 gckVIRTUAL_COMMAND_BUFFER_PTR buffer = gcvNULL;
3696 gckMMU mmu;
3697 gctUINT32 flag = gcvALLOC_FLAG_NON_CONTIGUOUS;
3698
3699 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
3700 os, InUserSpace, gcmOPT_VALUE(Bytes));
3701
3702 /* Verify the arguments. */
3703 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
3704 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
3705 gcmkVERIFY_ARGUMENT(*Bytes > 0);
3706 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3707 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
3708
3709 gcmkONERROR(gckOS_Allocate(os,
3710 sizeof(gckVIRTUAL_COMMAND_BUFFER),
3711 (gctPOINTER)&buffer));
3712
3713 gcmkONERROR(gckOS_ZeroMemory(buffer, sizeof(gckVIRTUAL_COMMAND_BUFFER)));
3714
3715 buffer->bytes = bytes;
3716
3717 gcmkONERROR(gckOS_AllocatePagedMemoryEx(os,
3718 flag,
3719 bytes,
3720 gcvNULL,
3721 &buffer->physical));
3722
3723 if (InUserSpace)
3724 {
3725 gcmkONERROR(gckOS_CreateUserVirtualMapping(os,
3726 buffer->physical,
3727 bytes,
3728 &logical,
3729 &pageCount));
3730
3731 *Logical =
3732 buffer->userLogical = logical;
3733 }
3734 else
3735 {
3736 gcmkONERROR(gckOS_CreateKernelVirtualMapping(os,
3737 buffer->physical,
3738 bytes,
3739 &logical,
3740 &pageCount));
3741
3742 *Logical =
3743 buffer->kernelLogical = logical;
3744 }
3745
3746 buffer->pageCount = pageCount;
3747 buffer->kernel = Kernel;
3748
3749 gcmkONERROR(gckOS_GetProcessID(&buffer->pid));
3750
3751#if gcdPROCESS_ADDRESS_SPACE
3752 gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
3753 buffer->mmu = mmu;
3754#else
3755 mmu = Kernel->mmu;
3756#endif
3757
3758 gcmkONERROR(gckMMU_AllocatePages(mmu,
3759 pageCount,
3760 &buffer->pageTable,
3761 &buffer->gpuAddress));
3762
3763
3764 gcmkONERROR(gckOS_MapPagesEx(os,
3765 Kernel->core,
3766 buffer->physical,
3767 pageCount,
3768 buffer->gpuAddress,
3769 buffer->pageTable));
3770
3771 gcmkONERROR(gckMMU_Flush(mmu, gcvSURF_INDEX));
3772
3773 *Physical = buffer;
3774
3775 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_KERNEL,
3776 "gpuAddress = %x pageCount = %d kernelLogical = %x userLogical=%x",
3777 buffer->gpuAddress, buffer->pageCount,
3778 buffer->kernelLogical, buffer->userLogical);
3779
3780 gcmkVERIFY_OK(gckOS_AcquireMutex(os, Kernel->virtualBufferLock, gcvINFINITE));
3781
3782 if (Kernel->virtualBufferHead == gcvNULL)
3783 {
3784 Kernel->virtualBufferHead =
3785 Kernel->virtualBufferTail = buffer;
3786 }
3787 else
3788 {
3789 buffer->prev = Kernel->virtualBufferTail;
3790 Kernel->virtualBufferTail->next = buffer;
3791 Kernel->virtualBufferTail = buffer;
3792 }
3793
3794 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Kernel->virtualBufferLock));
3795
3796 gcmkFOOTER_NO();
3797 return gcvSTATUS_OK;
3798
3799OnError:
3800 if (buffer->gpuAddress)
3801 {
3802#if gcdPROCESS_ADDRESS_SPACE
3803 gcmkVERIFY_OK(
3804 gckMMU_FreePages(mmu, buffer->pageTable, buffer->pageCount));
3805#else
3806 gcmkVERIFY_OK(
3807 gckMMU_FreePages(Kernel->mmu, buffer->pageTable, buffer->pageCount));
3808#endif
3809 }
3810
3811 if (buffer->userLogical)
3812 {
3813 gcmkVERIFY_OK(
3814 gckOS_DestroyUserVirtualMapping(os,
3815 buffer->physical,
3816 bytes,
3817 buffer->userLogical));
3818 }
3819
3820 if (buffer->kernelLogical)
3821 {
3822 gcmkVERIFY_OK(
3823 gckOS_DestroyKernelVirtualMapping(os,
3824 buffer->physical,
3825 bytes,
3826 buffer->kernelLogical));
3827 }
3828
3829 if (buffer->physical)
3830 {
3831 gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, bytes));
3832 }
3833
3834 gcmkVERIFY_OK(gckOS_Free(os, buffer));
3835
3836 /* Return the status. */
3837 gcmkFOOTER();
3838 return status;
3839}
3840
3841gceSTATUS
3842gckKERNEL_DestroyVirtualCommandBuffer(
3843 IN gckKERNEL Kernel,
3844 IN gctSIZE_T Bytes,
3845 IN gctPHYS_ADDR Physical,
3846 IN gctPOINTER Logical
3847 )
3848{
3849 gckOS os;
3850 gckKERNEL kernel;
3851 gckVIRTUAL_COMMAND_BUFFER_PTR buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)Physical;
3852
3853 gcmkHEADER();
3854 gcmkVERIFY_ARGUMENT(buffer != gcvNULL);
3855
3856 kernel = buffer->kernel;
3857 os = kernel->os;
3858
3859 if (!buffer->userLogical)
3860 {
3861 gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(os,
3862 buffer->physical,
3863 Bytes,
3864 Logical));
3865 }
3866
3867#if !gcdPROCESS_ADDRESS_SPACE
3868 gcmkVERIFY_OK(
3869 gckMMU_FreePages(kernel->mmu, buffer->pageTable, buffer->pageCount));
3870#endif
3871
3872 gcmkVERIFY_OK(gckOS_UnmapPages(os, buffer->pageCount, buffer->gpuAddress));
3873
3874 gcmkVERIFY_OK(gckOS_FreePagedMemory(os, buffer->physical, Bytes));
3875
3876 gcmkVERIFY_OK(gckOS_AcquireMutex(os, kernel->virtualBufferLock, gcvINFINITE));
3877
3878 if (buffer == kernel->virtualBufferHead)
3879 {
3880 if ((kernel->virtualBufferHead = buffer->next) == gcvNULL)
3881 {
3882 kernel->virtualBufferTail = gcvNULL;
3883 }
3884 }
3885 else
3886 {
3887 buffer->prev->next = buffer->next;
3888
3889 if (buffer == kernel->virtualBufferTail)
3890 {
3891 kernel->virtualBufferTail = buffer->prev;
3892 }
3893 else
3894 {
3895 buffer->next->prev = buffer->prev;
3896 }
3897 }
3898
3899 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, kernel->virtualBufferLock));
3900
3901 gcmkVERIFY_OK(gckOS_Free(os, buffer));
3902
3903 gcmkFOOTER_NO();
3904 return gcvSTATUS_OK;
3905}
3906
3907gceSTATUS
3908gckKERNEL_GetGPUAddress(
3909 IN gckKERNEL Kernel,
3910 IN gctPOINTER Logical,
3911 IN gctBOOL InUserSpace,
3912 IN gckVIRTUAL_COMMAND_BUFFER_PTR Buffer,
3913 OUT gctUINT32 * Address
3914 )
3915{
3916 gckVIRTUAL_COMMAND_BUFFER_PTR buffer = Buffer;
3917 gctPOINTER start;
3918
3919 gcmkHEADER_ARG("Logical = %x InUserSpace=%d.", Logical, InUserSpace);
3920
3921 if (InUserSpace)
3922 {
3923 start = buffer->userLogical;
3924 }
3925 else
3926 {
3927 start = buffer->kernelLogical;
3928 }
3929
3930 gcmkASSERT(Logical >= start
3931 && (Logical < (gctPOINTER)((gctUINT8_PTR)start + buffer->pageCount * 4096)));
3932
3933 * Address = buffer->gpuAddress + (gctUINT32)((gctUINT8_PTR)Logical - (gctUINT8_PTR)start);
3934
3935 gcmkFOOTER_NO();
3936 return gcvSTATUS_OK;
3937}
3938
3939gceSTATUS
3940gckKERNEL_QueryGPUAddress(
3941 IN gckKERNEL Kernel,
3942 IN gctUINT32 GpuAddress,
3943 OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
3944 )
3945{
3946 gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
3947 gctUINT32 start;
3948 gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
3949
3950 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, Kernel->virtualBufferLock, gcvINFINITE));
3951
3952 /* Walk all command buffers. */
3953 for (buffer = Kernel->virtualBufferHead; buffer != gcvNULL; buffer = buffer->next)
3954 {
3955 start = (gctUINT32)buffer->gpuAddress;
3956
3957 if (GpuAddress >= start && GpuAddress < (start + buffer->pageCount * 4096))
3958 {
3959 /* Find a range matched. */
3960 *Buffer = buffer;
3961 status = gcvSTATUS_OK;
3962 break;
3963 }
3964 }
3965
3966 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->virtualBufferLock));
3967
3968 return status;
3969}
3970
3971#if gcdLINK_QUEUE_SIZE
3972static void
3973gckLINKQUEUE_Dequeue(
3974 IN gckLINKQUEUE LinkQueue
3975 )
3976{
3977 gcmkASSERT(LinkQueue->count == gcdLINK_QUEUE_SIZE);
3978
3979 LinkQueue->count--;
3980 LinkQueue->front = (LinkQueue->front + 1) % gcdLINK_QUEUE_SIZE;
3981}
3982
3983void
3984gckLINKQUEUE_Enqueue(
3985 IN gckLINKQUEUE LinkQueue,
3986 IN gctUINT32 start,
3987 IN gctUINT32 end,
3988 IN gctUINT32 LinkLow,
3989 IN gctUINT32 LinkHigh
3990 )
3991{
3992 if (LinkQueue->count == gcdLINK_QUEUE_SIZE)
3993 {
3994 gckLINKQUEUE_Dequeue(LinkQueue);
3995 }
3996
3997 gcmkASSERT(LinkQueue->count < gcdLINK_QUEUE_SIZE);
3998
3999 LinkQueue->count++;
4000
4001 LinkQueue->data[LinkQueue->rear].start = start;
4002 LinkQueue->data[LinkQueue->rear].end = end;
4003 LinkQueue->data[LinkQueue->rear].linkLow = LinkLow;
4004 LinkQueue->data[LinkQueue->rear].linkHigh = LinkHigh;
4005
4006
4007 gcmkVERIFY_OK(
4008 gckOS_GetProcessID(&LinkQueue->data[LinkQueue->rear].pid));
4009
4010 LinkQueue->rear = (LinkQueue->rear + 1) % gcdLINK_QUEUE_SIZE;
4011}
4012
4013void
4014gckLINKQUEUE_GetData(
4015 IN gckLINKQUEUE LinkQueue,
4016 IN gctUINT32 Index,
4017 OUT gckLINKDATA * Data
4018 )
4019{
4020 gcmkASSERT(Index >= 0 && Index < gcdLINK_QUEUE_SIZE);
4021
4022 *Data = &LinkQueue->data[(Index + LinkQueue->front) % gcdLINK_QUEUE_SIZE];
4023}
4024#endif
4025
4026/*
4027* gckENTRYQUEUE_Enqueue is called with Command->mutexQueue acquired.
4028*/
4029gceSTATUS
4030gckENTRYQUEUE_Enqueue(
4031 IN gckKERNEL Kernel,
4032 IN gckENTRYQUEUE Queue,
4033 IN gctUINT32 physical,
4034 IN gctUINT32 bytes
4035 )
4036{
4037 gctUINT32 next = (Queue->rear + 1) % gcdENTRY_QUEUE_SIZE;
4038
4039 if (next == Queue->front)
4040 {
4041 /* Queue is full. */
4042 return gcvSTATUS_INVALID_REQUEST;
4043 }
4044
4045 /* Copy data. */
4046 Queue->data[Queue->rear].physical = physical;
4047 Queue->data[Queue->rear].bytes = bytes;
4048
4049 gcmkVERIFY_OK(gckOS_MemoryBarrier(Kernel->os, &Queue->rear));
4050
4051 /* Update rear. */
4052 Queue->rear = next;
4053
4054 return gcvSTATUS_OK;
4055}
4056
4057gceSTATUS
4058gckENTRYQUEUE_Dequeue(
4059 IN gckENTRYQUEUE Queue,
4060 OUT gckENTRYDATA * Data
4061 )
4062{
4063 if (Queue->front == Queue->rear)
4064 {
4065 /* Queue is empty. */
4066 return gcvSTATUS_INVALID_REQUEST;
4067 }
4068
4069 /* Copy data. */
4070 *Data = &Queue->data[Queue->front];
4071
4072 /* Update front. */
4073 Queue->front = (Queue->front + 1) % gcdENTRY_QUEUE_SIZE;
4074
4075 return gcvSTATUS_OK;
4076}
4077
4078/******************************************************************************\
4079*************************** Pointer - ID translation ***************************
4080\******************************************************************************/
4081#define gcdID_TABLE_LENGTH 1024
4082typedef struct _gcsINTEGERDB * gckINTEGERDB;
4083typedef struct _gcsINTEGERDB
4084{
4085 gckOS os;
4086 gctPOINTER* table;
4087 gctPOINTER mutex;
4088 gctUINT32 tableLen;
4089 gctUINT32 currentID;
4090 gctUINT32 unused;
4091}
4092gcsINTEGERDB;
4093
4094gceSTATUS
4095gckKERNEL_CreateIntegerDatabase(
4096 IN gckKERNEL Kernel,
4097 OUT gctPOINTER * Database
4098 )
4099{
4100 gceSTATUS status;
4101 gckINTEGERDB database = gcvNULL;
4102
4103 gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
4104
4105 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
4106 gcmkVERIFY_ARGUMENT(Database != gcvNULL);
4107
4108 /* Allocate a database. */
4109 gcmkONERROR(gckOS_Allocate(
4110 Kernel->os, gcmSIZEOF(gcsINTEGERDB), (gctPOINTER *)&database));
4111
4112 gcmkONERROR(gckOS_ZeroMemory(database, gcmSIZEOF(gcsINTEGERDB)));
4113
4114 /* Allocate a pointer table. */
4115 gcmkONERROR(gckOS_Allocate(
4116 Kernel->os, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH, (gctPOINTER *)&database->table));
4117
4118 gcmkONERROR(gckOS_ZeroMemory(database->table, gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH));
4119
4120 /* Allocate a database mutex. */
4121 gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->mutex));
4122
4123 /* Initialize. */
4124 database->currentID = 0;
4125 database->unused = gcdID_TABLE_LENGTH;
4126 database->os = Kernel->os;
4127 database->tableLen = gcdID_TABLE_LENGTH;
4128
4129 *Database = database;
4130
4131 gcmkFOOTER_ARG("*Database=0x%08X", *Database);
4132 return gcvSTATUS_OK;
4133
4134OnError:
4135 /* Rollback. */
4136 if (database)
4137 {
4138 if (database->table)
4139 {
4140 gcmkOS_SAFE_FREE(Kernel->os, database->table);
4141 }
4142
4143 gcmkOS_SAFE_FREE(Kernel->os, database);
4144 }
4145
4146 gcmkFOOTER();
4147 return status;
4148}
4149
4150gceSTATUS
4151gckKERNEL_DestroyIntegerDatabase(
4152 IN gckKERNEL Kernel,
4153 IN gctPOINTER Database
4154 )
4155{
4156 gckINTEGERDB database = Database;
4157
4158 gcmkHEADER_ARG("Kernel=0x%08X Datbase=0x%08X", Kernel, Database);
4159
4160 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
4161 gcmkVERIFY_ARGUMENT(Database != gcvNULL);
4162
4163 /* Destroy pointer table. */
4164 gcmkOS_SAFE_FREE(Kernel->os, database->table);
4165
4166 /* Destroy database mutex. */
4167 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, database->mutex));
4168
4169 /* Destroy database. */
4170 gcmkOS_SAFE_FREE(Kernel->os, database);
4171
4172 gcmkFOOTER_NO();
4173 return gcvSTATUS_OK;
4174}
4175
4176gceSTATUS
4177gckKERNEL_AllocateIntegerId(
4178 IN gctPOINTER Database,
4179 IN gctPOINTER Pointer,
4180 OUT gctUINT32 * Id
4181 )
4182{
4183 gceSTATUS status;
4184 gckINTEGERDB database = Database;
4185 gctUINT32 i, unused, currentID, tableLen;
4186 gctPOINTER * table;
4187 gckOS os = database->os;
4188 gctBOOL acquired = gcvFALSE;
4189
4190 gcmkHEADER_ARG("Database=0x%08X Pointer=0x%08X", Database, Pointer);
4191
4192 gcmkVERIFY_ARGUMENT(Id != gcvNULL);
4193
4194 gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
4195 acquired = gcvTRUE;
4196
4197 if (database->unused < 1)
4198 {
4199 /* Extend table. */
4200 gcmkONERROR(
4201 gckOS_Allocate(os,
4202 gcmSIZEOF(gctPOINTER) * (database->tableLen + gcdID_TABLE_LENGTH),
4203 (gctPOINTER *)&table));
4204
4205 gcmkONERROR(gckOS_ZeroMemory(table + database->tableLen,
4206 gcmSIZEOF(gctPOINTER) * gcdID_TABLE_LENGTH));
4207
4208 /* Copy data from old table. */
4209 gckOS_MemCopy(table,
4210 database->table,
4211 database->tableLen * gcmSIZEOF(gctPOINTER));
4212
4213 gcmkOS_SAFE_FREE(os, database->table);
4214
4215 /* Update databse with new allocated table. */
4216 database->table = table;
4217 database->currentID = database->tableLen;
4218 database->tableLen += gcdID_TABLE_LENGTH;
4219 database->unused += gcdID_TABLE_LENGTH;
4220 }
4221
4222 table = database->table;
4223 currentID = database->currentID;
4224 tableLen = database->tableLen;
4225 unused = database->unused;
4226
4227 /* Connect id with pointer. */
4228 table[currentID] = Pointer;
4229
4230 *Id = currentID + 1;
4231
4232 /* Update the currentID. */
4233 if (--unused > 0)
4234 {
4235 for (i = 0; i < tableLen; i++)
4236 {
4237 if (++currentID >= tableLen)
4238 {
4239 /* Wrap to the begin. */
4240 currentID = 0;
4241 }
4242
4243 if (table[currentID] == gcvNULL)
4244 {
4245 break;
4246 }
4247 }
4248 }
4249
4250 database->table = table;
4251 database->currentID = currentID;
4252 database->tableLen = tableLen;
4253 database->unused = unused;
4254
4255 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
4256 acquired = gcvFALSE;
4257
4258 gcmkFOOTER_ARG("*Id=%d", *Id);
4259 return gcvSTATUS_OK;
4260
4261OnError:
4262 if (acquired)
4263 {
4264 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
4265 }
4266
4267 gcmkFOOTER();
4268 return status;
4269}
4270
4271gceSTATUS
4272gckKERNEL_FreeIntegerId(
4273 IN gctPOINTER Database,
4274 IN gctUINT32 Id
4275 )
4276{
4277 gceSTATUS status;
4278 gckINTEGERDB database = Database;
4279 gckOS os = database->os;
4280 gctBOOL acquired = gcvFALSE;
4281
4282 gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
4283
4284 gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
4285 acquired = gcvTRUE;
4286
4287 if (!(Id > 0 && Id <= database->tableLen))
4288 {
4289 gcmkONERROR(gcvSTATUS_NOT_FOUND);
4290 }
4291
4292 Id -= 1;
4293
4294 database->table[Id] = gcvNULL;
4295
4296 if (database->unused++ == 0)
4297 {
4298 database->currentID = Id;
4299 }
4300
4301 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
4302 acquired = gcvFALSE;
4303
4304 gcmkFOOTER_NO();
4305 return gcvSTATUS_OK;
4306
4307OnError:
4308 if (acquired)
4309 {
4310 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
4311 }
4312
4313 gcmkFOOTER();
4314 return status;
4315}
4316
4317gceSTATUS
4318gckKERNEL_QueryIntegerId(
4319 IN gctPOINTER Database,
4320 IN gctUINT32 Id,
4321 OUT gctPOINTER * Pointer
4322 )
4323{
4324 gceSTATUS status;
4325 gckINTEGERDB database = Database;
4326 gctPOINTER pointer;
4327 gckOS os = database->os;
4328 gctBOOL acquired = gcvFALSE;
4329
4330 gcmkHEADER_ARG("Database=0x%08X Id=%d", Database, Id);
4331 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4332
4333 gcmkVERIFY_OK(gckOS_AcquireMutex(os, database->mutex, gcvINFINITE));
4334 acquired = gcvTRUE;
4335
4336 if (!(Id > 0 && Id <= database->tableLen))
4337 {
4338 gcmkONERROR(gcvSTATUS_NOT_FOUND);
4339 }
4340
4341 Id -= 1;
4342
4343 pointer = database->table[Id];
4344
4345 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
4346 acquired = gcvFALSE;
4347
4348 if (pointer)
4349 {
4350 *Pointer = pointer;
4351 }
4352 else
4353 {
4354 gcmkONERROR(gcvSTATUS_NOT_FOUND);
4355 }
4356
4357 gcmkFOOTER_ARG("*Pointer=0x%08X", *Pointer);
4358 return gcvSTATUS_OK;
4359
4360OnError:
4361 if (acquired)
4362 {
4363 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, database->mutex));
4364 }
4365
4366 gcmkFOOTER();
4367 return status;
4368}
4369
4370
4371gctUINT32
4372gckKERNEL_AllocateNameFromPointer(
4373 IN gckKERNEL Kernel,
4374 IN gctPOINTER Pointer
4375 )
4376{
4377 gceSTATUS status;
4378 gctUINT32 name;
4379 gctPOINTER database = Kernel->db->pointerDatabase;
4380
4381 gcmkHEADER_ARG("Kernel=0x%X Pointer=0x%X", Kernel, Pointer);
4382
4383 gcmkONERROR(
4384 gckKERNEL_AllocateIntegerId(database, Pointer, &name));
4385
4386 gcmkFOOTER_ARG("name=%d", name);
4387 return name;
4388
4389OnError:
4390 gcmkFOOTER();
4391 return 0;
4392}
4393
4394gctPOINTER
4395gckKERNEL_QueryPointerFromName(
4396 IN gckKERNEL Kernel,
4397 IN gctUINT32 Name
4398 )
4399{
4400 gceSTATUS status;
4401 gctPOINTER pointer = gcvNULL;
4402 gctPOINTER database = Kernel->db->pointerDatabase;
4403
4404 gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
4405
4406 /* Lookup in database to get pointer. */
4407 gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, &pointer));
4408
4409 gcmkFOOTER_ARG("pointer=0x%X", pointer);
4410 return pointer;
4411
4412OnError:
4413 gcmkFOOTER();
4414 return gcvNULL;
4415}
4416
4417gceSTATUS
4418gckKERNEL_DeleteName(
4419 IN gckKERNEL Kernel,
4420 IN gctUINT32 Name
4421 )
4422{
4423 gctPOINTER database = Kernel->db->pointerDatabase;
4424
4425 gcmkHEADER_ARG("Kernel=0x%X Name=0x%X", Kernel, Name);
4426
4427 /* Free name if exists. */
4428 gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Name));
4429
4430 gcmkFOOTER_NO();
4431 return gcvSTATUS_OK;
4432}
4433
4434gceSTATUS
4435gckKERNEL_SetRecovery(
4436 IN gckKERNEL Kernel,
4437 IN gctBOOL Recovery,
4438 IN gctUINT32 StuckDump
4439 )
4440{
4441 Kernel->recovery = Recovery;
4442
4443 if (Recovery == gcvFALSE)
4444 {
4445 /* Dump stuck information if Recovery is disabled. */
4446 Kernel->stuckDump = gcmMAX(StuckDump, gcvSTUCK_DUMP_USER_COMMAND);
4447 }
4448
4449 return gcvSTATUS_OK;
4450}
4451
4452/*******************************************************************************
4453***** Shared Buffer ************************************************************
4454*******************************************************************************/
4455
4456/*******************************************************************************
4457**
4458** gckKERNEL_CreateShBuffer
4459**
4460** Create shared buffer.
4461** The shared buffer can be used across processes. Other process needs call
4462** gckKERNEL_MapShBuffer before use it.
4463**
4464** INPUT:
4465**
4466** gckKERNEL Kernel
4467** Pointer to an gckKERNEL object.
4468**
4469** gctUINT32 Size
4470** Specify the shared buffer size.
4471**
4472** OUTPUT:
4473**
4474** gctSHBUF * ShBuf
4475** Pointer to hold return shared buffer handle.
4476*/
4477gceSTATUS
4478gckKERNEL_CreateShBuffer(
4479 IN gckKERNEL Kernel,
4480 IN gctUINT32 Size,
4481 OUT gctSHBUF * ShBuf
4482 )
4483{
4484 gceSTATUS status;
4485 gcsSHBUF_PTR shBuf = gcvNULL;
4486
4487 gcmkHEADER_ARG("Kernel=0x%X, Size=%u", Kernel, Size);
4488
4489 /* Verify the arguments. */
4490 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
4491
4492 if (Size == 0)
4493 {
4494 /* Invalid size. */
4495 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4496 }
4497 else if (Size > 1024)
4498 {
4499 /* Limite shared buffer size. */
4500 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4501 }
4502
4503 /* Create a shared buffer structure. */
4504 gcmkONERROR(
4505 gckOS_Allocate(Kernel->os,
4506 sizeof (gcsSHBUF),
4507 (gctPOINTER *)&shBuf));
4508
4509 /* Initialize shared buffer. */
4510 shBuf->id = 0;
4511 shBuf->reference = gcvNULL;
4512 shBuf->size = Size;
4513 shBuf->data = gcvNULL;
4514
4515 /* Allocate integer id for this shared buffer. */
4516 gcmkONERROR(
4517 gckKERNEL_AllocateIntegerId(Kernel->db->pointerDatabase,
4518 shBuf,
4519 &shBuf->id));
4520
4521 /* Allocate atom. */
4522 gcmkONERROR(gckOS_AtomConstruct(Kernel->os, &shBuf->reference));
4523
4524 /* Set default reference count to 1. */
4525 gcmkVERIFY_OK(gckOS_AtomSet(Kernel->os, shBuf->reference, 1));
4526
4527 /* Return integer id. */
4528 *ShBuf = (gctSHBUF)(gctUINTPTR_T)shBuf->id;
4529
4530 gcmkFOOTER_ARG("*ShBuf=%u", shBuf->id);
4531 return gcvSTATUS_OK;
4532
4533OnError:
4534 /* Error roll back. */
4535 if (shBuf != gcvNULL)
4536 {
4537 if (shBuf->id != 0)
4538 {
4539 gcmkVERIFY_OK(
4540 gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
4541 shBuf->id));
4542 }
4543
4544 gcmkOS_SAFE_FREE(Kernel->os, shBuf);
4545 }
4546
4547 gcmkFOOTER();
4548 return status;
4549}
4550
4551/*******************************************************************************
4552**
4553** gckKERNEL_DestroyShBuffer
4554**
4555** Destroy shared buffer.
4556** This will decrease reference of specified shared buffer and do actual
4557** destroy when no reference on it.
4558**
4559** INPUT:
4560**
4561** gckKERNEL Kernel
4562** Pointer to an gckKERNEL object.
4563**
4564** gctSHBUF ShBuf
4565** Specify the shared buffer to be destroyed.
4566**
4567** OUTPUT:
4568**
4569** Nothing.
4570*/
4571gceSTATUS
4572gckKERNEL_DestroyShBuffer(
4573 IN gckKERNEL Kernel,
4574 IN gctSHBUF ShBuf
4575 )
4576{
4577 gceSTATUS status;
4578 gcsSHBUF_PTR shBuf;
4579 gctINT32 oldValue = 0;
4580 gctBOOL acquired = gcvFALSE;
4581
4582 gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
4583 Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
4584
4585 /* Verify the arguments. */
4586 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
4587 gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
4588
4589 /* Acquire mutex. */
4590 gcmkONERROR(
4591 gckOS_AcquireMutex(Kernel->os,
4592 Kernel->db->pointerDatabaseMutex,
4593 gcvINFINITE));
4594 acquired = gcvTRUE;
4595
4596 /* Find shared buffer structure. */
4597 gcmkONERROR(
4598 gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
4599 (gctUINT32)(gctUINTPTR_T)ShBuf,
4600 (gctPOINTER)&shBuf));
4601
4602 gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
4603
4604 /* Decrease the reference count. */
4605 gckOS_AtomDecrement(Kernel->os, shBuf->reference, &oldValue);
4606
4607 if (oldValue == 1)
4608 {
4609 /* Free integer id. */
4610 gcmkVERIFY_OK(
4611 gckKERNEL_FreeIntegerId(Kernel->db->pointerDatabase,
4612 shBuf->id));
4613
4614 /* Free atom. */
4615 gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, shBuf->reference));
4616
4617 if (shBuf->data)
4618 {
4619 gcmkOS_SAFE_FREE(Kernel->os, shBuf->data);
4620 shBuf->data = gcvNULL;
4621 }
4622
4623 /* Free the shared buffer. */
4624 gcmkOS_SAFE_FREE(Kernel->os, shBuf);
4625 }
4626
4627 /* Release the mutex. */
4628 gcmkVERIFY_OK(
4629 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4630 acquired = gcvFALSE;
4631
4632 gcmkFOOTER_NO();
4633 return gcvSTATUS_OK;
4634
4635OnError:
4636 if (acquired)
4637 {
4638 /* Release the mutex. */
4639 gcmkVERIFY_OK(
4640 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4641 }
4642
4643 gcmkFOOTER();
4644 return status;
4645}
4646
4647/*******************************************************************************
4648**
4649** gckKERNEL_MapShBuffer
4650**
4651** Map shared buffer into this process so that it can be used in this process.
4652** This will increase reference count on the specified shared buffer.
4653** Call gckKERNEL_DestroyShBuffer to dereference.
4654**
4655** INPUT:
4656**
4657** gckKERNEL Kernel
4658** Pointer to an gckKERNEL object.
4659**
4660** gctSHBUF ShBuf
4661** Specify the shared buffer to be mapped.
4662**
4663** OUTPUT:
4664**
4665** Nothing.
4666*/
4667gceSTATUS
4668gckKERNEL_MapShBuffer(
4669 IN gckKERNEL Kernel,
4670 IN gctSHBUF ShBuf
4671 )
4672{
4673 gceSTATUS status;
4674 gcsSHBUF_PTR shBuf;
4675 gctINT32 oldValue = 0;
4676 gctBOOL acquired = gcvFALSE;
4677
4678 gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u",
4679 Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf);
4680
4681 /* Verify the arguments. */
4682 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
4683 gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
4684
4685 /* Acquire mutex. */
4686 gcmkONERROR(
4687 gckOS_AcquireMutex(Kernel->os,
4688 Kernel->db->pointerDatabaseMutex,
4689 gcvINFINITE));
4690 acquired = gcvTRUE;
4691
4692 /* Find shared buffer structure. */
4693 gcmkONERROR(
4694 gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
4695 (gctUINT32)(gctUINTPTR_T)ShBuf,
4696 (gctPOINTER)&shBuf));
4697
4698 gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
4699
4700 /* Increase the reference count. */
4701 gckOS_AtomIncrement(Kernel->os, shBuf->reference, &oldValue);
4702
4703 /* Release the mutex. */
4704 gcmkVERIFY_OK(
4705 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4706 acquired = gcvFALSE;
4707
4708 gcmkFOOTER_NO();
4709 return gcvSTATUS_OK;
4710
4711OnError:
4712 if (acquired)
4713 {
4714 /* Release the mutex. */
4715 gcmkVERIFY_OK(
4716 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4717 }
4718
4719 gcmkFOOTER();
4720 return status;
4721}
4722
4723/*******************************************************************************
4724**
4725** gckKERNEL_WriteShBuffer
4726**
4727** Write user data into shared buffer.
4728**
4729** INPUT:
4730**
4731** gckKERNEL Kernel
4732** Pointer to an gckKERNEL object.
4733**
4734** gctSHBUF ShBuf
4735** Specify the shared buffer to be written to.
4736**
4737** gctPOINTER UserData
4738** User mode pointer to hold the source data.
4739**
4740** gctUINT32 ByteCount
4741** Specify number of bytes to write. If this is larger than
4742** shared buffer size, gcvSTATUS_INVALID_ARGUMENT is returned.
4743**
4744** OUTPUT:
4745**
4746** Nothing.
4747*/
4748gceSTATUS
4749gckKERNEL_WriteShBuffer(
4750 IN gckKERNEL Kernel,
4751 IN gctSHBUF ShBuf,
4752 IN gctPOINTER UserData,
4753 IN gctUINT32 ByteCount
4754 )
4755{
4756 gceSTATUS status;
4757 gcsSHBUF_PTR shBuf;
4758 gctBOOL acquired = gcvFALSE;
4759
4760 gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u UserData=0x%X ByteCount=%u",
4761 Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf, UserData, ByteCount);
4762
4763 /* Verify the arguments. */
4764 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
4765 gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
4766
4767 /* Acquire mutex. */
4768 gcmkONERROR(
4769 gckOS_AcquireMutex(Kernel->os,
4770 Kernel->db->pointerDatabaseMutex,
4771 gcvINFINITE));
4772 acquired = gcvTRUE;
4773
4774 /* Find shared buffer structure. */
4775 gcmkONERROR(
4776 gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
4777 (gctUINT32)(gctUINTPTR_T)ShBuf,
4778 (gctPOINTER)&shBuf));
4779
4780 gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
4781
4782 if ((ByteCount > shBuf->size) ||
4783 (ByteCount == 0) ||
4784 (UserData == gcvNULL))
4785 {
4786 /* Exceeds buffer max size or invalid. */
4787 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4788 }
4789
4790 if (shBuf->data == gcvNULL)
4791 {
4792 /* Allocate buffer data when first time write. */
4793 gcmkONERROR(gckOS_Allocate(Kernel->os, ByteCount, &shBuf->data));
4794 }
4795
4796 /* Copy data from user. */
4797 gcmkONERROR(
4798 gckOS_CopyFromUserData(Kernel->os,
4799 shBuf->data,
4800 UserData,
4801 ByteCount));
4802
4803 /* Release the mutex. */
4804 gcmkVERIFY_OK(
4805 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4806 acquired = gcvFALSE;
4807
4808 gcmkFOOTER_NO();
4809 return gcvSTATUS_OK;
4810
4811OnError:
4812 if (acquired)
4813 {
4814 /* Release the mutex. */
4815 gcmkVERIFY_OK(
4816 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4817 }
4818
4819 gcmkFOOTER();
4820 return status;
4821}
4822
4823/*******************************************************************************
4824**
4825** gckKERNEL_ReadShBuffer
4826**
4827** Read data from shared buffer and copy to user pointer.
4828**
4829** INPUT:
4830**
4831** gckKERNEL Kernel
4832** Pointer to an gckKERNEL object.
4833**
4834** gctSHBUF ShBuf
4835** Specify the shared buffer to be read from.
4836**
4837** gctPOINTER UserData
4838** User mode pointer to save output data.
4839**
4840** gctUINT32 ByteCount
4841** Specify number of bytes to read.
4842** If this is larger than shared buffer size, only avaiable bytes are
4843** copied. If smaller, copy requested size.
4844**
4845** OUTPUT:
4846**
4847** gctUINT32 * BytesRead
4848** Pointer to hold how many bytes actually read from shared buffer.
4849*/
4850gceSTATUS
4851gckKERNEL_ReadShBuffer(
4852 IN gckKERNEL Kernel,
4853 IN gctSHBUF ShBuf,
4854 IN gctPOINTER UserData,
4855 IN gctUINT32 ByteCount,
4856 OUT gctUINT32 * BytesRead
4857 )
4858{
4859 gceSTATUS status;
4860 gcsSHBUF_PTR shBuf;
4861 gctUINT32 bytes;
4862 gctBOOL acquired = gcvFALSE;
4863
4864 gcmkHEADER_ARG("Kernel=0x%X ShBuf=%u UserData=0x%X ByteCount=%u",
4865 Kernel, (gctUINT32)(gctUINTPTR_T) ShBuf, UserData, ByteCount);
4866
4867 /* Verify the arguments. */
4868 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
4869 gcmkVERIFY_ARGUMENT(ShBuf != gcvNULL);
4870
4871 /* Acquire mutex. */
4872 gcmkONERROR(
4873 gckOS_AcquireMutex(Kernel->os,
4874 Kernel->db->pointerDatabaseMutex,
4875 gcvINFINITE));
4876 acquired = gcvTRUE;
4877
4878 /* Find shared buffer structure. */
4879 gcmkONERROR(
4880 gckKERNEL_QueryIntegerId(Kernel->db->pointerDatabase,
4881 (gctUINT32)(gctUINTPTR_T)ShBuf,
4882 (gctPOINTER)&shBuf));
4883
4884 gcmkASSERT(shBuf->id == (gctUINT32)(gctUINTPTR_T)ShBuf);
4885
4886 if (shBuf->data == gcvNULL)
4887 {
4888 *BytesRead = 0;
4889
4890 /* No data in shared buffer, skip copy. */
4891 status = gcvSTATUS_SKIP;
4892 goto OnError;
4893 }
4894 else if (ByteCount == 0)
4895 {
4896 /* Invalid size to read. */
4897 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4898 }
4899
4900 /* Determine bytes to copy. */
4901 bytes = (ByteCount < shBuf->size) ? ByteCount : shBuf->size;
4902
4903 /* Copy data to user. */
4904 gcmkONERROR(
4905 gckOS_CopyToUserData(Kernel->os,
4906 shBuf->data,
4907 UserData,
4908 bytes));
4909
4910 /* Return copied size. */
4911 *BytesRead = bytes;
4912
4913 /* Release the mutex. */
4914 gcmkVERIFY_OK(
4915 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4916 acquired = gcvFALSE;
4917
4918 gcmkFOOTER_ARG("*BytesRead=%u", bytes);
4919 return gcvSTATUS_OK;
4920
4921OnError:
4922 if (acquired)
4923 {
4924 /* Release the mutex. */
4925 gcmkVERIFY_OK(
4926 gckOS_ReleaseMutex(Kernel->os, Kernel->db->pointerDatabaseMutex));
4927 }
4928
4929 gcmkFOOTER();
4930 return status;
4931}
4932
4933/*******************************************************************************\
4934********************************* Fence *****************************************
4935\*******************************************************************************/
4936
4937gceSTATUS
4938gckFENCE_Create(
4939 IN gckOS Os,
4940 IN gckKERNEL Kernel,
4941 OUT gckFENCE * Fence
4942 )
4943{
4944 gceSTATUS status;
4945 gckFENCE fence = gcvNULL;
4946 gctSIZE_T pageSize = 4096;
4947
4948 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsFENCE), (gctPOINTER *)&fence));
4949
4950 gcmkONERROR(gckOS_CreateMutex(Os, (gctPOINTER *)&fence->mutex));
4951
4952 gcmkONERROR(gckOS_AllocateNonPagedMemory(
4953 Os,
4954 gcvFALSE,
4955 &pageSize,
4956 &fence->physical,
4957 &fence->logical
4958 ));
4959
4960 gcmkONERROR(gckHARDWARE_ConvertLogical(
4961 Kernel->hardware,
4962 fence->logical,
4963 gcvFALSE,
4964 &fence->address
4965 ));
4966
4967 *Fence = fence;
4968
4969 return gcvSTATUS_OK;
4970OnError:
4971 if (fence)
4972 {
4973 gckFENCE_Destory(Os, fence);
4974 }
4975
4976 return status;
4977}
4978
4979gceSTATUS
4980gckFENCE_Destory(
4981 IN gckOS Os,
4982 OUT gckFENCE Fence
4983 )
4984{
4985 if (Fence->mutex)
4986 {
4987 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Fence->mutex));
4988 }
4989
4990 if (Fence->logical)
4991 {
4992 gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
4993 Os,
4994 4096,
4995 Fence->physical,
4996 Fence->logical
4997 ));
4998 }
4999
5000 gcmkOS_SAFE_FREE(Os, Fence);
5001
5002 return gcvSTATUS_OK;
5003}
5004
5005/*******************************************************************************
5006***** Test Code ****************************************************************
5007*******************************************************************************/
5008
diff --git a/src/hal/kernel/gc_hal_kernel.h b/src/hal/kernel/gc_hal_kernel.h
new file mode 100755
index 0000000..14419e8
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel.h
@@ -0,0 +1,1485 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_h_
57#define __gc_hal_kernel_h_
58
59#include "gc_hal.h"
60#include "gc_hal_kernel_hardware.h"
61#include "gc_hal_driver.h"
62
63#include "gc_hal_kernel_mutex.h"
64
65
66
67#ifdef __cplusplus
68extern "C" {
69#endif
70
71/*******************************************************************************
72***** New MMU Defination *******************************************************/
73#define gcdMMU_MTLB_SHIFT 22
74#define gcdMMU_STLB_4K_SHIFT 12
75#define gcdMMU_STLB_64K_SHIFT 16
76
77#define gcdMMU_MTLB_BITS (32 - gcdMMU_MTLB_SHIFT)
78#define gcdMMU_PAGE_4K_BITS gcdMMU_STLB_4K_SHIFT
79#define gcdMMU_STLB_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_4K_BITS)
80#define gcdMMU_PAGE_64K_BITS gcdMMU_STLB_64K_SHIFT
81#define gcdMMU_STLB_64K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_PAGE_64K_BITS)
82
83#define gcdMMU_MTLB_ENTRY_NUM (1 << gcdMMU_MTLB_BITS)
84#define gcdMMU_MTLB_SIZE (gcdMMU_MTLB_ENTRY_NUM << 2)
85#define gcdMMU_STLB_4K_ENTRY_NUM (1 << gcdMMU_STLB_4K_BITS)
86#define gcdMMU_STLB_4K_SIZE (gcdMMU_STLB_4K_ENTRY_NUM << 2)
87#define gcdMMU_PAGE_4K_SIZE (1 << gcdMMU_STLB_4K_SHIFT)
88#define gcdMMU_STLB_64K_ENTRY_NUM (1 << gcdMMU_STLB_64K_BITS)
89#define gcdMMU_STLB_64K_SIZE (gcdMMU_STLB_64K_ENTRY_NUM << 2)
90#define gcdMMU_PAGE_64K_SIZE (1 << gcdMMU_STLB_64K_SHIFT)
91
92#define gcdMMU_MTLB_MASK (~((1U << gcdMMU_MTLB_SHIFT)-1))
93#define gcdMMU_STLB_4K_MASK ((~0U << gcdMMU_STLB_4K_SHIFT) ^ gcdMMU_MTLB_MASK)
94#define gcdMMU_PAGE_4K_MASK (gcdMMU_PAGE_4K_SIZE - 1)
95#define gcdMMU_STLB_64K_MASK ((~((1U << gcdMMU_STLB_64K_SHIFT)-1)) ^ gcdMMU_MTLB_MASK)
96#define gcdMMU_PAGE_64K_MASK (gcdMMU_PAGE_64K_SIZE - 1)
97
98/* Page offset definitions. */
99#define gcdMMU_OFFSET_4K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_4K_BITS)
100#define gcdMMU_OFFSET_4K_MASK ((1U << gcdMMU_OFFSET_4K_BITS) - 1)
101#define gcdMMU_OFFSET_16K_BITS (32 - gcdMMU_MTLB_BITS - gcdMMU_STLB_16K_BITS)
102#define gcdMMU_OFFSET_16K_MASK ((1U << gcdMMU_OFFSET_16K_BITS) - 1)
103
104#define gcdMMU_MTLB_PRESENT 0x00000001
105#define gcdMMU_MTLB_EXCEPTION 0x00000002
106#define gcdMMU_MTLB_4K_PAGE 0x00000000
107
108#define gcdMMU_STLB_PRESENT 0x00000001
109#define gcdMMU_STLB_EXCEPTION 0x00000002
110#define gcdMMU_STLB_4K_PAGE 0x00000000
111
112/*******************************************************************************
113***** Stuck Dump Level ********************************************************/
114
115/* Dump nonthing when stuck happens. */
116#define gcvSTUCK_DUMP_NONE 0
117
118/* Dump GPU state and memory near stuck point. */
119#define gcvSTUCK_DUMP_NEARBY_MEMORY 1
120
121/* Beside gcvSTUCK_DUMP_NEARBY_MEMORY, dump context buffer and user command buffer. */
122#define gcvSTUCK_DUMP_USER_COMMAND 2
123
124/* Beside gcvSTUCK_DUMP_USER_COMMAND, commit will be stall
125** to make sure command causing stuck isn't missed. */
126#define gcvSTUCK_DUMP_STALL_COMMAND 3
127
128/* Beside gcvSTUCK_DUMP_USER_COMMAND, dump kernel command buffer. */
129#define gcvSTUCK_DUMP_ALL_COMMAND 4
130
131/*******************************************************************************
132***** Process Secure Cache ****************************************************/
133
134#define gcdSECURE_CACHE_LRU 1
135#define gcdSECURE_CACHE_LINEAR 2
136#define gcdSECURE_CACHE_HASH 3
137#define gcdSECURE_CACHE_TABLE 4
138
139#define gcvPAGE_TABLE_DIRTY_BIT_OTHER (1 << 0)
140#define gcvPAGE_TABLE_DIRTY_BIT_FE (1 << 1)
141
142typedef struct _gcskLOGICAL_CACHE * gcskLOGICAL_CACHE_PTR;
143typedef struct _gcskLOGICAL_CACHE gcskLOGICAL_CACHE;
144struct _gcskLOGICAL_CACHE
145{
146 /* Logical address. */
147 gctPOINTER logical;
148
149 /* DMAable address. */
150 gctUINT32 dma;
151
152#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
153 /* Pointer to the previous and next hash tables. */
154 gcskLOGICAL_CACHE_PTR nextHash;
155 gcskLOGICAL_CACHE_PTR prevHash;
156#endif
157
158#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
159 /* Pointer to the previous and next slot. */
160 gcskLOGICAL_CACHE_PTR next;
161 gcskLOGICAL_CACHE_PTR prev;
162#endif
163
164#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_LINEAR
165 /* Time stamp. */
166 gctUINT64 stamp;
167#endif
168};
169
170typedef struct _gcskSECURE_CACHE * gcskSECURE_CACHE_PTR;
171typedef struct _gcskSECURE_CACHE
172{
173 /* Cache memory. */
174 gcskLOGICAL_CACHE cache[1 + gcdSECURE_CACHE_SLOTS];
175
176 /* Last known index for LINEAR mode. */
177 gcskLOGICAL_CACHE_PTR cacheIndex;
178
179 /* Current free slot for LINEAR mode. */
180 gctUINT32 cacheFree;
181
182 /* Time stamp for LINEAR mode. */
183 gctUINT64 cacheStamp;
184
185#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
186 /* Hash table for HASH mode. */
187 gcskLOGICAL_CACHE hash[256];
188#endif
189}
190gcskSECURE_CACHE;
191
192/*******************************************************************************
193***** Process Database Management *********************************************/
194
195typedef enum _gceDATABASE_TYPE
196{
197 gcvDB_VIDEO_MEMORY = 1, /* Video memory created. */
198 gcvDB_COMMAND_BUFFER, /* Command Buffer. */
199 gcvDB_NON_PAGED, /* Non paged memory. */
200 gcvDB_CONTIGUOUS, /* Contiguous memory. */
201 gcvDB_SIGNAL, /* Signal. */
202 gcvDB_VIDEO_MEMORY_LOCKED, /* Video memory locked. */
203 gcvDB_CONTEXT, /* Context */
204 gcvDB_IDLE, /* GPU idle. */
205 gcvDB_MAP_MEMORY, /* Map memory */
206 gcvDB_MAP_USER_MEMORY, /* Map user memory */
207 gcvDB_SYNC_POINT, /* Sync point. */
208 gcvDB_SHBUF, /* Shared buffer. */
209}
210gceDATABASE_TYPE;
211
212#define gcdDATABASE_TYPE_MASK 0x000000FF
213#define gcdDB_VIDEO_MEMORY_TYPE_MASK 0x0000FF00
214#define gcdDB_VIDEO_MEMORY_TYPE_SHIFT 8
215
216#define gcdDB_VIDEO_MEMORY_POOL_MASK 0x00FF0000
217#define gcdDB_VIDEO_MEMORY_POOL_SHIFT 16
218
219typedef struct _gcsDATABASE_RECORD * gcsDATABASE_RECORD_PTR;
220typedef struct _gcsDATABASE_RECORD
221{
222 /* Pointer to kernel. */
223 gckKERNEL kernel;
224
225 /* Pointer to next database record. */
226 gcsDATABASE_RECORD_PTR next;
227
228 /* Type of record. */
229 gceDATABASE_TYPE type;
230
231 /* Data for record. */
232 gctPOINTER data;
233 gctPHYS_ADDR physical;
234 gctSIZE_T bytes;
235}
236gcsDATABASE_RECORD;
237
238typedef struct _gcsDATABASE * gcsDATABASE_PTR;
239typedef struct _gcsDATABASE
240{
241 /* Pointer to next entry is hash list. */
242 gcsDATABASE_PTR next;
243 gctSIZE_T slot;
244
245 /* Process ID. */
246 gctUINT32 processID;
247
248 /* Sizes to query. */
249 gcsDATABASE_COUNTERS vidMem;
250 gcsDATABASE_COUNTERS nonPaged;
251 gcsDATABASE_COUNTERS contiguous;
252 gcsDATABASE_COUNTERS mapUserMemory;
253 gcsDATABASE_COUNTERS mapMemory;
254 gcsDATABASE_COUNTERS virtualCommandBuffer;
255
256 gcsDATABASE_COUNTERS vidMemType[gcvSURF_NUM_TYPES];
257 /* Counter for each video memory pool. */
258 gcsDATABASE_COUNTERS vidMemPool[gcvPOOL_NUMBER_OF_POOLS];
259 gctPOINTER counterMutex;
260
261 /* Idle time management. */
262 gctUINT64 lastIdle;
263 gctUINT64 idle;
264
265 /* Pointer to database. */
266 gcsDATABASE_RECORD_PTR list[48];
267
268#if gcdSECURE_USER
269 /* Secure cache. */
270 gcskSECURE_CACHE cache;
271#endif
272
273 gctPOINTER handleDatabase;
274 gctPOINTER handleDatabaseMutex;
275
276#if gcdPROCESS_ADDRESS_SPACE
277 gckMMU mmu;
278#endif
279}
280gcsDATABASE;
281
282typedef struct _gcsRECORDER * gckRECORDER;
283
284typedef struct _gcsFDPRIVATE * gcsFDPRIVATE_PTR;
285typedef struct _gcsFDPRIVATE
286{
287 gctINT (* release) (gcsFDPRIVATE_PTR Private);
288}
289gcsFDPRIVATE;
290
291/* Create a process database that will contain all its allocations. */
292gceSTATUS
293gckKERNEL_CreateProcessDB(
294 IN gckKERNEL Kernel,
295 IN gctUINT32 ProcessID
296 );
297
298/* Add a record to the process database. */
299gceSTATUS
300gckKERNEL_AddProcessDB(
301 IN gckKERNEL Kernel,
302 IN gctUINT32 ProcessID,
303 IN gceDATABASE_TYPE Type,
304 IN gctPOINTER Pointer,
305 IN gctPHYS_ADDR Physical,
306 IN gctSIZE_T Size
307 );
308
309/* Remove a record to the process database. */
310gceSTATUS
311gckKERNEL_RemoveProcessDB(
312 IN gckKERNEL Kernel,
313 IN gctUINT32 ProcessID,
314 IN gceDATABASE_TYPE Type,
315 IN gctPOINTER Pointer
316 );
317
318/* Destroy the process database. */
319gceSTATUS
320gckKERNEL_DestroyProcessDB(
321 IN gckKERNEL Kernel,
322 IN gctUINT32 ProcessID
323 );
324
325/* Find a record to the process database. */
326gceSTATUS
327gckKERNEL_FindProcessDB(
328 IN gckKERNEL Kernel,
329 IN gctUINT32 ProcessID,
330 IN gctUINT32 ThreadID,
331 IN gceDATABASE_TYPE Type,
332 IN gctPOINTER Pointer,
333 OUT gcsDATABASE_RECORD_PTR Record
334 );
335
336/* Query the process database. */
337gceSTATUS
338gckKERNEL_QueryProcessDB(
339 IN gckKERNEL Kernel,
340 IN gctUINT32 ProcessID,
341 IN gctBOOL LastProcessID,
342 IN gceDATABASE_TYPE Type,
343 OUT gcuDATABASE_INFO * Info
344 );
345
346/* Dump the process database. */
347gceSTATUS
348gckKERNEL_DumpProcessDB(
349 IN gckKERNEL Kernel
350 );
351
352/* Dump the video memory usage for process specified. */
353gceSTATUS
354gckKERNEL_DumpVidMemUsage(
355 IN gckKERNEL Kernel,
356 IN gctINT32 ProcessID
357 );
358
359gceSTATUS
360gckKERNEL_FindDatabase(
361 IN gckKERNEL Kernel,
362 IN gctUINT32 ProcessID,
363 IN gctBOOL LastProcessID,
364 OUT gcsDATABASE_PTR * Database
365 );
366
367gceSTATUS
368gckKERNEL_FindHandleDatbase(
369 IN gckKERNEL Kernel,
370 IN gctUINT32 ProcessID,
371 OUT gctPOINTER * HandleDatabase,
372 OUT gctPOINTER * HandleDatabaseMutex
373 );
374
375gceSTATUS
376gckKERNEL_GetProcessMMU(
377 IN gckKERNEL Kernel,
378 OUT gckMMU * Mmu
379 );
380
381gceSTATUS
382gckKERNEL_SetRecovery(
383 IN gckKERNEL Kernel,
384 IN gctBOOL Recovery,
385 IN gctUINT32 StuckDump
386 );
387
388gceSTATUS
389gckMMU_FlatMapping(
390 IN gckMMU Mmu,
391 IN gctUINT32 Physical
392 );
393
394gceSTATUS
395gckMMU_GetPageEntry(
396 IN gckMMU Mmu,
397 IN gctUINT32 Address,
398 IN gctUINT32_PTR *PageTable
399 );
400
401gceSTATUS
402gckMMU_FreePagesEx(
403 IN gckMMU Mmu,
404 IN gctUINT32 Address,
405 IN gctSIZE_T PageCount
406 );
407
408gceSTATUS
409gckKERNEL_CreateIntegerDatabase(
410 IN gckKERNEL Kernel,
411 OUT gctPOINTER * Database
412 );
413
414gceSTATUS
415gckKERNEL_DestroyIntegerDatabase(
416 IN gckKERNEL Kernel,
417 IN gctPOINTER Database
418 );
419
420gceSTATUS
421gckKERNEL_AllocateIntegerId(
422 IN gctPOINTER Database,
423 IN gctPOINTER Pointer,
424 OUT gctUINT32 * Id
425 );
426
427gceSTATUS
428gckKERNEL_FreeIntegerId(
429 IN gctPOINTER Database,
430 IN gctUINT32 Id
431 );
432
433gceSTATUS
434gckKERNEL_QueryIntegerId(
435 IN gctPOINTER Database,
436 IN gctUINT32 Id,
437 OUT gctPOINTER * Pointer
438 );
439
440/* Pointer rename */
441gctUINT32
442gckKERNEL_AllocateNameFromPointer(
443 IN gckKERNEL Kernel,
444 IN gctPOINTER Pointer
445 );
446
447gctPOINTER
448gckKERNEL_QueryPointerFromName(
449 IN gckKERNEL Kernel,
450 IN gctUINT32 Name
451 );
452
453gceSTATUS
454gckKERNEL_DeleteName(
455 IN gckKERNEL Kernel,
456 IN gctUINT32 Name
457 );
458
459#if gcdSECURE_USER
460/* Get secure cache from the process database. */
461gceSTATUS
462gckKERNEL_GetProcessDBCache(
463 IN gckKERNEL Kernel,
464 IN gctUINT32 ProcessID,
465 OUT gcskSECURE_CACHE_PTR * Cache
466 );
467#endif
468
469/*******************************************************************************
470********* Timer Management ****************************************************/
471typedef struct _gcsTIMER * gcsTIMER_PTR;
472typedef struct _gcsTIMER
473{
474 /* Start and Stop time holders. */
475 gctUINT64 startTime;
476 gctUINT64 stopTime;
477}
478gcsTIMER;
479
480/******************************************************************************\
481********************************** Structures **********************************
482\******************************************************************************/
483
484/* gckDB object. */
485struct _gckDB
486{
487 /* Database management. */
488 gcsDATABASE_PTR db[16];
489 gctPOINTER dbMutex;
490 gcsDATABASE_PTR freeDatabase;
491 gcsDATABASE_RECORD_PTR freeRecord;
492 gcsDATABASE_PTR lastDatabase;
493 gctUINT32 lastProcessID;
494 gctUINT64 lastIdle;
495 gctUINT64 idleTime;
496 gctUINT64 lastSlowdown;
497 gctUINT64 lastSlowdownIdle;
498 gctPOINTER nameDatabase;
499 gctPOINTER nameDatabaseMutex;
500
501 gctPOINTER pointerDatabase;
502 gctPOINTER pointerDatabaseMutex;
503};
504
505typedef struct _gckVIRTUAL_COMMAND_BUFFER * gckVIRTUAL_COMMAND_BUFFER_PTR;
506typedef struct _gckVIRTUAL_COMMAND_BUFFER
507{
508 gctPHYS_ADDR physical;
509 gctPOINTER userLogical;
510 gctPOINTER kernelLogical;
511 gctSIZE_T bytes;
512 gctSIZE_T pageCount;
513 gctPOINTER pageTable;
514 gctUINT32 gpuAddress;
515 gctUINT pid;
516 gckVIRTUAL_COMMAND_BUFFER_PTR next;
517 gckVIRTUAL_COMMAND_BUFFER_PTR prev;
518 gckKERNEL kernel;
519#if gcdPROCESS_ADDRESS_SPACE
520 gckMMU mmu;
521#endif
522}
523gckVIRTUAL_COMMAND_BUFFER;
524
525/* gckKERNEL object. */
526struct _gckKERNEL
527{
528 /* Object. */
529 gcsOBJECT object;
530
531 /* Pointer to gckOS object. */
532 gckOS os;
533
534 /* Core */
535 gceCORE core;
536
537 /* Pointer to gckHARDWARE object. */
538 gckHARDWARE hardware;
539
540 /* Pointer to gckCOMMAND object. */
541 gckCOMMAND command;
542
543 /* Pointer to gckEVENT object. */
544 gckEVENT eventObj;
545
546 /* Pointer to context. */
547 gctPOINTER context;
548
549 /* Pointer to gckMMU object. */
550 gckMMU mmu;
551
552 /* Arom holding number of clients. */
553 gctPOINTER atomClients;
554
555#if VIVANTE_PROFILER
556 /* Enable profiling */
557 gctBOOL profileEnable;
558 /* Clear profile register or not*/
559 gctBOOL profileCleanRegister;
560#endif
561
562#ifdef QNX_SINGLE_THREADED_DEBUGGING
563 gctPOINTER debugMutex;
564#endif
565
566 /* Database management. */
567 gckDB db;
568 gctBOOL dbCreated;
569
570 gctUINT64 resetTimeStamp;
571
572 /* Pointer to gckEVENT object. */
573 gcsTIMER timers[8];
574 gctUINT32 timeOut;
575
576
577 /* Virtual command buffer list. */
578 gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferHead;
579 gckVIRTUAL_COMMAND_BUFFER_PTR virtualBufferTail;
580 gctPOINTER virtualBufferLock;
581
582 /* Enable virtual command buffer. */
583 gctBOOL virtualCommandBuffer;
584
585#if gcdDVFS
586 gckDVFS dvfs;
587#endif
588
589#if gcdANDROID_NATIVE_FENCE_SYNC
590 gctHANDLE timeline;
591#endif
592
593 /* Enable recovery. */
594 gctBOOL recovery;
595
596 /* Level of dump information after stuck. */
597 gctUINT stuckDump;
598
599
600 /* Timer to monitor GPU stuck. */
601 gctPOINTER monitorTimer;
602
603 /* Flag to quit monitor timer. */
604 gctBOOL monitorTimerStop;
605
606 /* Monitor states. */
607 gctBOOL monitoring;
608 gctUINT32 lastCommitStamp;
609 gctUINT32 timer;
610 gctUINT32 restoreAddress;
611 gctUINT32 restoreMask;
612};
613
614struct _FrequencyHistory
615{
616 gctUINT32 frequency;
617 gctUINT32 count;
618};
619
620/* gckDVFS object. */
621struct _gckDVFS
622{
623 gckOS os;
624 gckHARDWARE hardware;
625 gctPOINTER timer;
626 gctUINT32 pollingTime;
627 gctBOOL stop;
628 gctUINT32 totalConfig;
629 gctUINT32 loads[8];
630 gctUINT8 currentScale;
631 struct _FrequencyHistory frequencyHistory[16];
632};
633
634typedef struct _gcsFENCE * gckFENCE;
635typedef struct _gcsFENCE
636{
637 /* Fence location. */
638 gctPHYS_ADDR physical;
639 gctPOINTER logical;
640 gctUINT32 address;
641
642 gctPOINTER mutex;
643}
644gcsFENCE;
645
646/* gckCOMMAND object. */
647struct _gckCOMMAND
648{
649 /* Object. */
650 gcsOBJECT object;
651
652 /* Pointer to required object. */
653 gckKERNEL kernel;
654 gckOS os;
655
656 /* Number of bytes per page. */
657 gctUINT32 pageSize;
658
659 /* Current pipe select. */
660 gcePIPE_SELECT pipeSelect;
661
662 /* Command queue running flag. */
663 gctBOOL running;
664
665 /* Idle flag and commit stamp. */
666 gctBOOL idle;
667 gctUINT64 commitStamp;
668
669 /* Command queue mutex. */
670 gctPOINTER mutexQueue;
671
672 /* Context switching mutex. */
673 gctPOINTER mutexContext;
674
675#if VIVANTE_PROFILER_CONTEXT
676 /* Context sequence mutex. */
677 gctPOINTER mutexContextSeq;
678#endif
679
680 /* Command queue power semaphore. */
681 gctPOINTER powerSemaphore;
682
683 /* Current command queue. */
684 struct _gcskCOMMAND_QUEUE
685 {
686 gctSIGNAL signal;
687 gctPHYS_ADDR physical;
688 gctPOINTER logical;
689 gctUINT32 address;
690 }
691 queues[gcdCOMMAND_QUEUES];
692
693 gctUINT32 physical;
694 gctPOINTER logical;
695 gctUINT32 address;
696 gctUINT32 offset;
697 gctINT index;
698#if gcmIS_DEBUG(gcdDEBUG_TRACE)
699 gctUINT wrapCount;
700#endif
701
702 /* The command queue is new. */
703 gctBOOL newQueue;
704
705 /* Context management. */
706 gckCONTEXT currContext;
707 gctPOINTER stateMap;
708
709 /* Pointer to last WAIT command. */
710 gctUINT32 waitPhysical;
711 gctPOINTER waitLogical;
712 gctUINT32 waitSize;
713
714 /* Command buffer alignment. */
715 gctUINT32 alignment;
716 gctUINT32 reservedHead;
717 gctUINT32 reservedTail;
718
719 /* Commit counter. */
720 gctPOINTER atomCommit;
721
722 /* Kernel process ID. */
723 gctUINT32 kernelProcessID;
724
725 /* End Event signal. */
726 gctSIGNAL endEventSignal;
727
728#if gcdSECURE_USER
729 /* Hint array copy buffer. */
730 gctBOOL hintArrayAllocated;
731 gctUINT hintArraySize;
732 gctUINT32_PTR hintArray;
733#endif
734
735#if gcdPROCESS_ADDRESS_SPACE
736 gckMMU currentMmu;
737#endif
738 struct _gckENTRYQUEUE queue;
739
740 gckFENCE fence;
741};
742
743typedef struct _gcsEVENT * gcsEVENT_PTR;
744
745/* Structure holding one event to be processed. */
746typedef struct _gcsEVENT
747{
748 /* Pointer to next event in queue. */
749 gcsEVENT_PTR next;
750
751 /* Event information. */
752 gcsHAL_INTERFACE info;
753
754 /* Process ID owning the event. */
755 gctUINT32 processID;
756
757#ifdef __QNXNTO__
758 /* Kernel. */
759 gckKERNEL kernel;
760#endif
761
762 gctBOOL fromKernel;
763}
764gcsEVENT;
765
766/* Structure holding a list of events to be processed by an interrupt. */
767typedef struct _gcsEVENT_QUEUE * gcsEVENT_QUEUE_PTR;
768typedef struct _gcsEVENT_QUEUE
769{
770 /* Time stamp. */
771 gctUINT64 stamp;
772
773 /* Source of the event. */
774 gceKERNEL_WHERE source;
775
776
777 /* Pointer to head of event queue. */
778 gcsEVENT_PTR head;
779
780 /* Pointer to tail of event queue. */
781 gcsEVENT_PTR tail;
782
783 /* Next list of events. */
784 gcsEVENT_QUEUE_PTR next;
785
786 /* Current commit stamp. */
787 gctUINT64 commitStamp;
788}
789gcsEVENT_QUEUE;
790
791/*
792 gcdREPO_LIST_COUNT defines the maximum number of event queues with different
793 hardware module sources that may coexist at the same time. Only two sources
794 are supported - gcvKERNEL_COMMAND and gcvKERNEL_PIXEL. gcvKERNEL_COMMAND
795 source is used only for managing the kernel command queue and is only issued
796 when the current command queue gets full. Since we commit event queues every
797 time we commit command buffers, in the worst case we can have up to three
798 pending event queues:
799 - gcvKERNEL_PIXEL
800 - gcvKERNEL_COMMAND (queue overflow)
801 - gcvKERNEL_PIXEL
802*/
803#define gcdREPO_LIST_COUNT 3
804
805/* gckEVENT object. */
806struct _gckEVENT
807{
808 /* The object. */
809 gcsOBJECT object;
810
811 /* Pointer to required objects. */
812 gckOS os;
813 gckKERNEL kernel;
814
815 /* Time stamp. */
816 gctUINT64 stamp;
817 gctUINT32 lastCommitStamp;
818
819 /* Queue mutex. */
820 gctPOINTER eventQueueMutex;
821
822 /* Array of event queues. */
823 gcsEVENT_QUEUE queues[29];
824 gctUINT8 lastID;
825 gctPOINTER freeAtom;
826
827 /* Pending events. */
828#if gcdSMP
829 gctPOINTER pending;
830#else
831 volatile gctUINT pending;
832#endif
833
834 /* List of free event structures and its mutex. */
835 gcsEVENT_PTR freeEventList;
836 gctSIZE_T freeEventCount;
837 gctPOINTER freeEventMutex;
838
839 /* Event queues. */
840 gcsEVENT_QUEUE_PTR queueHead;
841 gcsEVENT_QUEUE_PTR queueTail;
842 gcsEVENT_QUEUE_PTR freeList;
843 gcsEVENT_QUEUE repoList[gcdREPO_LIST_COUNT];
844 gctPOINTER eventListMutex;
845
846 gctPOINTER submitTimer;
847
848#if gcdINTERRUPT_STATISTIC
849 gctPOINTER interruptCount;
850#endif
851
852#if gcdRECORD_COMMAND
853 gckRECORDER recorder;
854#endif
855};
856
857/* Free all events belonging to a process. */
858gceSTATUS
859gckEVENT_FreeProcess(
860 IN gckEVENT Event,
861 IN gctUINT32 ProcessID
862 );
863
864gceSTATUS
865gckEVENT_Stop(
866 IN gckEVENT Event,
867 IN gctUINT32 ProcessID,
868 IN gctUINT32 Handle,
869 IN gctPOINTER Logical,
870 IN gctSIGNAL Signal,
871 IN OUT gctUINT32 * waitSize
872 );
873
874typedef struct _gcsLOCK_INFO * gcsLOCK_INFO_PTR;
875typedef struct _gcsLOCK_INFO
876{
877 gctUINT32 GPUAddresses[gcdMAX_GPU_COUNT];
878 gctPOINTER pageTables[gcdMAX_GPU_COUNT];
879 gctUINT32 lockeds[gcdMAX_GPU_COUNT];
880 gckKERNEL lockKernels[gcdMAX_GPU_COUNT];
881 gckMMU lockMmus[gcdMAX_GPU_COUNT];
882}
883gcsLOCK_INFO;
884
885typedef struct _gcsGPU_MAP * gcsGPU_MAP_PTR;
886typedef struct _gcsGPU_MAP
887{
888 gctINT pid;
889 gcsLOCK_INFO lockInfo;
890 gcsGPU_MAP_PTR prev;
891 gcsGPU_MAP_PTR next;
892}
893gcsGPU_MAP;
894
895/* gcuVIDMEM_NODE structure. */
896typedef union _gcuVIDMEM_NODE
897{
898 /* Allocated from gckVIDMEM. */
899 struct _gcsVIDMEM_NODE_VIDMEM
900 {
901 /* Owner of this node. */
902 gckVIDMEM memory;
903
904 /* Dual-linked list of nodes. */
905 gcuVIDMEM_NODE_PTR next;
906 gcuVIDMEM_NODE_PTR prev;
907
908 /* Dual linked list of free nodes. */
909 gcuVIDMEM_NODE_PTR nextFree;
910 gcuVIDMEM_NODE_PTR prevFree;
911
912 /* Information for this node. */
913 gctSIZE_T offset;
914 gctSIZE_T bytes;
915 gctUINT32 alignment;
916
917#ifdef __QNXNTO__
918 /* Client virtual address. */
919 gctPOINTER logical;
920#endif
921
922 /* Locked counter. */
923 gctINT32 locked;
924
925 /* Memory pool. */
926 gcePOOL pool;
927 gctUINT32 physical;
928
929 /* Process ID owning this memory. */
930 gctUINT32 processID;
931
932 }
933 VidMem;
934
935 /* Allocated from gckOS. */
936 struct _gcsVIDMEM_NODE_VIRTUAL
937 {
938 /* Pointer to gckKERNEL object. */
939 gckKERNEL kernel;
940
941 /* Information for this node. */
942 /* Contiguously allocated? */
943 gctBOOL contiguous;
944 /* mdl record pointer... a kmalloc address. Process agnostic. */
945 gctPHYS_ADDR physical;
946 gctSIZE_T bytes;
947 /* do_mmap_pgoff address... mapped per-process. */
948 gctPOINTER logical;
949
950
951 /* Customer private handle */
952 gctUINT32 gid;
953
954 /* Page table information. */
955 /* Used only when node is not contiguous */
956 gctSIZE_T pageCount;
957
958 /* Used only when node is not contiguous */
959 gctPOINTER pageTables[gcdMAX_GPU_COUNT];
960 /* Pointer to gckKERNEL object who lock this. */
961 gckKERNEL lockKernels[gcdMAX_GPU_COUNT];
962 /* Actual physical address */
963 gctUINT32 addresses[gcdMAX_GPU_COUNT];
964
965 /* Locked counter. */
966 gctINT32 lockeds[gcdMAX_GPU_COUNT];
967
968 /* Process ID owning this memory. */
969 gctUINT32 processID;
970
971 /* Surface type. */
972 gceSURF_TYPE type;
973 }
974 Virtual;
975}
976gcuVIDMEM_NODE;
977
978/* gckVIDMEM object. */
979struct _gckVIDMEM
980{
981 /* Object. */
982 gcsOBJECT object;
983
984 /* Pointer to gckOS object. */
985 gckOS os;
986
987 /* Information for this video memory heap. */
988 gctUINT32 baseAddress;
989 gctSIZE_T bytes;
990 gctSIZE_T freeBytes;
991
992 /* Mapping for each type of surface. */
993 gctINT mapping[gcvSURF_NUM_TYPES];
994
995 /* Sentinel nodes for up to 8 banks. */
996 gcuVIDMEM_NODE sentinel[8];
997
998 /* Allocation threshold. */
999 gctSIZE_T threshold;
1000
1001 /* The heap mutex. */
1002 gctPOINTER mutex;
1003};
1004
1005typedef struct _gcsVIDMEM_NODE
1006{
1007 /* Pointer to gcuVIDMEM_NODE. */
1008 gcuVIDMEM_NODE_PTR node;
1009
1010 /* Mutex to protect node. */
1011 gctPOINTER mutex;
1012
1013 /* Reference count. */
1014 gctPOINTER reference;
1015
1016 /* Name for client to import. */
1017 gctUINT32 name;
1018
1019#if gcdPROCESS_ADDRESS_SPACE
1020 /* Head of mapping list. */
1021 gcsGPU_MAP_PTR mapHead;
1022
1023 /* Tail of mapping list. */
1024 gcsGPU_MAP_PTR mapTail;
1025
1026 gctPOINTER mapMutex;
1027#endif
1028
1029 /* Surface Type. */
1030 gceSURF_TYPE type;
1031
1032 /* Pool from which node is allocated. */
1033 gcePOOL pool;
1034}
1035gcsVIDMEM_NODE;
1036
1037typedef struct _gcsVIDMEM_HANDLE * gckVIDMEM_HANDLE;
1038typedef struct _gcsVIDMEM_HANDLE
1039{
1040 /* Pointer to gckVIDMEM_NODE. */
1041 gckVIDMEM_NODE node;
1042
1043 /* Handle for current process. */
1044 gctUINT32 handle;
1045
1046 /* Reference count for this handle. */
1047 gctPOINTER reference;
1048}
1049gcsVIDMEM_HANDLE;
1050
1051typedef struct _gcsSHBUF * gcsSHBUF_PTR;
1052typedef struct _gcsSHBUF
1053{
1054 /* ID. */
1055 gctUINT32 id;
1056
1057 /* Reference count. */
1058 gctPOINTER reference;
1059
1060 /* Data size. */
1061 gctUINT32 size;
1062
1063 /* Data. */
1064 gctPOINTER data;
1065}
1066gcsSHBUF;
1067
1068gceSTATUS
1069gckVIDMEM_HANDLE_Reference(
1070 IN gckKERNEL Kernel,
1071 IN gctUINT32 ProcessID,
1072 IN gctUINT32 Handle
1073 );
1074
1075gceSTATUS
1076gckVIDMEM_HANDLE_Dereference(
1077 IN gckKERNEL Kernel,
1078 IN gctUINT32 ProcessID,
1079 IN gctUINT32 Handle
1080 );
1081
1082gceSTATUS
1083gckVIDMEM_NODE_Allocate(
1084 IN gckKERNEL Kernel,
1085 IN gcuVIDMEM_NODE_PTR VideoNode,
1086 IN gceSURF_TYPE Type,
1087 IN gcePOOL Pool,
1088 IN gctUINT32 * Handle
1089 );
1090
1091gceSTATUS
1092gckVIDMEM_Node_Lock(
1093 IN gckKERNEL Kernel,
1094 IN gckVIDMEM_NODE Node,
1095 OUT gctUINT32 *Address
1096 );
1097
1098gceSTATUS
1099gckVIDMEM_NODE_Unlock(
1100 IN gckKERNEL Kernel,
1101 IN gckVIDMEM_NODE Node,
1102 IN gctUINT32 ProcessID
1103 );
1104
1105gceSTATUS
1106gckVIDMEM_NODE_Dereference(
1107 IN gckKERNEL Kernel,
1108 IN gckVIDMEM_NODE Node
1109 );
1110
1111gceSTATUS
1112gckVIDMEM_NODE_Name(
1113 IN gckKERNEL Kernel,
1114 IN gctUINT32 Handle,
1115 IN gctUINT32 * Name
1116 );
1117
1118gceSTATUS
1119gckVIDMEM_NODE_Import(
1120 IN gckKERNEL Kernel,
1121 IN gctUINT32 Name,
1122 IN gctUINT32 * Handle
1123 );
1124
1125gceSTATUS
1126gckVIDMEM_HANDLE_LookupAndReference(
1127 IN gckKERNEL Kernel,
1128 IN gctUINT32 Handle,
1129 OUT gckVIDMEM_NODE * Node
1130 );
1131
1132gceSTATUS
1133gckVIDMEM_HANDLE_Lookup(
1134 IN gckKERNEL Kernel,
1135 IN gctUINT32 ProcessID,
1136 IN gctUINT32 Handle,
1137 OUT gckVIDMEM_NODE * Node
1138 );
1139
1140gceSTATUS
1141gckVIDMEM_NODE_GetFd(
1142 IN gckKERNEL Kernel,
1143 IN gctUINT32 Handle,
1144 OUT gctINT * Fd
1145 );
1146
1147gceSTATUS
1148gckVIDMEM_ConstructVirtualFromUserMemory(
1149 IN gckKERNEL Kernel,
1150 IN gcsUSER_MEMORY_DESC_PTR Desc,
1151 OUT gcuVIDMEM_NODE_PTR * Node
1152 );
1153
1154#if gcdPROCESS_ADDRESS_SPACE
1155gceSTATUS
1156gckEVENT_DestroyMmu(
1157 IN gckEVENT Event,
1158 IN gckMMU Mmu,
1159 IN gceKERNEL_WHERE FromWhere
1160 );
1161#endif
1162
1163/* gckMMU object. */
1164struct _gckMMU
1165{
1166 /* The object. */
1167 gcsOBJECT object;
1168
1169 /* Pointer to gckOS object. */
1170 gckOS os;
1171
1172 /* Pointer to gckHARDWARE object. */
1173 gckHARDWARE hardware;
1174
1175 /* The page table mutex. */
1176 gctPOINTER pageTableMutex;
1177
1178 /* Page table information. */
1179 gctSIZE_T pageTableSize;
1180 gctPHYS_ADDR pageTablePhysical;
1181 gctUINT32_PTR pageTableLogical;
1182 gctUINT32 pageTableEntries;
1183
1184 /* Master TLB information. */
1185 gctSIZE_T mtlbSize;
1186 gctPHYS_ADDR mtlbPhysical;
1187 gctUINT32_PTR mtlbLogical;
1188 gctUINT32 mtlbEntries;
1189
1190 /* Free entries. */
1191 gctUINT32 heapList;
1192 gctBOOL freeNodes;
1193
1194 gctPOINTER staticSTLB;
1195 gctBOOL enabled;
1196
1197 gctUINT32 dynamicMappingStart;
1198
1199 gctUINT32_PTR mapLogical;
1200#if gcdPROCESS_ADDRESS_SPACE
1201 gctPOINTER pageTableDirty[gcdMAX_GPU_COUNT];
1202 gctPOINTER stlbs;
1203#endif
1204};
1205
1206gceSTATUS
1207gckOS_CreateKernelVirtualMapping(
1208 IN gckOS Os,
1209 IN gctPHYS_ADDR Physical,
1210 IN gctSIZE_T Bytes,
1211 OUT gctPOINTER * Logical,
1212 OUT gctSIZE_T * PageCount
1213 );
1214
1215gceSTATUS
1216gckOS_DestroyKernelVirtualMapping(
1217 IN gckOS Os,
1218 IN gctPHYS_ADDR Physical,
1219 IN gctSIZE_T Bytes,
1220 IN gctPOINTER Logical
1221 );
1222
1223gceSTATUS
1224gckOS_CreateUserVirtualMapping(
1225 IN gckOS Os,
1226 IN gctPHYS_ADDR Physical,
1227 IN gctSIZE_T Bytes,
1228 OUT gctPOINTER * Logical,
1229 OUT gctSIZE_T * PageCount
1230 );
1231
1232gceSTATUS
1233gckOS_DestroyUserVirtualMapping(
1234 IN gckOS Os,
1235 IN gctPHYS_ADDR Physical,
1236 IN gctSIZE_T Bytes,
1237 IN gctPOINTER Logical
1238 );
1239
1240gceSTATUS
1241gckOS_GetFd(
1242 IN gctSTRING Name,
1243 IN gcsFDPRIVATE_PTR Private,
1244 OUT gctINT *Fd
1245 );
1246
1247gceSTATUS
1248gckKERNEL_AllocateVirtualCommandBuffer(
1249 IN gckKERNEL Kernel,
1250 IN gctBOOL InUserSpace,
1251 IN OUT gctSIZE_T * Bytes,
1252 OUT gctPHYS_ADDR * Physical,
1253 OUT gctPOINTER * Logical
1254 );
1255
1256gceSTATUS
1257gckKERNEL_DestroyVirtualCommandBuffer(
1258 IN gckKERNEL Kernel,
1259 IN gctSIZE_T Bytes,
1260 IN gctPHYS_ADDR Physical,
1261 IN gctPOINTER Logical
1262 );
1263
1264gceSTATUS
1265gckKERNEL_GetGPUAddress(
1266 IN gckKERNEL Kernel,
1267 IN gctPOINTER Logical,
1268 IN gctBOOL InUserSpace,
1269 IN gckVIRTUAL_COMMAND_BUFFER_PTR Buffer,
1270 OUT gctUINT32 * Address
1271 );
1272
1273gceSTATUS
1274gckKERNEL_QueryGPUAddress(
1275 IN gckKERNEL Kernel,
1276 IN gctUINT32 GpuAddress,
1277 OUT gckVIRTUAL_COMMAND_BUFFER_PTR * Buffer
1278 );
1279
1280gceSTATUS
1281gckKERNEL_AttachProcess(
1282 IN gckKERNEL Kernel,
1283 IN gctBOOL Attach
1284 );
1285
1286gceSTATUS
1287gckKERNEL_AttachProcessEx(
1288 IN gckKERNEL Kernel,
1289 IN gctBOOL Attach,
1290 IN gctUINT32 PID
1291 );
1292
1293#if gcdSECURE_USER
1294gceSTATUS
1295gckKERNEL_MapLogicalToPhysical(
1296 IN gckKERNEL Kernel,
1297 IN gcskSECURE_CACHE_PTR Cache,
1298 IN OUT gctPOINTER * Data
1299 );
1300
1301gceSTATUS
1302gckKERNEL_FlushTranslationCache(
1303 IN gckKERNEL Kernel,
1304 IN gcskSECURE_CACHE_PTR Cache,
1305 IN gctPOINTER Logical,
1306 IN gctSIZE_T Bytes
1307 );
1308#endif
1309
1310gceSTATUS
1311gckHARDWARE_QueryIdle(
1312 IN gckHARDWARE Hardware,
1313 OUT gctBOOL_PTR IsIdle
1314 );
1315
1316gceSTATUS
1317gckHARDWARE_AddressInHardwareFuncions(
1318 IN gckHARDWARE Hardware,
1319 IN gctUINT32 Address,
1320 OUT gctPOINTER *Pointer
1321 );
1322
1323
1324gceSTATUS
1325gckKERNEL_CreateShBuffer(
1326 IN gckKERNEL Kernel,
1327 IN gctUINT32 Size,
1328 OUT gctSHBUF * ShBuf
1329 );
1330
1331gceSTATUS
1332gckKERNEL_DestroyShBuffer(
1333 IN gckKERNEL Kernel,
1334 IN gctSHBUF ShBuf
1335 );
1336
1337gceSTATUS
1338gckKERNEL_MapShBuffer(
1339 IN gckKERNEL Kernel,
1340 IN gctSHBUF ShBuf
1341 );
1342
1343gceSTATUS
1344gckKERNEL_WriteShBuffer(
1345 IN gckKERNEL Kernel,
1346 IN gctSHBUF ShBuf,
1347 IN gctPOINTER UserData,
1348 IN gctUINT32 ByteCount
1349 );
1350
1351gceSTATUS
1352gckKERNEL_ReadShBuffer(
1353 IN gckKERNEL Kernel,
1354 IN gctSHBUF ShBuf,
1355 IN gctPOINTER UserData,
1356 IN gctUINT32 ByteCount,
1357 OUT gctUINT32 * BytesRead
1358 );
1359
1360
1361/******************************************************************************\
1362******************************* gckCONTEXT Object *******************************
1363\******************************************************************************/
1364
1365gceSTATUS
1366gckCONTEXT_Construct(
1367 IN gckOS Os,
1368 IN gckHARDWARE Hardware,
1369 IN gctUINT32 ProcessID,
1370 OUT gckCONTEXT * Context
1371 );
1372
1373gceSTATUS
1374gckCONTEXT_Destroy(
1375 IN gckCONTEXT Context
1376 );
1377
1378gceSTATUS
1379gckCONTEXT_Update(
1380 IN gckCONTEXT Context,
1381 IN gctUINT32 ProcessID,
1382 IN gcsSTATE_DELTA_PTR StateDelta
1383 );
1384
1385gceSTATUS
1386gckCONTEXT_MapBuffer(
1387 IN gckCONTEXT Context,
1388 OUT gctUINT32 *Physicals,
1389 OUT gctUINT64 *Logicals,
1390 OUT gctUINT32 *Bytes
1391 );
1392
1393#if gcdLINK_QUEUE_SIZE
1394void
1395gckLINKQUEUE_Enqueue(
1396 IN gckLINKQUEUE LinkQueue,
1397 IN gctUINT32 start,
1398 IN gctUINT32 end,
1399 IN gctUINT32 LinkLow,
1400 IN gctUINT32 LinkHigh
1401 );
1402
1403void
1404gckLINKQUEUE_GetData(
1405 IN gckLINKQUEUE LinkQueue,
1406 IN gctUINT32 Index,
1407 OUT gckLINKDATA * Data
1408 );
1409#endif
1410
1411gceSTATUS
1412gckENTRYQUEUE_Enqueue(
1413 IN gckKERNEL Kernel,
1414 IN gckENTRYQUEUE Queue,
1415 IN gctUINT32 physical,
1416 IN gctUINT32 bytes
1417 );
1418
1419gceSTATUS
1420gckENTRYQUEUE_Dequeue(
1421 IN gckENTRYQUEUE Queue,
1422 OUT gckENTRYDATA * Data
1423 );
1424
1425/******************************************************************************\
1426****************************** gckRECORDER Object ******************************
1427\******************************************************************************/
1428gceSTATUS
1429gckRECORDER_Construct(
1430 IN gckOS Os,
1431 IN gckHARDWARE Hardware,
1432 OUT gckRECORDER * Recorder
1433 );
1434
1435gceSTATUS
1436gckRECORDER_Destory(
1437 IN gckOS Os,
1438 IN gckRECORDER Recorder
1439 );
1440
1441void
1442gckRECORDER_AdvanceIndex(
1443 gckRECORDER Recorder,
1444 gctUINT64 CommitStamp
1445 );
1446
1447void
1448gckRECORDER_Record(
1449 gckRECORDER Recorder,
1450 gctUINT8_PTR CommandBuffer,
1451 gctUINT32 CommandBytes,
1452 gctUINT8_PTR ContextBuffer,
1453 gctUINT32 ContextBytes
1454 );
1455
1456void
1457gckRECORDER_Dump(
1458 gckRECORDER Recorder
1459 );
1460
1461gceSTATUS
1462gckRECORDER_UpdateMirror(
1463 gckRECORDER Recorder,
1464 gctUINT32 State,
1465 gctUINT32 Data
1466 );
1467
1468gceSTATUS
1469gckFENCE_Create(
1470 IN gckOS Os,
1471 IN gckKERNEL Kernel,
1472 OUT gckFENCE * Fence
1473 );
1474
1475gceSTATUS
1476gckFENCE_Destory(
1477 IN gckOS Os,
1478 OUT gckFENCE Fence
1479 );
1480
1481#ifdef __cplusplus
1482}
1483#endif
1484
1485#endif /* __gc_hal_kernel_h_ */
diff --git a/src/hal/kernel/gc_hal_kernel_command.c b/src/hal/kernel/gc_hal_kernel_command.c
new file mode 100755
index 0000000..d063400
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_command.c
@@ -0,0 +1,3366 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57#include "gc_hal_kernel_context.h"
58
59#define _GC_OBJ_ZONE gcvZONE_COMMAND
60
61/******************************************************************************\
62********************************* Support Code *********************************
63\******************************************************************************/
64
65/*******************************************************************************
66**
67** _NewQueue
68**
69** Allocate a new command queue.
70**
71** INPUT:
72**
73** gckCOMMAND Command
74** Pointer to an gckCOMMAND object.
75**
76** OUTPUT:
77**
78** gckCOMMAND Command
79** gckCOMMAND object has been updated with a new command queue.
80*/
81static gceSTATUS
82_NewQueue(
83 IN OUT gckCOMMAND Command
84 )
85{
86 gceSTATUS status;
87 gctINT currentIndex, newIndex;
88 gctPHYS_ADDR_T physical;
89
90 gcmkHEADER_ARG("Command=0x%x", Command);
91
92 /* Switch to the next command buffer. */
93 currentIndex = Command->index;
94 newIndex = (currentIndex + 1) % gcdCOMMAND_QUEUES;
95
96 /* Wait for availability. */
97#if gcdDUMP_COMMAND
98 gcmkPRINT("@[kernel.waitsignal]");
99#endif
100
101 gcmkONERROR(gckOS_WaitSignal(
102 Command->os,
103 Command->queues[newIndex].signal,
104 gcvINFINITE
105 ));
106
107#if gcmIS_DEBUG(gcdDEBUG_TRACE)
108 if (newIndex < currentIndex)
109 {
110 Command->wrapCount += 1;
111
112 gcmkTRACE_ZONE_N(
113 gcvLEVEL_INFO, gcvZONE_COMMAND,
114 2 * 4,
115 "%s(%d): queue array wrapped around.\n",
116 __FUNCTION__, __LINE__
117 );
118 }
119
120 gcmkTRACE_ZONE_N(
121 gcvLEVEL_INFO, gcvZONE_COMMAND,
122 3 * 4,
123 "%s(%d): total queue wrap arounds %d.\n",
124 __FUNCTION__, __LINE__, Command->wrapCount
125 );
126
127 gcmkTRACE_ZONE_N(
128 gcvLEVEL_INFO, gcvZONE_COMMAND,
129 3 * 4,
130 "%s(%d): switched to queue %d.\n",
131 __FUNCTION__, __LINE__, newIndex
132 );
133#endif
134
135 /* Update gckCOMMAND object with new command queue. */
136 Command->index = newIndex;
137 Command->newQueue = gcvTRUE;
138 Command->logical = Command->queues[newIndex].logical;
139 Command->address = Command->queues[newIndex].address;
140 Command->offset = 0;
141
142 gcmkONERROR(gckOS_GetPhysicalAddress(
143 Command->os,
144 Command->logical,
145 &physical
146 ));
147
148 gcmkSAFECASTPHYSADDRT(Command->physical, physical);
149
150 if (currentIndex != -1)
151 {
152 /* Mark the command queue as available. */
153 gcmkONERROR(gckEVENT_Signal(
154 Command->kernel->eventObj,
155 Command->queues[currentIndex].signal,
156 gcvKERNEL_COMMAND
157 ));
158 }
159
160 /* Success. */
161 gcmkFOOTER_ARG("Command->index=%d", Command->index);
162 return gcvSTATUS_OK;
163
164OnError:
165 /* Return the status. */
166 gcmkFOOTER();
167 return status;
168}
169
170static gceSTATUS
171_IncrementCommitAtom(
172 IN gckCOMMAND Command,
173 IN gctBOOL Increment
174 )
175{
176 gceSTATUS status;
177 gckHARDWARE hardware;
178 gctINT32 atomValue;
179 gctBOOL powerAcquired = gcvFALSE;
180
181 gcmkHEADER_ARG("Command=0x%x", Command);
182
183 /* Extract the gckHARDWARE and gckEVENT objects. */
184 hardware = Command->kernel->hardware;
185 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
186
187 /* Grab the power mutex. */
188 gcmkONERROR(gckOS_AcquireMutex(
189 Command->os, hardware->powerMutex, gcvINFINITE
190 ));
191 powerAcquired = gcvTRUE;
192
193 /* Increment the commit atom. */
194 if (Increment)
195 {
196 gcmkONERROR(gckOS_AtomIncrement(
197 Command->os, Command->atomCommit, &atomValue
198 ));
199 }
200 else
201 {
202 gcmkONERROR(gckOS_AtomDecrement(
203 Command->os, Command->atomCommit, &atomValue
204 ));
205 }
206
207 /* Release the power mutex. */
208 gcmkONERROR(gckOS_ReleaseMutex(
209 Command->os, hardware->powerMutex
210 ));
211 powerAcquired = gcvFALSE;
212
213 /* Success. */
214 gcmkFOOTER();
215 return gcvSTATUS_OK;
216
217OnError:
218 if (powerAcquired)
219 {
220 /* Release the power mutex. */
221 gcmkVERIFY_OK(gckOS_ReleaseMutex(
222 Command->os, hardware->powerMutex
223 ));
224 }
225
226 /* Return the status. */
227 gcmkFOOTER();
228 return status;
229}
230
231#if gcdSECURE_USER
232static gceSTATUS
233_ProcessHints(
234 IN gckCOMMAND Command,
235 IN gctUINT32 ProcessID,
236 IN gcoCMDBUF CommandBuffer
237 )
238{
239 gceSTATUS status = gcvSTATUS_OK;
240 gckKERNEL kernel;
241 gctBOOL needCopy = gcvFALSE;
242 gcskSECURE_CACHE_PTR cache;
243 gctUINT8_PTR commandBufferLogical;
244 gctUINT8_PTR hintedData;
245 gctUINT32_PTR hintArray;
246 gctUINT i, hintCount;
247
248 gcmkHEADER_ARG(
249 "Command=0x%08X ProcessID=%d CommandBuffer=0x%08X",
250 Command, ProcessID, CommandBuffer
251 );
252
253 /* Verify the arguments. */
254 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
255
256 /* Reset state array pointer. */
257 hintArray = gcvNULL;
258
259 /* Get the kernel object. */
260 kernel = Command->kernel;
261
262 /* Get the cache form the database. */
263 gcmkONERROR(gckKERNEL_GetProcessDBCache(kernel, ProcessID, &cache));
264
265 /* Determine the start of the command buffer. */
266 commandBufferLogical
267 = (gctUINT8_PTR) CommandBuffer->logical
268 + CommandBuffer->startOffset;
269
270 /* Determine the number of records in the state array. */
271 hintCount = CommandBuffer->hintArrayTail - CommandBuffer->hintArray;
272
273 /* Check wehther we need to copy the structures or not. */
274 gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
275
276 /* Get access to the state array. */
277 if (needCopy)
278 {
279 gctUINT copySize;
280
281 if (Command->hintArrayAllocated &&
282 (Command->hintArraySize < CommandBuffer->hintArraySize))
283 {
284 gcmkONERROR(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
285 Command->hintArraySize = gcvFALSE;
286 }
287
288 if (!Command->hintArrayAllocated)
289 {
290 gctPOINTER pointer = gcvNULL;
291
292 gcmkONERROR(gckOS_Allocate(
293 Command->os,
294 CommandBuffer->hintArraySize,
295 &pointer
296 ));
297
298 Command->hintArray = gcmPTR_TO_UINT64(pointer);
299 Command->hintArrayAllocated = gcvTRUE;
300 Command->hintArraySize = CommandBuffer->hintArraySize;
301 }
302
303 hintArray = gcmUINT64_TO_PTR(Command->hintArray);
304 copySize = hintCount * gcmSIZEOF(gctUINT32);
305
306 gcmkONERROR(gckOS_CopyFromUserData(
307 Command->os,
308 hintArray,
309 gcmUINT64_TO_PTR(CommandBuffer->hintArray),
310 copySize
311 ));
312 }
313 else
314 {
315 gctPOINTER pointer = gcvNULL;
316
317 gcmkONERROR(gckOS_MapUserPointer(
318 Command->os,
319 gcmUINT64_TO_PTR(CommandBuffer->hintArray),
320 CommandBuffer->hintArraySize,
321 &pointer
322 ));
323
324 hintArray = pointer;
325 }
326
327 /* Scan through the buffer. */
328 for (i = 0; i < hintCount; i += 1)
329 {
330 /* Determine the location of the hinted data. */
331 hintedData = commandBufferLogical + hintArray[i];
332
333 /* Map handle into physical address. */
334 gcmkONERROR(gckKERNEL_MapLogicalToPhysical(
335 kernel, cache, (gctPOINTER) hintedData
336 ));
337 }
338
339OnError:
340 /* Get access to the state array. */
341 if (!needCopy && (hintArray != gcvNULL))
342 {
343 gcmkVERIFY_OK(gckOS_UnmapUserPointer(
344 Command->os,
345 gcmUINT64_TO_PTR(CommandBuffer->hintArray),
346 CommandBuffer->hintArraySize,
347 hintArray
348 ));
349 }
350
351 /* Return the status. */
352 gcmkFOOTER();
353 return status;
354}
355#endif
356
357static gceSTATUS
358_FlushMMU(
359 IN gckCOMMAND Command
360 )
361{
362 gceSTATUS status;
363 gctUINT32 oldValue;
364 gckHARDWARE hardware = Command->kernel->hardware;
365 gctBOOL pause = gcvFALSE;
366
367 gctUINT8_PTR pointer;
368 gctUINT32 eventBytes;
369 gctUINT32 endBytes;
370 gctUINT32 bufferSize;
371 gctUINT32 executeBytes;
372 gctUINT32 waitLinkBytes;
373
374 gcmkONERROR(gckOS_AtomicExchange(Command->os,
375 hardware->pageTableDirty,
376 0,
377 &oldValue));
378
379 if (oldValue)
380 {
381 /* Page Table is upated, flush mmu before commit. */
382 gcmkONERROR(gckHARDWARE_FlushMMU(hardware));
383
384 if ((oldValue & gcvPAGE_TABLE_DIRTY_BIT_FE)
385 && (hardware->endAfterFlushMmuCache)
386 )
387 {
388 pause = gcvTRUE;
389 }
390 }
391
392 if (pause)
393 {
394 /* Query size. */
395 gcmkONERROR(gckHARDWARE_Event(hardware, gcvNULL, 0, gcvKERNEL_PIXEL, &eventBytes));
396 gcmkONERROR(gckHARDWARE_End(hardware, gcvNULL, &endBytes));
397
398 executeBytes = eventBytes + endBytes;
399
400 gcmkONERROR(gckHARDWARE_WaitLink(
401 hardware,
402 gcvNULL,
403 Command->offset + executeBytes,
404 &waitLinkBytes,
405 gcvNULL,
406 gcvNULL
407 ));
408
409 /* Reserve space. */
410 gcmkONERROR(gckCOMMAND_Reserve(
411 Command,
412 executeBytes,
413 (gctPOINTER *)&pointer,
414 &bufferSize
415 ));
416
417 /* Append EVENT(29). */
418 gcmkONERROR(gckHARDWARE_Event(
419 hardware,
420 pointer,
421 29,
422 gcvKERNEL_PIXEL,
423 &eventBytes
424 ));
425
426 /* Append END. */
427 pointer += eventBytes;
428 gcmkONERROR(gckHARDWARE_End(hardware, pointer, &endBytes));
429
430 /* Store address to queue. */
431 gcmkONERROR(gckENTRYQUEUE_Enqueue(
432 Command->kernel,
433 &Command->queue,
434 Command->address + Command->offset + executeBytes,
435 waitLinkBytes
436 ));
437
438 gcmkONERROR(gckCOMMAND_Execute(Command, executeBytes));
439 }
440
441 return gcvSTATUS_OK;
442OnError:
443 return status;
444}
445
446static void
447_DumpBuffer(
448 IN gctPOINTER Buffer,
449 IN gctUINT32 GpuAddress,
450 IN gctSIZE_T Size
451 )
452{
453 gctSIZE_T i, line, left;
454 gctUINT32_PTR data = Buffer;
455
456 line = Size / 32;
457 left = Size % 32;
458
459 for (i = 0; i < line; i++)
460 {
461 gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X %08X %08X",
462 GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
463 data += 8;
464 GpuAddress += 8 * 4;
465 }
466
467 switch(left)
468 {
469 case 28:
470 gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X %08X",
471 GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
472 break;
473 case 24:
474 gcmkPRINT("%08X : %08X %08X %08X %08X %08X %08X",
475 GpuAddress, data[0], data[1], data[2], data[3], data[4], data[5]);
476 break;
477 case 20:
478 gcmkPRINT("%08X : %08X %08X %08X %08X %08X",
479 GpuAddress, data[0], data[1], data[2], data[3], data[4]);
480 break;
481 case 16:
482 gcmkPRINT("%08X : %08X %08X %08X %08X",
483 GpuAddress, data[0], data[1], data[2], data[3]);
484 break;
485 case 12:
486 gcmkPRINT("%08X : %08X %08X %08X",
487 GpuAddress, data[0], data[1], data[2]);
488 break;
489 case 8:
490 gcmkPRINT("%08X : %08X %08X",
491 GpuAddress, data[0], data[1]);
492 break;
493 case 4:
494 gcmkPRINT("%08X : %08X",
495 GpuAddress, data[0]);
496 break;
497 default:
498 break;
499 }
500}
501
502static void
503_DumpKernelCommandBuffer(
504 IN gckCOMMAND Command
505 )
506{
507 gctINT i;
508 gctUINT64 physical = 0;
509 gctUINT32 address;
510 gctPOINTER entry = gcvNULL;
511
512 for (i = 0; i < gcdCOMMAND_QUEUES; i++)
513 {
514 entry = Command->queues[i].logical;
515
516 gckOS_GetPhysicalAddress(Command->os, entry, &physical);
517
518 gcmkPRINT("Kernel command buffer %d\n", i);
519
520 gcmkSAFECASTPHYSADDRT(address, physical);
521
522 _DumpBuffer(entry, address, Command->pageSize);
523 }
524}
525
526/******************************************************************************\
527****************************** gckCOMMAND API Code ******************************
528\******************************************************************************/
529
530/*******************************************************************************
531**
532** gckCOMMAND_Construct
533**
534** Construct a new gckCOMMAND object.
535**
536** INPUT:
537**
538** gckKERNEL Kernel
539** Pointer to an gckKERNEL object.
540**
541** OUTPUT:
542**
543** gckCOMMAND * Command
544** Pointer to a variable that will hold the pointer to the gckCOMMAND
545** object.
546*/
547gceSTATUS
548gckCOMMAND_Construct(
549 IN gckKERNEL Kernel,
550 OUT gckCOMMAND * Command
551 )
552{
553 gckOS os;
554 gckCOMMAND command = gcvNULL;
555 gceSTATUS status;
556 gctINT i;
557 gctPOINTER pointer = gcvNULL;
558 gctSIZE_T pageSize;
559
560 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
561
562 /* Verify the arguments. */
563 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
564 gcmkVERIFY_ARGUMENT(Command != gcvNULL);
565
566 /* Extract the gckOS object. */
567 os = Kernel->os;
568
569 /* Allocate the gckCOMMAND structure. */
570 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckCOMMAND), &pointer));
571 command = pointer;
572
573 /* Reset the entire object. */
574 gcmkONERROR(gckOS_ZeroMemory(command, gcmSIZEOF(struct _gckCOMMAND)));
575
576 /* Initialize the gckCOMMAND object.*/
577 command->object.type = gcvOBJ_COMMAND;
578 command->kernel = Kernel;
579 command->os = os;
580
581 /* Get the command buffer requirements. */
582 gcmkONERROR(gckHARDWARE_QueryCommandBuffer(
583 Kernel->hardware,
584 &command->alignment,
585 &command->reservedHead,
586 &command->reservedTail
587 ));
588
589 /* Create the command queue mutex. */
590 gcmkONERROR(gckOS_CreateMutex(os, &command->mutexQueue));
591
592 /* Create the context switching mutex. */
593 gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContext));
594
595#if VIVANTE_PROFILER_CONTEXT
596 /* Create the context switching mutex. */
597 gcmkONERROR(gckOS_CreateMutex(os, &command->mutexContextSeq));
598#endif
599
600 /* Create the power management semaphore. */
601 gcmkONERROR(gckOS_CreateSemaphore(os, &command->powerSemaphore));
602
603 /* Create the commit atom. */
604 gcmkONERROR(gckOS_AtomConstruct(os, &command->atomCommit));
605
606 /* Get the page size from teh OS. */
607 gcmkONERROR(gckOS_GetPageSize(os, &pageSize));
608
609 gcmkSAFECASTSIZET(command->pageSize, pageSize);
610
611 /* Get process ID. */
612 gcmkONERROR(gckOS_GetProcessID(&command->kernelProcessID));
613
614 /* Set hardware to pipe 0. */
615 command->pipeSelect = gcvPIPE_INVALID;
616
617 /* Pre-allocate the command queues. */
618 for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
619 {
620 gcmkONERROR(gckOS_AllocateNonPagedMemory(
621 os,
622 gcvFALSE,
623 &pageSize,
624 &command->queues[i].physical,
625 &command->queues[i].logical
626 ));
627
628 gcmkONERROR(gckHARDWARE_ConvertLogical(
629 Kernel->hardware,
630 command->queues[i].logical,
631 gcvFALSE,
632 &command->queues[i].address
633 ));
634
635 gcmkONERROR(gckOS_CreateSignal(
636 os, gcvFALSE, &command->queues[i].signal
637 ));
638
639 gcmkONERROR(gckOS_Signal(
640 os, command->queues[i].signal, gcvTRUE
641 ));
642 }
643
644#if gcdRECORD_COMMAND
645 gcmkONERROR(gckRECORDER_Construct(os, Kernel->hardware, &command->recorder));
646#endif
647
648 gcmkONERROR(gckFENCE_Create(
649 os, Kernel, &command->fence
650 ));
651
652 /* No command queue in use yet. */
653 command->index = -1;
654 command->logical = gcvNULL;
655 command->newQueue = gcvFALSE;
656
657 /* Command is not yet running. */
658 command->running = gcvFALSE;
659
660 /* Command queue is idle. */
661 command->idle = gcvTRUE;
662
663 /* Commit stamp is zero. */
664 command->commitStamp = 0;
665
666 /* END event signal not created. */
667 command->endEventSignal = gcvNULL;
668
669 command->queue.front = 0;
670 command->queue.rear = 0;
671 command->queue.count = 0;
672
673 /* Return pointer to the gckCOMMAND object. */
674 *Command = command;
675
676 /* Success. */
677 gcmkFOOTER_ARG("*Command=0x%x", *Command);
678 return gcvSTATUS_OK;
679
680OnError:
681 /* Roll back. */
682 if (command != gcvNULL)
683 {
684 gcmkVERIFY_OK(gckCOMMAND_Destroy(command));
685 }
686
687 /* Return the status. */
688 gcmkFOOTER();
689 return status;
690}
691
692/*******************************************************************************
693**
694** gckCOMMAND_Destroy
695**
696** Destroy an gckCOMMAND object.
697**
698** INPUT:
699**
700** gckCOMMAND Command
701** Pointer to an gckCOMMAND object to destroy.
702**
703** OUTPUT:
704**
705** Nothing.
706*/
707gceSTATUS
708gckCOMMAND_Destroy(
709 IN gckCOMMAND Command
710 )
711{
712 gctINT i;
713
714 gcmkHEADER_ARG("Command=0x%x", Command);
715
716 /* Verify the arguments. */
717 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
718
719 /* Stop the command queue. */
720 gcmkVERIFY_OK(gckCOMMAND_Stop(Command, gcvFALSE));
721
722 for (i = 0; i < gcdCOMMAND_QUEUES; ++i)
723 {
724 if (Command->queues[i].signal)
725 {
726 gcmkVERIFY_OK(gckOS_DestroySignal(
727 Command->os, Command->queues[i].signal
728 ));
729 }
730
731 if (Command->queues[i].logical)
732 {
733 gcmkVERIFY_OK(gckOS_FreeNonPagedMemory(
734 Command->os,
735 Command->pageSize,
736 Command->queues[i].physical,
737 Command->queues[i].logical
738 ));
739 }
740 }
741
742 /* END event signal. */
743 if (Command->endEventSignal != gcvNULL)
744 {
745 gcmkVERIFY_OK(gckOS_DestroySignal(
746 Command->os, Command->endEventSignal
747 ));
748 }
749
750 if (Command->mutexContext)
751 {
752 /* Delete the context switching mutex. */
753 gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContext));
754 }
755
756#if VIVANTE_PROFILER_CONTEXT
757 if (Command->mutexContextSeq != gcvNULL)
758 gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexContextSeq));
759#endif
760
761 if (Command->mutexQueue)
762 {
763 /* Delete the command queue mutex. */
764 gcmkVERIFY_OK(gckOS_DeleteMutex(Command->os, Command->mutexQueue));
765 }
766
767 if (Command->powerSemaphore)
768 {
769 /* Destroy the power management semaphore. */
770 gcmkVERIFY_OK(gckOS_DestroySemaphore(Command->os, Command->powerSemaphore));
771 }
772
773 if (Command->atomCommit)
774 {
775 /* Destroy the commit atom. */
776 gcmkVERIFY_OK(gckOS_AtomDestroy(Command->os, Command->atomCommit));
777 }
778
779#if gcdSECURE_USER
780 /* Free state array. */
781 if (Command->hintArrayAllocated)
782 {
783 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, gcmUINT64_TO_PTR(Command->hintArray)));
784 Command->hintArrayAllocated = gcvFALSE;
785 }
786#endif
787
788#if gcdRECORD_COMMAND
789 gckRECORDER_Destory(Command->os, Command->recorder);
790#endif
791
792 if (Command->stateMap)
793 {
794 gcmkOS_SAFE_FREE(Command->os, Command->stateMap);
795 }
796
797 if (Command->fence)
798 {
799 gcmkVERIFY_OK(gckFENCE_Destory(Command->os, Command->fence));
800 }
801
802 /* Mark object as unknown. */
803 Command->object.type = gcvOBJ_UNKNOWN;
804
805 /* Free the gckCOMMAND object. */
806 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Command->os, Command));
807
808 /* Success. */
809 gcmkFOOTER_NO();
810 return gcvSTATUS_OK;
811}
812
813/*******************************************************************************
814**
815** gckCOMMAND_EnterCommit
816**
817** Acquire command queue synchronization objects.
818**
819** INPUT:
820**
821** gckCOMMAND Command
822** Pointer to an gckCOMMAND object to destroy.
823**
824** gctBOOL FromPower
825** Determines whether the call originates from inside the power
826** management or not.
827**
828** OUTPUT:
829**
830** Nothing.
831*/
832gceSTATUS
833gckCOMMAND_EnterCommit(
834 IN gckCOMMAND Command,
835 IN gctBOOL FromPower
836 )
837{
838 gceSTATUS status;
839 gckHARDWARE hardware;
840 gctBOOL atomIncremented = gcvFALSE;
841 gctBOOL semaAcquired = gcvFALSE;
842
843 gcmkHEADER_ARG("Command=0x%x", Command);
844
845 /* Extract the gckHARDWARE and gckEVENT objects. */
846 hardware = Command->kernel->hardware;
847 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
848
849 if (!FromPower)
850 {
851 /* Increment COMMIT atom to let power management know that a commit is
852 ** in progress. */
853 gcmkONERROR(_IncrementCommitAtom(Command, gcvTRUE));
854 atomIncremented = gcvTRUE;
855
856 /* Notify the system the GPU has a commit. */
857 gcmkONERROR(gckOS_Broadcast(Command->os,
858 hardware,
859 gcvBROADCAST_GPU_COMMIT));
860
861 /* Acquire the power management semaphore. */
862 gcmkONERROR(gckOS_AcquireSemaphore(Command->os,
863 Command->powerSemaphore));
864 semaAcquired = gcvTRUE;
865 }
866
867 /* Grab the conmmand queue mutex. */
868 gcmkONERROR(gckOS_AcquireMutex(Command->os,
869 Command->mutexQueue,
870 gcvINFINITE));
871
872 /* Success. */
873 gcmkFOOTER();
874 return gcvSTATUS_OK;
875
876OnError:
877 if (semaAcquired)
878 {
879 /* Release the power management semaphore. */
880 gcmkVERIFY_OK(gckOS_ReleaseSemaphore(
881 Command->os, Command->powerSemaphore
882 ));
883 }
884
885 if (atomIncremented)
886 {
887 /* Decrement the commit atom. */
888 gcmkVERIFY_OK(_IncrementCommitAtom(
889 Command, gcvFALSE
890 ));
891 }
892
893 /* Return the status. */
894 gcmkFOOTER();
895 return status;
896}
897
898/*******************************************************************************
899**
900** gckCOMMAND_ExitCommit
901**
902** Release command queue synchronization objects.
903**
904** INPUT:
905**
906** gckCOMMAND Command
907** Pointer to an gckCOMMAND object to destroy.
908**
909** gctBOOL FromPower
910** Determines whether the call originates from inside the power
911** management or not.
912**
913** OUTPUT:
914**
915** Nothing.
916*/
917gceSTATUS
918gckCOMMAND_ExitCommit(
919 IN gckCOMMAND Command,
920 IN gctBOOL FromPower
921 )
922{
923 gceSTATUS status;
924
925 gcmkHEADER_ARG("Command=0x%x", Command);
926
927 /* Release the power mutex. */
928 gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexQueue));
929
930 if (!FromPower)
931 {
932 /* Release the power management semaphore. */
933 gcmkONERROR(gckOS_ReleaseSemaphore(Command->os,
934 Command->powerSemaphore));
935
936 /* Decrement the commit atom. */
937 gcmkONERROR(_IncrementCommitAtom(Command, gcvFALSE));
938 }
939
940 /* Success. */
941 gcmkFOOTER();
942 return gcvSTATUS_OK;
943
944OnError:
945 /* Return the status. */
946 gcmkFOOTER();
947 return status;
948}
949
950/*******************************************************************************
951**
952** gckCOMMAND_Start
953**
954** Start up the command queue.
955**
956** INPUT:
957**
958** gckCOMMAND Command
959** Pointer to an gckCOMMAND object to start.
960**
961** OUTPUT:
962**
963** Nothing.
964*/
965gceSTATUS
966gckCOMMAND_Start(
967 IN gckCOMMAND Command
968 )
969{
970 gceSTATUS status;
971 gckHARDWARE hardware;
972 gctUINT32 waitOffset = 0;
973 gctUINT32 waitLinkBytes;
974
975 gcmkHEADER_ARG("Command=0x%x", Command);
976
977 /* Verify the arguments. */
978 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
979
980 if (Command->running)
981 {
982 /* Command queue already running. */
983 gcmkFOOTER_NO();
984 return gcvSTATUS_OK;
985 }
986
987 /* Extract the gckHARDWARE object. */
988 hardware = Command->kernel->hardware;
989 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
990
991 if (Command->logical == gcvNULL)
992 {
993 /* Start at beginning of a new queue. */
994 gcmkONERROR(_NewQueue(Command));
995 }
996
997 /* Start at beginning of page. */
998 Command->offset = 0;
999
1000 /* Set abvailable number of bytes for WAIT/LINK command sequence. */
1001 waitLinkBytes = Command->pageSize;
1002
1003 /* Append WAIT/LINK. */
1004 gcmkONERROR(gckHARDWARE_WaitLink(
1005 hardware,
1006 Command->logical,
1007 0,
1008 &waitLinkBytes,
1009 &waitOffset,
1010 &Command->waitSize
1011 ));
1012
1013 Command->waitLogical = (gctUINT8_PTR) Command->logical + waitOffset;
1014 Command->waitPhysical = Command->physical + waitOffset;
1015
1016#if gcdNONPAGED_MEMORY_CACHEABLE
1017 /* Flush the cache for the wait/link. */
1018 gcmkONERROR(gckOS_CacheClean(
1019 Command->os,
1020 Command->kernelProcessID,
1021 gcvNULL,
1022 (gctUINT32)Command->physical,
1023 Command->logical,
1024 waitLinkBytes
1025 ));
1026#endif
1027
1028 /* Adjust offset. */
1029 Command->offset = waitLinkBytes;
1030 Command->newQueue = gcvFALSE;
1031
1032 /* Enable command processor. */
1033 gcmkONERROR(gckHARDWARE_Execute(
1034 hardware,
1035 Command->address,
1036 waitLinkBytes
1037 ));
1038
1039 /* Command queue is running. */
1040 Command->running = gcvTRUE;
1041
1042 /* Success. */
1043 gcmkFOOTER_NO();
1044 return gcvSTATUS_OK;
1045
1046OnError:
1047 /* Return the status. */
1048 gcmkFOOTER();
1049 return status;
1050}
1051
1052/*******************************************************************************
1053**
1054** gckCOMMAND_Stop
1055**
1056** Stop the command queue.
1057**
1058** INPUT:
1059**
1060** gckCOMMAND Command
1061** Pointer to an gckCOMMAND object to stop.
1062**
1063** OUTPUT:
1064**
1065** Nothing.
1066*/
1067gceSTATUS
1068gckCOMMAND_Stop(
1069 IN gckCOMMAND Command,
1070 IN gctBOOL FromRecovery
1071 )
1072{
1073 gckHARDWARE hardware;
1074 gceSTATUS status;
1075 gctUINT32 idle;
1076
1077 gcmkHEADER_ARG("Command=0x%x", Command);
1078
1079 /* Verify the arguments. */
1080 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
1081
1082 if (!Command->running)
1083 {
1084 /* Command queue is not running. */
1085 gcmkFOOTER_NO();
1086 return gcvSTATUS_OK;
1087 }
1088
1089 /* Extract the gckHARDWARE object. */
1090 hardware = Command->kernel->hardware;
1091 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
1092
1093 if (gckHARDWARE_IsFeatureAvailable(hardware,
1094 gcvFEATURE_END_EVENT) == gcvSTATUS_TRUE)
1095 {
1096 /* Allocate the signal. */
1097 if (Command->endEventSignal == gcvNULL)
1098 {
1099 gcmkONERROR(gckOS_CreateSignal(Command->os,
1100 gcvTRUE,
1101 &Command->endEventSignal));
1102 }
1103
1104 /* Append the END EVENT command to trigger the signal. */
1105 gcmkONERROR(gckEVENT_Stop(Command->kernel->eventObj,
1106 Command->kernelProcessID,
1107 Command->waitPhysical,
1108 Command->waitLogical,
1109 Command->endEventSignal,
1110 &Command->waitSize));
1111 }
1112 else
1113 {
1114 /* Replace last WAIT with END. */
1115 gcmkONERROR(gckHARDWARE_End(
1116 hardware, Command->waitLogical, &Command->waitSize
1117 ));
1118
1119
1120 /* Update queue tail pointer. */
1121 gcmkONERROR(gckHARDWARE_UpdateQueueTail(Command->kernel->hardware,
1122 Command->logical,
1123 Command->offset));
1124
1125#if gcdNONPAGED_MEMORY_CACHEABLE
1126 /* Flush the cache for the END. */
1127 gcmkONERROR(gckOS_CacheClean(
1128 Command->os,
1129 Command->kernelProcessID,
1130 gcvNULL,
1131 (gctUINT32)Command->waitPhysical,
1132 Command->waitLogical,
1133 Command->waitSize
1134 ));
1135#endif
1136
1137 /* Wait for idle. */
1138 gcmkONERROR(gckHARDWARE_GetIdle(hardware, !FromRecovery, &idle));
1139 }
1140
1141 /* Command queue is no longer running. */
1142 Command->running = gcvFALSE;
1143
1144 /* Success. */
1145 gcmkFOOTER_NO();
1146 return gcvSTATUS_OK;
1147
1148OnError:
1149 /* Return the status. */
1150 gcmkFOOTER();
1151 return status;
1152}
1153
1154/*******************************************************************************
1155**
1156** gckCOMMAND_Commit
1157**
1158** Commit a command buffer to the command queue.
1159**
1160** INPUT:
1161**
1162** gckCOMMAND Command
1163** Pointer to a gckCOMMAND object.
1164**
1165** gckCONTEXT Context
1166** Pointer to a gckCONTEXT object.
1167**
1168** gcoCMDBUF CommandBuffer
1169** Pointer to a gcoCMDBUF object.
1170**
1171** gcsSTATE_DELTA_PTR StateDelta
1172** Pointer to the state delta.
1173**
1174** gctUINT32 ProcessID
1175** Current process ID.
1176**
1177** OUTPUT:
1178**
1179** Nothing.
1180*/
1181gceSTATUS
1182gckCOMMAND_Commit(
1183 IN gckCOMMAND Command,
1184 IN gckCONTEXT Context,
1185 IN gcoCMDBUF CommandBuffer,
1186 IN gcsSTATE_DELTA_PTR StateDelta,
1187 IN gcsQUEUE_PTR EventQueue,
1188 IN gctUINT32 ProcessID
1189 )
1190{
1191 gceSTATUS status;
1192 gctBOOL commitEntered = gcvFALSE;
1193 gctBOOL contextAcquired = gcvFALSE;
1194 gckHARDWARE hardware;
1195 gctBOOL needCopy = gcvFALSE;
1196 gcsQUEUE_PTR eventRecord = gcvNULL;
1197 gcsQUEUE _eventRecord;
1198 gcsQUEUE_PTR nextEventRecord;
1199 gctBOOL commandBufferMapped = gcvFALSE;
1200 gcoCMDBUF commandBufferObject = gcvNULL;
1201 gctBOOL stall = gcvFALSE;
1202
1203#if !gcdNULL_DRIVER
1204 gcsCONTEXT_PTR contextBuffer;
1205 struct _gcoCMDBUF _commandBufferObject;
1206 gctPHYS_ADDR_T commandBufferPhysical;
1207 gctUINT8_PTR commandBufferLogical = gcvNULL;
1208 gctUINT32 commandBufferAddress = 0;
1209 gctUINT8_PTR commandBufferLink = gcvNULL;
1210 gctUINT commandBufferSize;
1211 gctSIZE_T nopBytes;
1212 gctUINT32 pipeBytes;
1213 gctUINT32 linkBytes;
1214 gctSIZE_T bytes;
1215 gctUINT32 offset;
1216#if gcdNONPAGED_MEMORY_CACHEABLE
1217 gctPHYS_ADDR entryPhysical;
1218#endif
1219 gctPOINTER entryLogical;
1220 gctUINT32 entryAddress;
1221 gctUINT32 entryBytes;
1222#if gcdNONPAGED_MEMORY_CACHEABLE
1223 gctPHYS_ADDR exitPhysical;
1224#endif
1225 gctPOINTER exitLogical;
1226 gctUINT32 exitAddress;
1227 gctUINT32 exitBytes;
1228 gctUINT32 waitLinkPhysical;
1229 gctPOINTER waitLinkLogical;
1230 gctUINT32 waitLinkAddress;
1231 gctUINT32 waitLinkBytes;
1232 gctUINT32 waitPhysical;
1233 gctPOINTER waitLogical;
1234 gctUINT32 waitOffset;
1235 gctUINT32 waitSize;
1236
1237#ifdef __QNXNTO__
1238 gctPOINTER userCommandBufferLogical = gcvNULL;
1239 gctBOOL userCommandBufferLogicalMapped = gcvFALSE;
1240 gctPOINTER userCommandBufferLink = gcvNULL;
1241 gctBOOL userCommandBufferLinkMapped = gcvFALSE;
1242#endif
1243
1244#if gcdPROCESS_ADDRESS_SPACE
1245 gctSIZE_T mmuConfigureBytes;
1246 gctPOINTER mmuConfigureLogical = gcvNULL;
1247 gctUINT32 mmuConfigureAddress;
1248 gctPOINTER mmuConfigurePhysical = 0;
1249 gctSIZE_T mmuConfigureWaitLinkOffset;
1250 gckMMU mmu;
1251 gctSIZE_T reservedBytes;
1252 gctUINT32 oldValue;
1253#endif
1254
1255#if gcdDUMP_COMMAND
1256 gctPOINTER contextDumpLogical = gcvNULL;
1257 gctSIZE_T contextDumpBytes = 0;
1258 gctPOINTER bufferDumpLogical = gcvNULL;
1259 gctSIZE_T bufferDumpBytes = 0;
1260# endif
1261#endif
1262
1263#if VIVANTE_PROFILER_CONTEXT
1264 gctBOOL sequenceAcquired = gcvFALSE;
1265#endif
1266
1267 gctPOINTER pointer = gcvNULL;
1268
1269
1270 gctUINT32 exitLinkLow = 0, exitLinkHigh = 0;
1271 gctUINT32 entryLinkLow = 0, entryLinkHigh = 0;
1272 gctUINT32 commandLinkLow = 0, commandLinkHigh = 0;
1273
1274 gckVIRTUAL_COMMAND_BUFFER_PTR virtualCommandBuffer = gcvNULL;
1275
1276 gcmkHEADER_ARG(
1277 "Command=0x%x CommandBuffer=0x%x ProcessID=%d",
1278 Command, CommandBuffer, ProcessID
1279 );
1280
1281 /* Verify the arguments. */
1282 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
1283
1284 if (Command->kernel->hardware->type== gcvHARDWARE_2D)
1285 {
1286 /* There is no context for 2D. */
1287 Context = gcvNULL;
1288 }
1289
1290#if gcdPROCESS_ADDRESS_SPACE
1291 gcmkONERROR(gckKERNEL_GetProcessMMU(Command->kernel, &mmu));
1292
1293 gcmkONERROR(gckOS_AtomicExchange(Command->os,
1294 mmu->pageTableDirty[Command->kernel->core],
1295 0,
1296 &oldValue));
1297#else
1298#endif
1299
1300#if VIVANTE_PROFILER_CONTEXT
1301 if((Command->kernel->hardware->gpuProfiler) && (Command->kernel->profileEnable))
1302 {
1303 /* Acquire the context sequnence mutex. */
1304 gcmkONERROR(gckOS_AcquireMutex(
1305 Command->os, Command->mutexContextSeq, gcvINFINITE
1306 ));
1307 sequenceAcquired = gcvTRUE;
1308 }
1309#endif
1310
1311 /* Acquire the command queue. */
1312 gcmkONERROR(gckCOMMAND_EnterCommit(Command, gcvFALSE));
1313 commitEntered = gcvTRUE;
1314
1315 /* Acquire the context switching mutex. */
1316 gcmkONERROR(gckOS_AcquireMutex(
1317 Command->os, Command->mutexContext, gcvINFINITE
1318 ));
1319 contextAcquired = gcvTRUE;
1320
1321 /* Extract the gckHARDWARE and gckEVENT objects. */
1322 hardware = Command->kernel->hardware;
1323
1324 /* Check wehther we need to copy the structures or not. */
1325 gcmkONERROR(gckOS_QueryNeedCopy(Command->os, ProcessID, &needCopy));
1326
1327#if gcdNULL_DRIVER
1328 /* Context switch required? */
1329 if ((Context != gcvNULL) && (Command->currContext != Context))
1330 {
1331 /* Yes, merge in the deltas. */
1332 gckCONTEXT_Update(Context, ProcessID, StateDelta);
1333
1334 /* Update the current context. */
1335 Command->currContext = Context;
1336 }
1337#else
1338 if (needCopy)
1339 {
1340 commandBufferObject = &_commandBufferObject;
1341
1342 gcmkONERROR(gckOS_CopyFromUserData(
1343 Command->os,
1344 commandBufferObject,
1345 CommandBuffer,
1346 gcmSIZEOF(struct _gcoCMDBUF)
1347 ));
1348
1349 gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
1350 }
1351 else
1352 {
1353 gcmkONERROR(gckOS_MapUserPointer(
1354 Command->os,
1355 CommandBuffer,
1356 gcmSIZEOF(struct _gcoCMDBUF),
1357 &pointer
1358 ));
1359
1360 commandBufferObject = pointer;
1361
1362 gcmkVERIFY_OBJECT(commandBufferObject, gcvOBJ_COMMANDBUFFER);
1363 commandBufferMapped = gcvTRUE;
1364 }
1365
1366 /* Query the size of NOP command. */
1367 gcmkONERROR(gckHARDWARE_Nop(
1368 hardware, gcvNULL, &nopBytes
1369 ));
1370
1371 /* Query the size of pipe select command sequence. */
1372 gcmkONERROR(gckHARDWARE_PipeSelect(
1373 hardware, gcvNULL, gcvPIPE_3D, &pipeBytes
1374 ));
1375
1376 /* Query the size of LINK command. */
1377 gcmkONERROR(gckHARDWARE_Link(
1378 hardware, gcvNULL, 0, 0, &linkBytes, gcvNULL, gcvNULL
1379 ));
1380
1381
1382 /* Compute the command buffer entry and the size. */
1383 commandBufferLogical
1384 = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
1385 + commandBufferObject->startOffset;
1386
1387 /* Get the hardware address. */
1388 if (Command->kernel->virtualCommandBuffer)
1389 {
1390 gckKERNEL kernel = Command->kernel;
1391
1392 virtualCommandBuffer = gcmNAME_TO_PTR(commandBufferObject->physical);
1393
1394 if (virtualCommandBuffer == gcvNULL)
1395 {
1396 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
1397 }
1398
1399 gcmkONERROR(gckKERNEL_GetGPUAddress(
1400 Command->kernel,
1401 commandBufferLogical,
1402 gcvTRUE,
1403 virtualCommandBuffer,
1404 &commandBufferAddress
1405 ));
1406 }
1407 else
1408 {
1409 gcmkONERROR(gckHARDWARE_ConvertLogical(
1410 hardware,
1411 commandBufferLogical,
1412 gcvTRUE,
1413 &commandBufferAddress
1414 ));
1415 }
1416
1417 /* Get the physical address. */
1418 gcmkONERROR(gckOS_UserLogicalToPhysical(
1419 Command->os,
1420 commandBufferLogical,
1421 &commandBufferPhysical
1422 ));
1423
1424#ifdef __QNXNTO__
1425 userCommandBufferLogical = (gctPOINTER) commandBufferLogical;
1426
1427 gcmkONERROR(gckOS_MapUserPointer(
1428 Command->os,
1429 userCommandBufferLogical,
1430 0,
1431 &pointer));
1432
1433 commandBufferLogical = pointer;
1434
1435 userCommandBufferLogicalMapped = gcvTRUE;
1436#endif
1437
1438 commandBufferSize
1439 = commandBufferObject->offset
1440 + Command->reservedTail
1441 - commandBufferObject->startOffset;
1442
1443 gcmkONERROR(_FlushMMU(Command));
1444
1445 /* Get the current offset. */
1446 offset = Command->offset;
1447
1448 /* Compute number of bytes left in current kernel command queue. */
1449 bytes = Command->pageSize - offset;
1450
1451
1452 /* Query the size of WAIT/LINK command sequence. */
1453 gcmkONERROR(gckHARDWARE_WaitLink(
1454 hardware,
1455 gcvNULL,
1456 offset,
1457 &waitLinkBytes,
1458 gcvNULL,
1459 gcvNULL
1460 ));
1461
1462 /* Is there enough space in the current command queue? */
1463 if (bytes < waitLinkBytes)
1464 {
1465 /* No, create a new one. */
1466 gcmkONERROR(_NewQueue(Command));
1467
1468 /* Get the new current offset. */
1469 offset = Command->offset;
1470
1471 /* Recompute the number of bytes in the new kernel command queue. */
1472 bytes = Command->pageSize - offset;
1473 gcmkASSERT(bytes >= waitLinkBytes);
1474 }
1475
1476 /* Compute the location if WAIT/LINK command sequence. */
1477 waitLinkPhysical = Command->physical + offset;
1478 waitLinkLogical = (gctUINT8_PTR) Command->logical + offset;
1479 waitLinkAddress = Command->address + offset;
1480
1481 /* Context switch required? */
1482 if (Context == gcvNULL)
1483 {
1484 /* See if we have to switch pipes for the command buffer. */
1485 if (commandBufferObject->entryPipe == Command->pipeSelect)
1486 {
1487 /* Skip pipe switching sequence. */
1488 offset = pipeBytes;
1489 }
1490 else
1491 {
1492 /* The current hardware and the entry command buffer pipes
1493 ** are different, switch to the correct pipe. */
1494 gcmkONERROR(gckHARDWARE_PipeSelect(
1495 Command->kernel->hardware,
1496 commandBufferLogical,
1497 commandBufferObject->entryPipe,
1498 &pipeBytes
1499 ));
1500
1501 /* Do not skip pipe switching sequence. */
1502 offset = 0;
1503 }
1504
1505 /* Compute the entry. */
1506#if gcdNONPAGED_MEMORY_CACHEABLE
1507 entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
1508#endif
1509 entryLogical = commandBufferLogical + offset;
1510 entryAddress = commandBufferAddress + offset;
1511 entryBytes = commandBufferSize - offset;
1512
1513 Command->currContext = gcvNULL;
1514 }
1515 else if (Command->currContext != Context)
1516 {
1517 /* Temporary disable context length oprimization. */
1518 Context->dirty = gcvTRUE;
1519
1520 /* Get the current context buffer. */
1521 contextBuffer = Context->buffer;
1522
1523 /* Yes, merge in the deltas. */
1524 gcmkONERROR(gckCONTEXT_Update(Context, ProcessID, StateDelta));
1525
1526 /* Determine context entry and exit points. */
1527 if (0)
1528 {
1529 /* Reset 2D dirty flag. */
1530 Context->dirty2D = gcvFALSE;
1531
1532 if (Context->dirty || commandBufferObject->using3D)
1533 {
1534 /***************************************************************
1535 ** SWITCHING CONTEXT: 2D and 3D are used.
1536 */
1537
1538 /* Reset 3D dirty flag. */
1539 Context->dirty3D = gcvFALSE;
1540
1541 /* Compute the entry. */
1542 if (Command->pipeSelect == gcvPIPE_2D)
1543 {
1544#if gcdNONPAGED_MEMORY_CACHEABLE
1545 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
1546#endif
1547 entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
1548 entryAddress = contextBuffer->address + pipeBytes;
1549 entryBytes = Context->bufferSize - pipeBytes;
1550 }
1551 else
1552 {
1553#if gcdNONPAGED_MEMORY_CACHEABLE
1554 entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
1555#endif
1556 entryLogical = (gctUINT8_PTR) contextBuffer->logical;
1557 entryAddress = contextBuffer->address;
1558 entryBytes = Context->bufferSize;
1559 }
1560
1561 /* See if we have to switch pipes between the context
1562 and command buffers. */
1563 if (commandBufferObject->entryPipe == gcvPIPE_3D)
1564 {
1565 /* Skip pipe switching sequence. */
1566 offset = pipeBytes;
1567 }
1568 else
1569 {
1570 /* The current hardware and the initial context pipes are
1571 different, switch to the correct pipe. */
1572 gcmkONERROR(gckHARDWARE_PipeSelect(
1573 Command->kernel->hardware,
1574 commandBufferLogical,
1575 commandBufferObject->entryPipe,
1576 &pipeBytes
1577 ));
1578
1579 /* Do not skip pipe switching sequence. */
1580 offset = 0;
1581 }
1582
1583 /* Ensure the NOP between 2D and 3D is in place so that the
1584 execution falls through from 2D to 3D. */
1585 gcmkONERROR(gckHARDWARE_Nop(
1586 hardware,
1587 contextBuffer->link2D,
1588 &nopBytes
1589 ));
1590
1591 /* Generate a LINK from the context buffer to
1592 the command buffer. */
1593 gcmkONERROR(gckHARDWARE_Link(
1594 hardware,
1595 contextBuffer->link3D,
1596 commandBufferAddress + offset,
1597 commandBufferSize - offset,
1598 &linkBytes,
1599 &commandLinkLow,
1600 &commandLinkHigh
1601 ));
1602
1603 /* Mark context as not dirty. */
1604 Context->dirty = gcvFALSE;
1605 }
1606 else
1607 {
1608 /***************************************************************
1609 ** SWITCHING CONTEXT: 2D only command buffer.
1610 */
1611
1612 /* Mark 3D as dirty. */
1613 Context->dirty3D = gcvTRUE;
1614
1615 /* Compute the entry. */
1616 if (Command->pipeSelect == gcvPIPE_2D)
1617 {
1618#if gcdNONPAGED_MEMORY_CACHEABLE
1619 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
1620#endif
1621 entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
1622 entryAddress = contextBuffer->address + pipeBytes;
1623 entryBytes = Context->entryOffset3D - pipeBytes;
1624 }
1625 else
1626 {
1627#if gcdNONPAGED_MEMORY_CACHEABLE
1628 entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
1629#endif
1630 entryLogical = (gctUINT8_PTR) contextBuffer->logical;
1631 entryAddress = contextBuffer->address;
1632 entryBytes = Context->entryOffset3D;
1633 }
1634
1635 /* Store the current context buffer. */
1636 Context->dirtyBuffer = contextBuffer;
1637
1638 /* See if we have to switch pipes between the context
1639 and command buffers. */
1640 if (commandBufferObject->entryPipe == gcvPIPE_2D)
1641 {
1642 /* Skip pipe switching sequence. */
1643 offset = pipeBytes;
1644 }
1645 else
1646 {
1647 /* The current hardware and the initial context pipes are
1648 different, switch to the correct pipe. */
1649 gcmkONERROR(gckHARDWARE_PipeSelect(
1650 Command->kernel->hardware,
1651 commandBufferLogical,
1652 commandBufferObject->entryPipe,
1653 &pipeBytes
1654 ));
1655
1656 /* Do not skip pipe switching sequence. */
1657 offset = 0;
1658 }
1659
1660 /* 3D is not used, generate a LINK from the end of 2D part of
1661 the context buffer to the command buffer. */
1662 gcmkONERROR(gckHARDWARE_Link(
1663 hardware,
1664 contextBuffer->link2D,
1665 commandBufferAddress + offset,
1666 commandBufferSize - offset,
1667 &linkBytes,
1668 &commandLinkLow,
1669 &commandLinkHigh
1670 ));
1671 }
1672 }
1673
1674 /* Not using 2D. */
1675 else
1676 {
1677
1678 /* Store the current context buffer. */
1679 Context->dirtyBuffer = contextBuffer;
1680
1681 if (Context->dirty || commandBufferObject->using3D)
1682 {
1683 /***************************************************************
1684 ** SWITCHING CONTEXT: 3D only command buffer.
1685 */
1686
1687 /* Reset 3D dirty flag. */
1688 Context->dirty3D = gcvFALSE;
1689
1690 /* Determine context buffer entry offset. */
1691 offset = (Command->pipeSelect == gcvPIPE_3D)
1692
1693 /* Skip pipe switching sequence. */
1694 ? Context->entryOffset3D + Context->pipeSelectBytes
1695
1696 /* Do not skip pipe switching sequence. */
1697 : Context->entryOffset3D;
1698
1699 /* Compute the entry. */
1700#if gcdNONPAGED_MEMORY_CACHEABLE
1701 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
1702#endif
1703 entryLogical = (gctUINT8_PTR) contextBuffer->logical + offset;
1704 entryAddress = contextBuffer->address + offset;
1705 entryBytes = Context->bufferSize - offset;
1706
1707 /* See if we have to switch pipes between the context
1708 and command buffers. */
1709 if (commandBufferObject->entryPipe == gcvPIPE_3D)
1710 {
1711 /* Skip pipe switching sequence. */
1712 offset = pipeBytes;
1713 }
1714 else
1715 {
1716 /* The current hardware and the initial context pipes are
1717 different, switch to the correct pipe. */
1718 gcmkONERROR(gckHARDWARE_PipeSelect(
1719 Command->kernel->hardware,
1720 commandBufferLogical,
1721 commandBufferObject->entryPipe,
1722 &pipeBytes
1723 ));
1724
1725 /* Do not skip pipe switching sequence. */
1726 offset = 0;
1727 }
1728
1729 /* Generate a LINK from the context buffer to
1730 the command buffer. */
1731 gcmkONERROR(gckHARDWARE_Link(
1732 hardware,
1733 contextBuffer->link3D,
1734 commandBufferAddress + offset,
1735 commandBufferSize - offset,
1736 &linkBytes,
1737 &commandLinkLow,
1738 &commandLinkHigh
1739 ));
1740 }
1741 else
1742 {
1743 /***************************************************************
1744 ** SWITCHING CONTEXT: "XD" command buffer - neither 2D nor 3D.
1745 */
1746
1747 /* Mark 3D as dirty. */
1748 Context->dirty3D = gcvTRUE;
1749
1750 /* Compute the entry. */
1751 if (Command->pipeSelect == gcvPIPE_3D)
1752 {
1753#if gcdNONPAGED_MEMORY_CACHEABLE
1754 entryPhysical
1755 = (gctUINT8_PTR) contextBuffer->physical
1756 + Context->entryOffsetXDFrom3D;
1757#endif
1758 entryLogical
1759 = (gctUINT8_PTR) contextBuffer->logical
1760 + Context->entryOffsetXDFrom3D;
1761
1762 entryAddress
1763 = contextBuffer->address
1764 + Context->entryOffsetXDFrom3D;
1765
1766 entryBytes
1767 = Context->bufferSize
1768 - Context->entryOffsetXDFrom3D;
1769 }
1770 else
1771 {
1772#if gcdNONPAGED_MEMORY_CACHEABLE
1773 entryPhysical
1774 = (gctUINT8_PTR) contextBuffer->physical
1775 + Context->entryOffsetXDFrom2D;
1776#endif
1777 entryLogical
1778 = (gctUINT8_PTR) contextBuffer->logical
1779 + Context->entryOffsetXDFrom2D;
1780
1781 entryAddress
1782 = contextBuffer->address
1783 + Context->entryOffsetXDFrom2D;
1784
1785 entryBytes
1786 = Context->totalSize
1787 - Context->entryOffsetXDFrom2D;
1788 }
1789
1790 /* See if we have to switch pipes between the context
1791 and command buffers. */
1792 if (commandBufferObject->entryPipe == gcvPIPE_3D)
1793 {
1794 /* Skip pipe switching sequence. */
1795 offset = pipeBytes;
1796 }
1797 else
1798 {
1799 /* The current hardware and the initial context pipes are
1800 different, switch to the correct pipe. */
1801 gcmkONERROR(gckHARDWARE_PipeSelect(
1802 Command->kernel->hardware,
1803 commandBufferLogical,
1804 commandBufferObject->entryPipe,
1805 &pipeBytes
1806 ));
1807
1808 /* Do not skip pipe switching sequence. */
1809 offset = 0;
1810 }
1811
1812 /* Generate a LINK from the context buffer to
1813 the command buffer. */
1814 gcmkONERROR(gckHARDWARE_Link(
1815 hardware,
1816 contextBuffer->link3D,
1817 commandBufferAddress + offset,
1818 commandBufferSize - offset,
1819 &linkBytes,
1820 &commandLinkLow,
1821 &commandLinkHigh
1822 ));
1823 }
1824 }
1825
1826#if gcdNONPAGED_MEMORY_CACHEABLE
1827 /* Flush the context buffer cache. */
1828 gcmkONERROR(gckOS_CacheClean(
1829 Command->os,
1830 Command->kernelProcessID,
1831 gcvNULL,
1832 (gctUINT32)entryPhysical,
1833 entryLogical,
1834 entryBytes
1835 ));
1836#endif
1837
1838 /* Update the current context. */
1839 Command->currContext = Context;
1840
1841#if gcdDUMP_COMMAND
1842 contextDumpLogical = entryLogical;
1843 contextDumpBytes = entryBytes;
1844#endif
1845
1846
1847#if gcdRECORD_COMMAND
1848 gckRECORDER_Record(
1849 Command->recorder,
1850 gcvNULL,
1851 0xFFFFFFFF,
1852 entryLogical,
1853 entryBytes - 8
1854 );
1855#endif
1856 }
1857
1858 /* Same context. */
1859 else
1860 {
1861 /* Determine context entry and exit points. */
1862 if (commandBufferObject->using2D && Context->dirty2D)
1863 {
1864 /* Reset 2D dirty flag. */
1865 Context->dirty2D = gcvFALSE;
1866
1867 /* Get the "dirty" context buffer. */
1868 contextBuffer = Context->dirtyBuffer;
1869
1870 if (commandBufferObject->using3D && Context->dirty3D)
1871 {
1872 /* Reset 3D dirty flag. */
1873 Context->dirty3D = gcvFALSE;
1874
1875 /* Compute the entry. */
1876 if (Command->pipeSelect == gcvPIPE_2D)
1877 {
1878#if gcdNONPAGED_MEMORY_CACHEABLE
1879 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
1880#endif
1881 entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
1882 entryAddress = contextBuffer->address + pipeBytes;
1883 entryBytes = Context->bufferSize - pipeBytes;
1884 }
1885 else
1886 {
1887#if gcdNONPAGED_MEMORY_CACHEABLE
1888 entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
1889#endif
1890 entryLogical = (gctUINT8_PTR) contextBuffer->logical;
1891 entryAddress = contextBuffer->address;
1892 entryBytes = Context->bufferSize;
1893 }
1894
1895 /* See if we have to switch pipes between the context
1896 and command buffers. */
1897 if (commandBufferObject->entryPipe == gcvPIPE_3D)
1898 {
1899 /* Skip pipe switching sequence. */
1900 offset = pipeBytes;
1901 }
1902 else
1903 {
1904 /* The current hardware and the initial context pipes are
1905 different, switch to the correct pipe. */
1906 gcmkONERROR(gckHARDWARE_PipeSelect(
1907 Command->kernel->hardware,
1908 commandBufferLogical,
1909 commandBufferObject->entryPipe,
1910 &pipeBytes
1911 ));
1912
1913 /* Do not skip pipe switching sequence. */
1914 offset = 0;
1915 }
1916
1917 /* Ensure the NOP between 2D and 3D is in place so that the
1918 execution falls through from 2D to 3D. */
1919 gcmkONERROR(gckHARDWARE_Nop(
1920 hardware,
1921 contextBuffer->link2D,
1922 &nopBytes
1923 ));
1924
1925 /* Generate a LINK from the context buffer to
1926 the command buffer. */
1927 gcmkONERROR(gckHARDWARE_Link(
1928 hardware,
1929 contextBuffer->link3D,
1930 commandBufferAddress + offset,
1931 commandBufferSize - offset,
1932 &linkBytes,
1933 &commandLinkLow,
1934 &commandLinkHigh
1935 ));
1936 }
1937 else
1938 {
1939 /* Compute the entry. */
1940 if (Command->pipeSelect == gcvPIPE_2D)
1941 {
1942#if gcdNONPAGED_MEMORY_CACHEABLE
1943 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + pipeBytes;
1944#endif
1945 entryLogical = (gctUINT8_PTR) contextBuffer->logical + pipeBytes;
1946 entryAddress = contextBuffer->address + pipeBytes;
1947 entryBytes = Context->entryOffset3D - pipeBytes;
1948 }
1949 else
1950 {
1951#if gcdNONPAGED_MEMORY_CACHEABLE
1952 entryPhysical = (gctUINT8_PTR) contextBuffer->physical;
1953#endif
1954 entryLogical = (gctUINT8_PTR) contextBuffer->logical;
1955 entryAddress = contextBuffer->address;
1956 entryBytes = Context->entryOffset3D;
1957 }
1958
1959 /* See if we have to switch pipes between the context
1960 and command buffers. */
1961 if (commandBufferObject->entryPipe == gcvPIPE_2D)
1962 {
1963 /* Skip pipe switching sequence. */
1964 offset = pipeBytes;
1965 }
1966 else
1967 {
1968 /* The current hardware and the initial context pipes are
1969 different, switch to the correct pipe. */
1970 gcmkONERROR(gckHARDWARE_PipeSelect(
1971 Command->kernel->hardware,
1972 commandBufferLogical,
1973 commandBufferObject->entryPipe,
1974 &pipeBytes
1975 ));
1976
1977 /* Do not skip pipe switching sequence. */
1978 offset = 0;
1979 }
1980
1981 /* 3D is not used, generate a LINK from the end of 2D part of
1982 the context buffer to the command buffer. */
1983 gcmkONERROR(gckHARDWARE_Link(
1984 hardware,
1985 contextBuffer->link2D,
1986 commandBufferAddress + offset,
1987 commandBufferSize - offset,
1988 &linkBytes,
1989 &commandLinkLow,
1990 &commandLinkHigh
1991 ));
1992 }
1993 }
1994 else
1995 {
1996 if (commandBufferObject->using3D && Context->dirty3D)
1997 {
1998 /* Reset 3D dirty flag. */
1999 Context->dirty3D = gcvFALSE;
2000
2001 /* Get the "dirty" context buffer. */
2002 contextBuffer = Context->dirtyBuffer;
2003
2004 /* Determine context buffer entry offset. */
2005 offset = (Command->pipeSelect == gcvPIPE_3D)
2006
2007 /* Skip pipe switching sequence. */
2008 ? Context->entryOffset3D + pipeBytes
2009
2010 /* Do not skip pipe switching sequence. */
2011 : Context->entryOffset3D;
2012
2013 /* Compute the entry. */
2014#if gcdNONPAGED_MEMORY_CACHEABLE
2015 entryPhysical = (gctUINT8_PTR) contextBuffer->physical + offset;
2016#endif
2017 entryLogical = (gctUINT8_PTR) contextBuffer->logical + offset;
2018 entryAddress = contextBuffer->address + offset;
2019 entryBytes = Context->bufferSize - offset;
2020
2021 /* See if we have to switch pipes between the context
2022 and command buffers. */
2023 if (commandBufferObject->entryPipe == gcvPIPE_3D)
2024 {
2025 /* Skip pipe switching sequence. */
2026 offset = pipeBytes;
2027 }
2028 else
2029 {
2030 /* The current hardware and the initial context pipes are
2031 different, switch to the correct pipe. */
2032 gcmkONERROR(gckHARDWARE_PipeSelect(
2033 Command->kernel->hardware,
2034 commandBufferLogical,
2035 commandBufferObject->entryPipe,
2036 &pipeBytes
2037 ));
2038
2039 /* Do not skip pipe switching sequence. */
2040 offset = 0;
2041 }
2042
2043 /* Generate a LINK from the context buffer to
2044 the command buffer. */
2045 gcmkONERROR(gckHARDWARE_Link(
2046 hardware,
2047 contextBuffer->link3D,
2048 commandBufferAddress + offset,
2049 commandBufferSize - offset,
2050 &linkBytes,
2051 &commandLinkLow,
2052 &commandLinkHigh
2053 ));
2054 }
2055 else
2056 {
2057 /* See if we have to switch pipes for the command buffer. */
2058 if (commandBufferObject->entryPipe == Command->pipeSelect)
2059 {
2060 /* Skip pipe switching sequence. */
2061 offset = pipeBytes;
2062 }
2063 else
2064 {
2065 /* The current hardware and the entry command buffer pipes
2066 ** are different, switch to the correct pipe. */
2067 gcmkONERROR(gckHARDWARE_PipeSelect(
2068 Command->kernel->hardware,
2069 commandBufferLogical,
2070 commandBufferObject->entryPipe,
2071 &pipeBytes
2072 ));
2073
2074 /* Do not skip pipe switching sequence. */
2075 offset = 0;
2076 }
2077
2078 /* Compute the entry. */
2079#if gcdNONPAGED_MEMORY_CACHEABLE
2080 entryPhysical = (gctUINT8_PTR) commandBufferPhysical + offset;
2081#endif
2082 entryLogical = commandBufferLogical + offset;
2083 entryAddress = commandBufferAddress + offset;
2084 entryBytes = commandBufferSize - offset;
2085 }
2086 }
2087 }
2088
2089#if gcdDUMP_COMMAND
2090 bufferDumpLogical = commandBufferLogical + offset;
2091 bufferDumpBytes = commandBufferSize - offset;
2092#endif
2093
2094#if gcdSECURE_USER
2095 /* Process user hints. */
2096 gcmkONERROR(_ProcessHints(Command, ProcessID, commandBufferObject));
2097#endif
2098
2099 /* Determine the location to jump to for the command buffer being
2100 ** scheduled. */
2101 if (Command->newQueue)
2102 {
2103 /* New command queue, jump to the beginning of it. */
2104#if gcdNONPAGED_MEMORY_CACHEABLE
2105 exitPhysical = Command->physical;
2106#endif
2107
2108 exitLogical = Command->logical;
2109 exitAddress = Command->address;
2110 exitBytes = Command->offset + waitLinkBytes;
2111 }
2112 else
2113 {
2114 /* Still within the preexisting command queue, jump to the new
2115 WAIT/LINK command sequence. */
2116#if gcdNONPAGED_MEMORY_CACHEABLE
2117 exitPhysical = waitLinkPhysical;
2118#endif
2119 exitLogical = waitLinkLogical;
2120 exitAddress = waitLinkAddress;
2121 exitBytes = waitLinkBytes;
2122 }
2123
2124 /* Add a new WAIT/LINK command sequence. When the command buffer which is
2125 currently being scheduled is fully executed by the GPU, the FE will
2126 jump to this WAIT/LINK sequence. */
2127 gcmkONERROR(gckHARDWARE_WaitLink(
2128 hardware,
2129 waitLinkLogical,
2130 offset,
2131 &waitLinkBytes,
2132 &waitOffset,
2133 &waitSize
2134 ));
2135
2136 /* Compute the location if WAIT command. */
2137 waitPhysical = waitLinkPhysical + waitOffset;
2138 waitLogical = (gctUINT8_PTR) waitLinkLogical + waitOffset;
2139
2140#if gcdNONPAGED_MEMORY_CACHEABLE
2141 /* Flush the command queue cache. */
2142 gcmkONERROR(gckOS_CacheClean(
2143 Command->os,
2144 Command->kernelProcessID,
2145 gcvNULL,
2146 (gctUINT32)exitPhysical,
2147 exitLogical,
2148 exitBytes
2149 ));
2150#endif
2151
2152 /* Determine the location of the LINK command in the command buffer. */
2153 commandBufferLink
2154 = (gctUINT8_PTR) gcmUINT64_TO_PTR(commandBufferObject->logical)
2155 + commandBufferObject->offset;
2156
2157#ifdef __QNXNTO__
2158 userCommandBufferLink = (gctPOINTER) commandBufferLink;
2159
2160 gcmkONERROR(gckOS_MapUserPointer(
2161 Command->os,
2162 userCommandBufferLink,
2163 0,
2164 &pointer));
2165
2166 commandBufferLink = pointer;
2167
2168 userCommandBufferLinkMapped = gcvTRUE;
2169#endif
2170
2171
2172 /* Generate a LINK from the end of the command buffer being scheduled
2173 back to the kernel command queue. */
2174 gcmkONERROR(gckHARDWARE_Link(
2175 hardware,
2176 commandBufferLink,
2177 exitAddress,
2178 exitBytes,
2179 &linkBytes,
2180 &exitLinkLow,
2181 &exitLinkHigh
2182 ));
2183
2184#ifdef __QNXNTO__
2185 gcmkONERROR(gckOS_UnmapUserPointer(
2186 Command->os,
2187 userCommandBufferLink,
2188 0,
2189 commandBufferLink));
2190
2191 userCommandBufferLinkMapped = gcvFALSE;
2192#endif
2193
2194#if gcdNONPAGED_MEMORY_CACHEABLE
2195 /* Flush the command buffer cache. */
2196 gcmkONERROR(gckOS_CacheClean(
2197 Command->os,
2198 ProcessID,
2199 gcvNULL,
2200 (gctUINT32)commandBufferPhysical,
2201 commandBufferLogical,
2202 commandBufferSize
2203 ));
2204#endif
2205
2206#if gcdRECORD_COMMAND
2207 gckRECORDER_Record(
2208 Command->recorder,
2209 commandBufferLogical + offset,
2210 commandBufferSize - offset - 8,
2211 gcvNULL,
2212 0xFFFFFFFF
2213 );
2214
2215 gckRECORDER_AdvanceIndex(Command->recorder, Command->commitStamp);
2216#endif
2217
2218 /* Generate a LINK from the previous WAIT/LINK command sequence to the
2219 entry determined above (either the context or the command buffer).
2220 This LINK replaces the WAIT instruction from the previous WAIT/LINK
2221 pair, therefore we use WAIT metrics for generation of this LINK.
2222 This action will execute the entire sequence. */
2223 gcmkONERROR(gckHARDWARE_Link(
2224 hardware,
2225 Command->waitLogical,
2226 entryAddress,
2227 entryBytes,
2228 &Command->waitSize,
2229 &entryLinkLow,
2230 &entryLinkHigh
2231 ));
2232
2233#if gcdLINK_QUEUE_SIZE
2234 if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_USER_COMMAND)
2235 {
2236 gckLINKQUEUE_Enqueue(
2237 &hardware->linkQueue,
2238 entryAddress,
2239 entryAddress + entryBytes,
2240 entryLinkLow,
2241 entryLinkHigh
2242 );
2243
2244 if (commandBufferAddress + offset != entryAddress)
2245 {
2246 gckLINKQUEUE_Enqueue(
2247 &hardware->linkQueue,
2248 commandBufferAddress + offset,
2249 commandBufferAddress + commandBufferSize,
2250 commandLinkLow,
2251 commandLinkHigh
2252 );
2253 }
2254
2255 if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_ALL_COMMAND)
2256 {
2257 /* Dump kernel command.*/
2258 gckLINKQUEUE_Enqueue(
2259 &hardware->linkQueue,
2260 exitAddress,
2261 exitAddress + exitBytes,
2262 exitLinkLow,
2263 exitLinkHigh
2264 );
2265 }
2266 }
2267#endif
2268
2269#if gcdNONPAGED_MEMORY_CACHEABLE
2270 /* Flush the cache for the link. */
2271 gcmkONERROR(gckOS_CacheClean(
2272 Command->os,
2273 Command->kernelProcessID,
2274 gcvNULL,
2275 (gctUINT32)Command->waitPhysical,
2276 Command->waitLogical,
2277 Command->waitSize
2278 ));
2279#endif
2280
2281 gcmkDUMPCOMMAND(
2282 Command->os,
2283 Command->waitLogical,
2284 Command->waitSize,
2285 gceDUMP_BUFFER_LINK,
2286 gcvFALSE
2287 );
2288
2289 gcmkDUMPCOMMAND(
2290 Command->os,
2291 contextDumpLogical,
2292 contextDumpBytes,
2293 gceDUMP_BUFFER_CONTEXT,
2294 gcvFALSE
2295 );
2296
2297 gcmkDUMPCOMMAND(
2298 Command->os,
2299 bufferDumpLogical,
2300 bufferDumpBytes,
2301 gceDUMP_BUFFER_USER,
2302 gcvFALSE
2303 );
2304
2305 gcmkDUMPCOMMAND(
2306 Command->os,
2307 waitLinkLogical,
2308 waitLinkBytes,
2309 gceDUMP_BUFFER_WAITLINK,
2310 gcvFALSE
2311 );
2312
2313 /* Update the current pipe. */
2314 Command->pipeSelect = commandBufferObject->exitPipe;
2315
2316 /* Update command queue offset. */
2317 Command->offset += waitLinkBytes;
2318 Command->newQueue = gcvFALSE;
2319
2320 /* Update address of last WAIT. */
2321 Command->waitPhysical = waitPhysical;
2322 Command->waitLogical = waitLogical;
2323 Command->waitSize = waitSize;
2324
2325 /* Update queue tail pointer. */
2326 gcmkONERROR(gckHARDWARE_UpdateQueueTail(
2327 hardware, Command->logical, Command->offset
2328 ));
2329
2330#if gcdDUMP_COMMAND
2331 gcmkPRINT("@[kernel.commit]");
2332#endif
2333#endif /* gcdNULL_DRIVER */
2334
2335 /* Release the context switching mutex. */
2336 gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
2337 contextAcquired = gcvFALSE;
2338
2339 Command->commitStamp++;
2340
2341 stall = gcvFALSE;
2342
2343#if gcdLINK_QUEUE_SIZE
2344 if (Command->kernel->stuckDump == gcvSTUCK_DUMP_STALL_COMMAND)
2345 {
2346 if ((Command->commitStamp % (gcdLINK_QUEUE_SIZE/2)) == 0)
2347 {
2348 /* If only context buffer and command buffer is recorded,
2349 ** each commit costs 2 slot in queue, to make sure command
2350 ** causing stuck is recorded, number of pending command buffer
2351 ** is limited to (gckLINK_QUEUE_SIZE/2)
2352 */
2353 stall = gcvTRUE;
2354 }
2355 }
2356#endif
2357
2358 /* Release the command queue. */
2359 gcmkONERROR(gckCOMMAND_ExitCommit(Command, gcvFALSE));
2360 commitEntered = gcvFALSE;
2361
2362 if (stall)
2363 {
2364 gcmkONERROR(gckCOMMAND_Stall(Command, gcvFALSE));
2365 }
2366
2367#if VIVANTE_PROFILER_CONTEXT
2368 if(sequenceAcquired)
2369 {
2370 gcmkONERROR(gckCOMMAND_Stall(Command, gcvTRUE));
2371 if (Command->currContext)
2372 {
2373 gcmkONERROR(gckHARDWARE_UpdateContextProfile(
2374 hardware,
2375 Command->currContext));
2376 }
2377
2378 /* Release the context switching mutex. */
2379 gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContextSeq));
2380 sequenceAcquired = gcvFALSE;
2381 }
2382#endif
2383
2384 /* Loop while there are records in the queue. */
2385 while (EventQueue != gcvNULL)
2386 {
2387 if (needCopy)
2388 {
2389 /* Point to stack record. */
2390 eventRecord = &_eventRecord;
2391
2392 /* Copy the data from the client. */
2393 gcmkONERROR(gckOS_CopyFromUserData(
2394 Command->os, eventRecord, EventQueue, gcmSIZEOF(gcsQUEUE)
2395 ));
2396 }
2397 else
2398 {
2399 /* Map record into kernel memory. */
2400 gcmkONERROR(gckOS_MapUserPointer(Command->os,
2401 EventQueue,
2402 gcmSIZEOF(gcsQUEUE),
2403 &pointer));
2404
2405 eventRecord = pointer;
2406 }
2407
2408 /* Append event record to event queue. */
2409 gcmkONERROR(gckEVENT_AddList(
2410 Command->kernel->eventObj, &eventRecord->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE
2411 ));
2412
2413 /* Next record in the queue. */
2414 nextEventRecord = gcmUINT64_TO_PTR(eventRecord->next);
2415
2416 if (!needCopy)
2417 {
2418 /* Unmap record from kernel memory. */
2419 gcmkONERROR(gckOS_UnmapUserPointer(
2420 Command->os, EventQueue, gcmSIZEOF(gcsQUEUE), (gctPOINTER *) eventRecord
2421 ));
2422
2423 eventRecord = gcvNULL;
2424 }
2425
2426 EventQueue = nextEventRecord;
2427 }
2428
2429 if (Command->kernel->eventObj->queueHead == gcvNULL
2430 && Command->kernel->hardware->powerManagement == gcvTRUE
2431 )
2432 {
2433 /* Commit done event by which work thread knows all jobs done. */
2434 gcmkVERIFY_OK(
2435 gckEVENT_CommitDone(Command->kernel->eventObj, gcvKERNEL_PIXEL));
2436 }
2437
2438 /* Submit events. */
2439 status = gckEVENT_Submit(Command->kernel->eventObj, gcvTRUE, gcvFALSE);
2440 if (status == gcvSTATUS_INTERRUPTED)
2441 {
2442 gcmkTRACE(
2443 gcvLEVEL_INFO,
2444 "%s(%d): Intterupted in gckEVENT_Submit",
2445 __FUNCTION__, __LINE__
2446 );
2447 status = gcvSTATUS_OK;
2448 }
2449 else
2450 {
2451 gcmkONERROR(status);
2452 }
2453
2454#ifdef __QNXNTO__
2455 if (userCommandBufferLogicalMapped)
2456 {
2457 gcmkONERROR(gckOS_UnmapUserPointer(
2458 Command->os,
2459 userCommandBufferLogical,
2460 0,
2461 commandBufferLogical));
2462
2463 userCommandBufferLogicalMapped = gcvFALSE;
2464 }
2465#endif
2466
2467 /* Unmap the command buffer pointer. */
2468 if (commandBufferMapped)
2469 {
2470 gcmkONERROR(gckOS_UnmapUserPointer(
2471 Command->os,
2472 CommandBuffer,
2473 gcmSIZEOF(struct _gcoCMDBUF),
2474 commandBufferObject
2475 ));
2476
2477 commandBufferMapped = gcvFALSE;
2478 }
2479
2480 /* Return status. */
2481 gcmkFOOTER();
2482 return gcvSTATUS_OK;
2483
2484OnError:
2485 if ((eventRecord != gcvNULL) && !needCopy)
2486 {
2487 /* Roll back. */
2488 gcmkVERIFY_OK(gckOS_UnmapUserPointer(
2489 Command->os,
2490 EventQueue,
2491 gcmSIZEOF(gcsQUEUE),
2492 (gctPOINTER *) eventRecord
2493 ));
2494 }
2495
2496 if (contextAcquired)
2497 {
2498 /* Release the context switching mutex. */
2499 gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
2500 }
2501
2502 if (commitEntered)
2503 {
2504 /* Release the command queue mutex. */
2505 gcmkVERIFY_OK(gckCOMMAND_ExitCommit(Command, gcvFALSE));
2506 }
2507
2508#if VIVANTE_PROFILER_CONTEXT
2509 if (sequenceAcquired)
2510 {
2511 /* Release the context sequence mutex. */
2512 gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContextSeq));
2513 }
2514#endif
2515
2516#ifdef __QNXNTO__
2517 if (userCommandBufferLinkMapped)
2518 {
2519 gcmkONERROR(gckOS_UnmapUserPointer(
2520 Command->os,
2521 userCommandBufferLink,
2522 0,
2523 commandBufferLink));
2524 }
2525
2526 if (userCommandBufferLogicalMapped)
2527 {
2528 gcmkVERIFY_OK(gckOS_UnmapUserPointer(
2529 Command->os,
2530 userCommandBufferLogical,
2531 0,
2532 commandBufferLogical));
2533 }
2534#endif
2535
2536 /* Unmap the command buffer pointer. */
2537 if (commandBufferMapped)
2538 {
2539 gcmkVERIFY_OK(gckOS_UnmapUserPointer(
2540 Command->os,
2541 CommandBuffer,
2542 gcmSIZEOF(struct _gcoCMDBUF),
2543 commandBufferObject
2544 ));
2545 }
2546
2547 /* Return status. */
2548 gcmkFOOTER();
2549 return status;
2550}
2551
2552/*******************************************************************************
2553**
2554** gckCOMMAND_Reserve
2555**
2556** Reserve space in the command queue. Also acquire the command queue mutex.
2557**
2558** INPUT:
2559**
2560** gckCOMMAND Command
2561** Pointer to an gckCOMMAND object.
2562**
2563** gctSIZE_T RequestedBytes
2564** Number of bytes previously reserved.
2565**
2566** OUTPUT:
2567**
2568** gctPOINTER * Buffer
2569** Pointer to a variable that will receive the address of the reserved
2570** space.
2571**
2572** gctSIZE_T * BufferSize
2573** Pointer to a variable that will receive the number of bytes
2574** available in the command queue.
2575*/
2576gceSTATUS
2577gckCOMMAND_Reserve(
2578 IN gckCOMMAND Command,
2579 IN gctUINT32 RequestedBytes,
2580 OUT gctPOINTER * Buffer,
2581 OUT gctUINT32 * BufferSize
2582 )
2583{
2584 gceSTATUS status;
2585 gctUINT32 bytes;
2586 gctUINT32 requiredBytes;
2587 gctUINT32 requestedAligned;
2588
2589 gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
2590
2591 /* Verify the arguments. */
2592 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
2593
2594 /* Compute aligned number of reuested bytes. */
2595 requestedAligned = gcmALIGN(RequestedBytes, Command->alignment);
2596
2597 /* Another WAIT/LINK command sequence will have to be appended after
2598 the requested area being reserved. Compute the number of bytes
2599 required for WAIT/LINK at the location after the reserved area. */
2600 gcmkONERROR(gckHARDWARE_WaitLink(
2601 Command->kernel->hardware,
2602 gcvNULL,
2603 Command->offset + requestedAligned,
2604 &requiredBytes,
2605 gcvNULL,
2606 gcvNULL
2607 ));
2608
2609 /* Compute total number of bytes required. */
2610 requiredBytes += requestedAligned;
2611
2612 /* Compute number of bytes available in command queue. */
2613 bytes = Command->pageSize - Command->offset;
2614
2615 /* Is there enough space in the current command queue? */
2616 if (bytes < requiredBytes)
2617 {
2618 /* Create a new command queue. */
2619 gcmkONERROR(_NewQueue(Command));
2620
2621 /* Recompute the number of bytes in the new kernel command queue. */
2622 bytes = Command->pageSize - Command->offset;
2623
2624 /* Still not enough space? */
2625 if (bytes < requiredBytes)
2626 {
2627 /* Rare case, not enough room in command queue. */
2628 gcmkONERROR(gcvSTATUS_BUFFER_TOO_SMALL);
2629 }
2630 }
2631
2632 /* Return pointer to empty slot command queue. */
2633 *Buffer = (gctUINT8 *) Command->logical + Command->offset;
2634
2635 /* Return number of bytes left in command queue. */
2636 *BufferSize = bytes;
2637
2638 /* Success. */
2639 gcmkFOOTER_ARG("*Buffer=0x%x *BufferSize=%lu", *Buffer, *BufferSize);
2640 return gcvSTATUS_OK;
2641
2642OnError:
2643 /* Return status. */
2644 gcmkFOOTER();
2645 return status;
2646}
2647
2648/*******************************************************************************
2649**
2650** gckCOMMAND_Execute
2651**
2652** Execute a previously reserved command queue by appending a WAIT/LINK command
2653** sequence after it and modifying the last WAIT into a LINK command. The
2654** command FIFO mutex will be released whether this function succeeds or not.
2655**
2656** INPUT:
2657**
2658** gckCOMMAND Command
2659** Pointer to an gckCOMMAND object.
2660**
2661** gctSIZE_T RequestedBytes
2662** Number of bytes previously reserved.
2663**
2664** OUTPUT:
2665**
2666** Nothing.
2667*/
2668gceSTATUS
2669gckCOMMAND_Execute(
2670 IN gckCOMMAND Command,
2671 IN gctUINT32 RequestedBytes
2672 )
2673{
2674 gceSTATUS status;
2675
2676 gctUINT32 waitLinkPhysical;
2677 gctUINT8_PTR waitLinkLogical;
2678 gctUINT32 waitLinkOffset;
2679 gctUINT32 waitLinkBytes;
2680
2681 gctUINT32 waitPhysical;
2682 gctPOINTER waitLogical;
2683 gctUINT32 waitOffset;
2684 gctUINT32 waitBytes;
2685
2686 gctUINT32 linkLow, linkHigh;
2687
2688#if gcdNONPAGED_MEMORY_CACHEABLE
2689 gctPHYS_ADDR execPhysical;
2690#endif
2691 gctPOINTER execLogical;
2692 gctUINT32 execAddress;
2693 gctUINT32 execBytes;
2694
2695 gcmkHEADER_ARG("Command=0x%x RequestedBytes=%lu", Command, RequestedBytes);
2696
2697 /* Verify the arguments. */
2698 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
2699
2700 /* Compute offset for WAIT/LINK. */
2701 waitLinkOffset = Command->offset + RequestedBytes;
2702
2703 /* Compute number of bytes left in command queue. */
2704 waitLinkBytes = Command->pageSize - waitLinkOffset;
2705
2706 /* Compute the location if WAIT/LINK command sequence. */
2707 waitLinkPhysical = Command->physical + waitLinkOffset;
2708 waitLinkLogical = (gctUINT8_PTR) Command->logical + waitLinkOffset;
2709
2710 /* Append WAIT/LINK in command queue. */
2711 gcmkONERROR(gckHARDWARE_WaitLink(
2712 Command->kernel->hardware,
2713 waitLinkLogical,
2714 waitLinkOffset,
2715 &waitLinkBytes,
2716 &waitOffset,
2717 &waitBytes
2718 ));
2719
2720 /* Compute the location if WAIT command. */
2721 waitPhysical = waitLinkPhysical + waitOffset;
2722 waitLogical = waitLinkLogical + waitOffset;
2723
2724 /* Determine the location to jump to for the command buffer being
2725 ** scheduled. */
2726 if (Command->newQueue)
2727 {
2728 /* New command queue, jump to the beginning of it. */
2729#if gcdNONPAGED_MEMORY_CACHEABLE
2730 execPhysical = Command->physical;
2731#endif
2732 execLogical = Command->logical;
2733 execAddress = Command->address;
2734 execBytes = waitLinkOffset + waitLinkBytes;
2735 }
2736 else
2737 {
2738 /* Still within the preexisting command queue, jump directly to the
2739 reserved area. */
2740#if gcdNONPAGED_MEMORY_CACHEABLE
2741 execPhysical = (gctUINT8 *) Command->physical + Command->offset;
2742#endif
2743 execLogical = (gctUINT8 *) Command->logical + Command->offset;
2744 execAddress = Command->address + Command->offset;
2745 execBytes = RequestedBytes + waitLinkBytes;
2746 }
2747
2748#if gcdNONPAGED_MEMORY_CACHEABLE
2749 /* Flush the cache. */
2750 gcmkONERROR(gckOS_CacheClean(
2751 Command->os,
2752 Command->kernelProcessID,
2753 gcvNULL,
2754 (gctUINT32)execPhysical,
2755 execLogical,
2756 execBytes
2757 ));
2758#endif
2759
2760 /* Convert the last WAIT into a LINK. */
2761 gcmkONERROR(gckHARDWARE_Link(
2762 Command->kernel->hardware,
2763 Command->waitLogical,
2764 execAddress,
2765 execBytes,
2766 &Command->waitSize,
2767 &linkLow,
2768 &linkHigh
2769 ));
2770
2771#if gcdLINK_QUEUE_SIZE
2772 if (Command->kernel->stuckDump >= gcvSTUCK_DUMP_ALL_COMMAND)
2773 {
2774 gckLINKQUEUE_Enqueue(
2775 &Command->kernel->hardware->linkQueue,
2776 execAddress,
2777 execAddress + execBytes,
2778 linkLow,
2779 linkHigh
2780 );
2781 }
2782#endif
2783
2784#if gcdNONPAGED_MEMORY_CACHEABLE
2785 /* Flush the cache. */
2786 gcmkONERROR(gckOS_CacheClean(
2787 Command->os,
2788 Command->kernelProcessID,
2789 gcvNULL,
2790 (gctUINT32)Command->waitPhysical,
2791 Command->waitLogical,
2792 Command->waitSize
2793 ));
2794#endif
2795
2796 gcmkDUMPCOMMAND(
2797 Command->os,
2798 Command->waitLogical,
2799 Command->waitSize,
2800 gceDUMP_BUFFER_LINK,
2801 gcvFALSE
2802 );
2803
2804 gcmkDUMPCOMMAND(
2805 Command->os,
2806 execLogical,
2807 execBytes,
2808 gceDUMP_BUFFER_KERNEL,
2809 gcvFALSE
2810 );
2811
2812 /* Update the pointer to the last WAIT. */
2813 Command->waitPhysical = waitPhysical;
2814 Command->waitLogical = waitLogical;
2815 Command->waitSize = waitBytes;
2816
2817 /* Update the command queue. */
2818 Command->offset += RequestedBytes + waitLinkBytes;
2819 Command->newQueue = gcvFALSE;
2820
2821 /* Update queue tail pointer. */
2822 gcmkONERROR(gckHARDWARE_UpdateQueueTail(
2823 Command->kernel->hardware, Command->logical, Command->offset
2824 ));
2825
2826#if gcdDUMP_COMMAND
2827 gcmkPRINT("@[kernel.execute]");
2828#endif
2829
2830 /* Success. */
2831 gcmkFOOTER_NO();
2832 return gcvSTATUS_OK;
2833
2834OnError:
2835 /* Return the status. */
2836 gcmkFOOTER();
2837 return status;
2838}
2839
2840/*******************************************************************************
2841**
2842** gckCOMMAND_Stall
2843**
2844** The calling thread will be suspended until the command queue has been
2845** completed.
2846**
2847** INPUT:
2848**
2849** gckCOMMAND Command
2850** Pointer to an gckCOMMAND object.
2851**
2852** gctBOOL FromPower
2853** Determines whether the call originates from inside the power
2854** management or not.
2855**
2856** OUTPUT:
2857**
2858** Nothing.
2859*/
2860gceSTATUS
2861gckCOMMAND_Stall(
2862 IN gckCOMMAND Command,
2863 IN gctBOOL FromPower
2864 )
2865{
2866#if gcdNULL_DRIVER
2867 /* Do nothing with infinite hardware. */
2868 return gcvSTATUS_OK;
2869#else
2870 gckOS os;
2871 gckHARDWARE hardware;
2872 gckEVENT eventObject;
2873 gceSTATUS status;
2874 gctSIGNAL signal = gcvNULL;
2875 gctUINT timer = 0;
2876
2877 gcmkHEADER_ARG("Command=0x%x", Command);
2878
2879 /* Verify the arguments. */
2880 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
2881
2882 /* Extract the gckOS object pointer. */
2883 os = Command->os;
2884 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
2885
2886 /* Extract the gckHARDWARE object pointer. */
2887 hardware = Command->kernel->hardware;
2888 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
2889
2890 /* Extract the gckEVENT object pointer. */
2891 eventObject = Command->kernel->eventObj;
2892 gcmkVERIFY_OBJECT(eventObject, gcvOBJ_EVENT);
2893
2894 /* Allocate the signal. */
2895 gcmkONERROR(gckOS_CreateSignal(os, gcvTRUE, &signal));
2896
2897 /* Append the EVENT command to trigger the signal. */
2898 gcmkONERROR(gckEVENT_Signal(eventObject, signal, gcvKERNEL_PIXEL));
2899
2900 /* Submit the event queue. */
2901 gcmkONERROR(gckEVENT_Submit(eventObject, gcvTRUE, FromPower));
2902
2903#if gcdDUMP_COMMAND
2904 gcmkPRINT("@[kernel.stall]");
2905#endif
2906
2907 if (status == gcvSTATUS_CHIP_NOT_READY)
2908 {
2909 /* Error. */
2910 goto OnError;
2911 }
2912
2913 do
2914 {
2915 /* Wait for the signal. */
2916 status = gckOS_WaitSignal(os, signal, gcdGPU_ADVANCETIMER);
2917
2918 if (status == gcvSTATUS_TIMEOUT)
2919 {
2920#if gcmIS_DEBUG(gcdDEBUG_CODE)
2921 gctUINT32 idle;
2922
2923 /* Read idle register. */
2924 gcmkVERIFY_OK(gckHARDWARE_GetIdle(
2925 hardware, gcvFALSE, &idle
2926 ));
2927
2928 gcmkTRACE(
2929 gcvLEVEL_ERROR,
2930 "%s(%d): idle=%08x",
2931 __FUNCTION__, __LINE__, idle
2932 );
2933
2934 gcmkVERIFY_OK(gckOS_MemoryBarrier(os, gcvNULL));
2935#endif
2936
2937 /* Advance timer. */
2938 timer += gcdGPU_ADVANCETIMER;
2939 }
2940 else if (status == gcvSTATUS_INTERRUPTED)
2941 {
2942 gcmkONERROR(gcvSTATUS_INTERRUPTED);
2943 }
2944
2945 }
2946 while (gcmIS_ERROR(status));
2947
2948 /* Bail out on timeout. */
2949 if (gcmIS_ERROR(status))
2950 {
2951 /* Broadcast the stuck GPU. */
2952 gcmkONERROR(gckOS_Broadcast(
2953 os, hardware, gcvBROADCAST_GPU_STUCK
2954 ));
2955 }
2956
2957 /* Delete the signal. */
2958 gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
2959
2960 /* Success. */
2961 gcmkFOOTER_NO();
2962 return gcvSTATUS_OK;
2963
2964OnError:
2965 if (signal != gcvNULL)
2966 {
2967 /* Free the signal. */
2968 gcmkVERIFY_OK(gckOS_DestroySignal(os, signal));
2969 }
2970
2971 /* Return the status. */
2972 gcmkFOOTER();
2973 return status;
2974#endif
2975}
2976
2977/*******************************************************************************
2978**
2979** gckCOMMAND_Attach
2980**
2981** Attach user process.
2982**
2983** INPUT:
2984**
2985** gckCOMMAND Command
2986** Pointer to a gckCOMMAND object.
2987**
2988** gctUINT32 ProcessID
2989** Current process ID.
2990**
2991** OUTPUT:
2992**
2993** gckCONTEXT * Context
2994** Pointer to a variable that will receive a pointer to a new
2995** gckCONTEXT object.
2996**
2997** gctSIZE_T * StateCount
2998** Pointer to a variable that will receive the number of states
2999** in the context buffer.
3000*/
3001gceSTATUS
3002gckCOMMAND_Attach(
3003 IN gckCOMMAND Command,
3004 OUT gckCONTEXT * Context,
3005 OUT gctSIZE_T * MaxState,
3006 OUT gctUINT32 * NumStates,
3007 IN gctUINT32 ProcessID
3008 )
3009{
3010 gceSTATUS status;
3011 gctBOOL acquired = gcvFALSE;
3012
3013 gcmkHEADER_ARG("Command=0x%x", Command);
3014
3015 /* Verify the arguments. */
3016 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
3017
3018 /* Acquire the context switching mutex. */
3019 gcmkONERROR(gckOS_AcquireMutex(
3020 Command->os, Command->mutexContext, gcvINFINITE
3021 ));
3022 acquired = gcvTRUE;
3023
3024 /* Construct a gckCONTEXT object. */
3025 gcmkONERROR(gckCONTEXT_Construct(
3026 Command->os,
3027 Command->kernel->hardware,
3028 ProcessID,
3029 Context
3030 ));
3031
3032 /* Return the number of states in the context. */
3033 * MaxState = (* Context)->maxState;
3034 * NumStates = (* Context)->numStates;
3035
3036 /* Release the context switching mutex. */
3037 gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
3038 acquired = gcvFALSE;
3039
3040 /* Success. */
3041 gcmkFOOTER_ARG("*Context=0x%x", *Context);
3042 return gcvSTATUS_OK;
3043
3044OnError:
3045 /* Release mutex. */
3046 if (acquired)
3047 {
3048 /* Release the context switching mutex. */
3049 gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
3050 acquired = gcvFALSE;
3051 }
3052
3053 /* Return the status. */
3054 gcmkFOOTER();
3055 return status;
3056}
3057
3058/*******************************************************************************
3059**
3060** gckCOMMAND_Detach
3061**
3062** Detach user process.
3063**
3064** INPUT:
3065**
3066** gckCOMMAND Command
3067** Pointer to a gckCOMMAND object.
3068**
3069** gckCONTEXT Context
3070** Pointer to a gckCONTEXT object to be destroyed.
3071**
3072** OUTPUT:
3073**
3074** Nothing.
3075*/
3076gceSTATUS
3077gckCOMMAND_Detach(
3078 IN gckCOMMAND Command,
3079 IN gckCONTEXT Context
3080 )
3081{
3082 gceSTATUS status;
3083 gctBOOL acquired = gcvFALSE;
3084
3085 gcmkHEADER_ARG("Command=0x%x Context=0x%x", Command, Context);
3086
3087 /* Verify the arguments. */
3088 gcmkVERIFY_OBJECT(Command, gcvOBJ_COMMAND);
3089
3090 /* Acquire the context switching mutex. */
3091 gcmkONERROR(gckOS_AcquireMutex(
3092 Command->os, Command->mutexContext, gcvINFINITE
3093 ));
3094 acquired = gcvTRUE;
3095
3096 /* Construct a gckCONTEXT object. */
3097 gcmkONERROR(gckCONTEXT_Destroy(Context));
3098
3099 if (Command->currContext == Context)
3100 {
3101 /* Detach from gckCOMMAND object if the destoryed context is current context. */
3102 Command->currContext = gcvNULL;
3103 }
3104
3105 /* Release the context switching mutex. */
3106 gcmkONERROR(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
3107 acquired = gcvFALSE;
3108
3109 /* Return the status. */
3110 gcmkFOOTER();
3111 return gcvSTATUS_OK;
3112
3113OnError:
3114 /* Release mutex. */
3115 if (acquired)
3116 {
3117 /* Release the context switching mutex. */
3118 gcmkVERIFY_OK(gckOS_ReleaseMutex(Command->os, Command->mutexContext));
3119 acquired = gcvFALSE;
3120 }
3121
3122 /* Return the status. */
3123 gcmkFOOTER();
3124 return status;
3125}
3126
3127/*******************************************************************************
3128**
3129** gckCOMMAND_DumpExecutingBuffer
3130**
3131** Dump the command buffer which GPU is executing.
3132**
3133** INPUT:
3134**
3135** gckCOMMAND Command
3136** Pointer to a gckCOMMAND object.
3137**
3138** OUTPUT:
3139**
3140** Nothing.
3141*/
3142gceSTATUS
3143gckCOMMAND_DumpExecutingBuffer(
3144 IN gckCOMMAND Command
3145 )
3146{
3147 gceSTATUS status;
3148 gckVIRTUAL_COMMAND_BUFFER_PTR buffer = gcvNULL;
3149 gctUINT32 gpuAddress;
3150 gctSIZE_T pageCount;
3151 gctPOINTER entry;
3152 gckOS os = Command->os;
3153 gckKERNEL kernel = Command->kernel;
3154 gctUINT32 i;
3155 gctUINT32 dumpRear;
3156 gckLINKQUEUE queue = &kernel->hardware->linkQueue;
3157 gctSIZE_T bytes;
3158 gckLINKDATA linkData;
3159 gctUINT32 offset;
3160 gctPOINTER entryDump;
3161 gctUINT32 pid;
3162 gctUINT8 processName[24] = {0};
3163
3164 gcmkPRINT("**************************\n");
3165 gcmkPRINT("**** COMMAND BUF DUMP ****\n");
3166 gcmkPRINT("**************************\n");
3167
3168 gcmkPRINT(" Submitted commit stamp = %lld", Command->commitStamp - 1);
3169 gcmkPRINT(" Executed commit stamp = %lld", *(gctUINT64_PTR)Command->fence->logical);
3170
3171 gcmkVERIFY_OK(gckOS_ReadRegisterEx(os, kernel->core, 0x664, &gpuAddress));
3172
3173 gcmkPRINT("DMA Address 0x%08X, memory around:", gpuAddress);
3174
3175 /* Search and dump memory around DMA address. */
3176 if (kernel->virtualCommandBuffer)
3177 {
3178 status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
3179 }
3180 else
3181 {
3182 status = gcvSTATUS_OK;
3183 }
3184
3185 if (gcmIS_SUCCESS(status))
3186 {
3187 if (kernel->virtualCommandBuffer)
3188 {
3189 gcmkVERIFY_OK(gckOS_CreateKernelVirtualMapping(
3190 os, buffer->physical, buffer->bytes, &entry, &pageCount));
3191
3192 offset = gpuAddress - buffer->gpuAddress;
3193
3194 entryDump = entry;
3195
3196 /* Dump one pages. */
3197 bytes = 4096;
3198
3199 /* Align to page. */
3200 offset &= 0xfffff000;
3201
3202 /* Kernel address of page where stall point stay. */
3203 entryDump = (gctUINT8_PTR)entryDump + offset;
3204
3205 /* Align to page. */
3206 gpuAddress &= 0xfffff000;
3207 }
3208 else
3209 {
3210 gcmkVERIFY_OK(gckOS_MapPhysical(os, gpuAddress, 4096, &entry));
3211
3212 /* Align to page start. */
3213 entryDump = (gctPOINTER)((gctUINTPTR_T)entry & ~0xFFF);
3214 gpuAddress = gpuAddress & ~0xFFF;
3215 bytes = 4096;
3216 }
3217
3218 gcmkPRINT("User Command Buffer:\n");
3219 _DumpBuffer(entryDump, gpuAddress, bytes);
3220
3221 if (kernel->virtualCommandBuffer)
3222 {
3223 gcmkVERIFY_OK(gckOS_DestroyKernelVirtualMapping(
3224 os, buffer->physical, buffer->bytes, entry));
3225 }
3226 else
3227 {
3228 gcmkVERIFY_OK(gckOS_UnmapPhysical(os, entry, 4096));
3229 }
3230 }
3231 else
3232 {
3233 _DumpKernelCommandBuffer(Command);
3234 }
3235
3236 /* Dump link queue. */
3237 if (queue->count)
3238 {
3239 gcmkPRINT("Dump Level is %d, dump %d valid record in link queue:",
3240 Command->kernel->stuckDump, queue->count);
3241
3242 dumpRear = queue->count;
3243
3244 for (i = 0; i < dumpRear; i++)
3245 {
3246 gckLINKQUEUE_GetData(queue, i, &linkData);
3247
3248 /* Get gpu address of this command buffer. */
3249 gpuAddress = linkData->start;
3250 bytes = linkData->end - gpuAddress;
3251
3252 pid = linkData->pid;
3253
3254 gckOS_GetProcessNameByPid(pid, 16, processName);
3255
3256 if (kernel->virtualCommandBuffer)
3257 {
3258 buffer = gcvNULL;
3259
3260 /* Get the whole buffer. */
3261 status = gckKERNEL_QueryGPUAddress(kernel, gpuAddress, &buffer);
3262
3263 if (gcmIS_ERROR(status))
3264 {
3265 /* Get kernel address of kernel command buffer. */
3266 status = gckCOMMAND_AddressInKernelCommandBuffer(
3267 kernel->command, gpuAddress, &entry);
3268
3269 if (gcmIS_ERROR(status))
3270 {
3271 status = gckHARDWARE_AddressInHardwareFuncions(
3272 kernel->hardware, gpuAddress, &entry);
3273
3274 if (gcmIS_ERROR(status))
3275 {
3276 gcmkPRINT("Buffer [%08X - %08X] not found, may be freed",
3277 linkData->start,
3278 linkData->end);
3279 continue;
3280 }
3281 }
3282
3283 offset = 0;
3284 gcmkPRINT("Kernel Command Buffer: %08X, %08X", linkData->linkLow, linkData->linkHigh);
3285 }
3286 else
3287 {
3288 /* Get kernel logical for dump. */
3289 if (buffer->kernelLogical)
3290 {
3291 /* Get kernel logical directly if it is a context buffer. */
3292 entry = buffer->kernelLogical;
3293 gcmkPRINT("Context Buffer: %08X, %08X PID:%d %s",
3294 linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
3295 }
3296 else
3297 {
3298 /* Make it accessiable by kernel if it is a user command buffer. */
3299 gcmkVERIFY_OK(
3300 gckOS_CreateKernelVirtualMapping(os,
3301 buffer->physical,
3302 buffer->bytes,
3303 &entry,
3304 &pageCount));
3305 gcmkPRINT("User Command Buffer: %08X, %08X PID:%d %s",
3306 linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
3307 }
3308
3309 offset = gpuAddress - buffer->gpuAddress;
3310 }
3311
3312 /* Dump from the entry. */
3313 _DumpBuffer((gctUINT8_PTR)entry + offset, gpuAddress, bytes);
3314
3315 /* Release kernel logical address if neccessary. */
3316 if (buffer && !buffer->kernelLogical)
3317 {
3318 gcmkVERIFY_OK(
3319 gckOS_DestroyKernelVirtualMapping(os,
3320 buffer->physical,
3321 buffer->bytes,
3322 entry));
3323 }
3324 }
3325 else
3326 {
3327 gcmkVERIFY_OK(gckOS_MapPhysical(os, gpuAddress, bytes, &entry));
3328
3329 gcmkPRINT("Command Buffer: %08X, %08X PID:%d %s",
3330 linkData->linkLow, linkData->linkHigh, linkData->pid, processName);
3331
3332 _DumpBuffer((gctUINT8_PTR)entry, gpuAddress, bytes);
3333
3334 gcmkVERIFY_OK(gckOS_UnmapPhysical(os, entry, bytes));
3335 }
3336 }
3337 }
3338
3339 return gcvSTATUS_OK;
3340}
3341
3342gceSTATUS
3343gckCOMMAND_AddressInKernelCommandBuffer(
3344 IN gckCOMMAND Command,
3345 IN gctUINT32 Address,
3346 OUT gctPOINTER * Pointer
3347 )
3348{
3349 gctINT i;
3350
3351 for (i = 0; i < gcdCOMMAND_QUEUES; i++)
3352 {
3353 if ((Address >= Command->queues[i].address)
3354 && (Address < (Command->queues[i].address + Command->pageSize))
3355 )
3356 {
3357 *Pointer = (gctUINT8_PTR)Command->queues[i].logical
3358 + (Address - Command->queues[i].address)
3359 ;
3360
3361 return gcvSTATUS_OK;
3362 }
3363 }
3364
3365 return gcvSTATUS_NOT_FOUND;
3366}
diff --git a/src/hal/kernel/gc_hal_kernel_db.c b/src/hal/kernel/gc_hal_kernel_db.c
new file mode 100755
index 0000000..3db981b
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_db.c
@@ -0,0 +1,1884 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57
58#define _GC_OBJ_ZONE gcvZONE_DATABASE
59
60/*******************************************************************************
61***** Private fuctions ********************************************************/
62
63#define _GetSlot(database, x) \
64 (gctUINT32)(gcmPTR_TO_UINT64(x) % gcmCOUNTOF(database->list))
65
66/*******************************************************************************
67** gckKERNEL_NewDatabase
68**
69** Create a new database structure and insert it to the head of the hash list.
70**
71** INPUT:
72**
73** gckKERNEL Kernel
74** Pointer to a gckKERNEL object.
75**
76** gctUINT32 ProcessID
77** ProcessID that identifies the database.
78**
79** OUTPUT:
80**
81** gcsDATABASE_PTR * Database
82** Pointer to a variable receiving the database structure pointer on
83** success.
84*/
85static gceSTATUS
86gckKERNEL_NewDatabase(
87 IN gckKERNEL Kernel,
88 IN gctUINT32 ProcessID,
89 OUT gcsDATABASE_PTR * Database
90 )
91{
92 gceSTATUS status;
93 gcsDATABASE_PTR database;
94 gctBOOL acquired = gcvFALSE;
95 gctSIZE_T slot;
96 gcsDATABASE_PTR existingDatabase;
97
98 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
99
100 /* Acquire the database mutex. */
101 gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
102 acquired = gcvTRUE;
103
104 /* Compute the hash for the database. */
105 slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
106
107 /* Walk the hash list. */
108 for (existingDatabase = Kernel->db->db[slot];
109 existingDatabase != gcvNULL;
110 existingDatabase = existingDatabase->next)
111 {
112 if (existingDatabase->processID == ProcessID)
113 {
114 /* One process can't be added twice. */
115 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
116 }
117 }
118
119 if (Kernel->db->freeDatabase != gcvNULL)
120 {
121 /* Allocate a database from the free list. */
122 database = Kernel->db->freeDatabase;
123 Kernel->db->freeDatabase = database->next;
124 }
125 else
126 {
127 gctPOINTER pointer = gcvNULL;
128
129 /* Allocate a new database from the heap. */
130 gcmkONERROR(gckOS_Allocate(Kernel->os,
131 gcmSIZEOF(gcsDATABASE),
132 &pointer));
133
134 gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsDATABASE));
135
136 database = pointer;
137
138 gcmkONERROR(gckOS_CreateMutex(Kernel->os, &database->counterMutex));
139 }
140
141 /* Insert the database into the hash. */
142 database->next = Kernel->db->db[slot];
143 Kernel->db->db[slot] = database;
144
145 /* Save the hash slot. */
146 database->slot = slot;
147
148 /* Release the database mutex. */
149 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
150
151 /* Return the database. */
152 *Database = database;
153
154 /* Success. */
155 gcmkFOOTER_ARG("*Database=0x%x", *Database);
156 return gcvSTATUS_OK;
157
158OnError:
159 if (acquired)
160 {
161 /* Release the database mutex. */
162 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
163 }
164
165 /* Return the status. */
166 gcmkFOOTER();
167 return status;
168}
169
170/*******************************************************************************
171** gckKERNEL_FindDatabase
172**
173** Find a database identified by a process ID and move it to the head of the
174** hash list.
175**
176** INPUT:
177**
178** gckKERNEL Kernel
179** Pointer to a gckKERNEL object.
180**
181** gctUINT32 ProcessID
182** ProcessID that identifies the database.
183**
184** gctBOOL LastProcessID
185** gcvTRUE if searching for the last known process ID. gcvFALSE if
186** we need to search for the process ID specified by the ProcessID
187** argument.
188**
189** OUTPUT:
190**
191** gcsDATABASE_PTR * Database
192** Pointer to a variable receiving the database structure pointer on
193** success.
194*/
195gceSTATUS
196gckKERNEL_FindDatabase(
197 IN gckKERNEL Kernel,
198 IN gctUINT32 ProcessID,
199 IN gctBOOL LastProcessID,
200 OUT gcsDATABASE_PTR * Database
201 )
202{
203 gceSTATUS status;
204 gcsDATABASE_PTR database, previous;
205 gctSIZE_T slot;
206 gctBOOL acquired = gcvFALSE;
207
208 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d LastProcessID=%d",
209 Kernel, ProcessID, LastProcessID);
210
211 /* Compute the hash for the database. */
212 slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
213
214 /* Acquire the database mutex. */
215 gcmkONERROR(
216 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
217 acquired = gcvTRUE;
218
219 /* Check whether we are getting the last known database. */
220 if (LastProcessID)
221 {
222 /* Use last database. */
223 database = Kernel->db->lastDatabase;
224
225 if (database == gcvNULL)
226 {
227 /* Database not found. */
228 gcmkONERROR(gcvSTATUS_INVALID_DATA);
229 }
230 }
231 else
232 {
233 /* Walk the hash list. */
234 for (previous = gcvNULL, database = Kernel->db->db[slot];
235 database != gcvNULL;
236 database = database->next)
237 {
238 if (database->processID == ProcessID)
239 {
240 /* Found it! */
241 break;
242 }
243
244 previous = database;
245 }
246
247 if (database == gcvNULL)
248 {
249 /* Database not found. */
250 gcmkONERROR(gcvSTATUS_INVALID_DATA);
251 }
252
253 if (previous != gcvNULL)
254 {
255 /* Move database to the head of the hash list. */
256 previous->next = database->next;
257 database->next = Kernel->db->db[slot];
258 Kernel->db->db[slot] = database;
259 }
260 }
261
262 /* Release the database mutex. */
263 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
264
265 /* Return the database. */
266 *Database = database;
267
268 /* Success. */
269 gcmkFOOTER_ARG("*Database=0x%x", *Database);
270 return gcvSTATUS_OK;
271
272OnError:
273 if (acquired)
274 {
275 /* Release the database mutex. */
276 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
277 }
278
279 /* Return the status. */
280 gcmkFOOTER();
281 return status;
282}
283
284/*******************************************************************************
285** gckKERNEL_DeleteDatabase
286**
287** Remove a database from the hash list and delete its structure.
288**
289** INPUT:
290**
291** gckKERNEL Kernel
292** Pointer to a gckKERNEL object.
293**
294** gcsDATABASE_PTR Database
295** Pointer to the database structure to remove.
296**
297** OUTPUT:
298**
299** Nothing.
300*/
301static gceSTATUS
302gckKERNEL_DeleteDatabase(
303 IN gckKERNEL Kernel,
304 IN gcsDATABASE_PTR Database
305 )
306{
307 gceSTATUS status;
308 gctBOOL acquired = gcvFALSE;
309 gcsDATABASE_PTR database;
310
311 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
312
313 /* Acquire the database mutex. */
314 gcmkONERROR(
315 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
316 acquired = gcvTRUE;
317
318 /* Check slot value. */
319 gcmkVERIFY_ARGUMENT(Database->slot < gcmCOUNTOF(Kernel->db->db));
320
321 if (Database->slot < gcmCOUNTOF(Kernel->db->db))
322 {
323 /* Check if database if the head of the hash list. */
324 if (Kernel->db->db[Database->slot] == Database)
325 {
326 /* Remove the database from the hash list. */
327 Kernel->db->db[Database->slot] = Database->next;
328 }
329 else
330 {
331 /* Walk the has list to find the database. */
332 for (database = Kernel->db->db[Database->slot];
333 database != gcvNULL;
334 database = database->next
335 )
336 {
337 /* Check if the next list entry is this database. */
338 if (database->next == Database)
339 {
340 /* Remove the database from the hash list. */
341 database->next = Database->next;
342 break;
343 }
344 }
345
346 if (database == gcvNULL)
347 {
348 /* Ouch! Something got corrupted. */
349 gcmkONERROR(gcvSTATUS_INVALID_DATA);
350 }
351 }
352 }
353
354 if (Kernel->db->lastDatabase != gcvNULL)
355 {
356 /* Insert database to the free list. */
357 Kernel->db->lastDatabase->next = Kernel->db->freeDatabase;
358 Kernel->db->freeDatabase = Kernel->db->lastDatabase;
359 }
360
361 /* Keep database as the last database. */
362 Kernel->db->lastDatabase = Database;
363
364 /* Destory handle db. */
365 gcmkVERIFY_OK(gckKERNEL_DestroyIntegerDatabase(Kernel, Database->handleDatabase));
366 Database->handleDatabase = gcvNULL;
367 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Database->handleDatabaseMutex));
368 Database->handleDatabaseMutex = gcvNULL;
369
370#if gcdPROCESS_ADDRESS_SPACE
371 /* Destory process MMU. */
372 gcmkVERIFY_OK(gckEVENT_DestroyMmu(Kernel->eventObj, Database->mmu, gcvKERNEL_PIXEL));
373 Database->mmu = gcvNULL;
374#endif
375
376 /* Release the database mutex. */
377 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
378
379 /* Success. */
380 gcmkFOOTER_NO();
381 return gcvSTATUS_OK;
382
383OnError:
384 if (acquired)
385 {
386 /* Release the database mutex. */
387 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
388 }
389
390 /* Return the status. */
391 gcmkFOOTER();
392 return status;
393}
394
395/*******************************************************************************
396** gckKERNEL_NewRecord
397**
398** Create a new database record structure and insert it to the head of the
399** database.
400**
401** INPUT:
402**
403** gckKERNEL Kernel
404** Pointer to a gckKERNEL object.
405**
406** gcsDATABASE_PTR Database
407** Pointer to a database structure.
408**
409** OUTPUT:
410**
411** gcsDATABASE_RECORD_PTR * Record
412** Pointer to a variable receiving the database record structure
413** pointer on success.
414*/
415static gceSTATUS
416gckKERNEL_NewRecord(
417 IN gckKERNEL Kernel,
418 IN gcsDATABASE_PTR Database,
419 IN gctUINT32 Slot,
420 OUT gcsDATABASE_RECORD_PTR * Record
421 )
422{
423 gceSTATUS status;
424 gctBOOL acquired = gcvFALSE;
425 gcsDATABASE_RECORD_PTR record = gcvNULL;
426
427 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
428
429 /* Acquire the database mutex. */
430 gcmkONERROR(
431 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
432 acquired = gcvTRUE;
433
434 if (Kernel->db->freeRecord != gcvNULL)
435 {
436 /* Allocate the record from the free list. */
437 record = Kernel->db->freeRecord;
438 Kernel->db->freeRecord = record->next;
439 }
440 else
441 {
442 gctPOINTER pointer = gcvNULL;
443
444 /* Allocate the record from the heap. */
445 gcmkONERROR(gckOS_Allocate(Kernel->os,
446 gcmSIZEOF(gcsDATABASE_RECORD),
447 &pointer));
448
449 record = pointer;
450 }
451
452 /* Insert the record in the database. */
453 record->next = Database->list[Slot];
454 Database->list[Slot] = record;
455
456 /* Release the database mutex. */
457 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
458
459 /* Return the record. */
460 *Record = record;
461
462 /* Success. */
463 gcmkFOOTER_ARG("*Record=0x%x", *Record);
464 return gcvSTATUS_OK;
465
466OnError:
467 if (acquired)
468 {
469 /* Release the database mutex. */
470 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
471 }
472 if (record != gcvNULL)
473 {
474 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
475 }
476
477 /* Return the status. */
478 gcmkFOOTER();
479 return status;
480}
481
482/*******************************************************************************
483** gckKERNEL_DeleteRecord
484**
485** Remove a database record from the database and delete its structure.
486**
487** INPUT:
488**
489** gckKERNEL Kernel
490** Pointer to a gckKERNEL object.
491**
492** gcsDATABASE_PTR Database
493** Pointer to a database structure.
494**
495** gceDATABASE_TYPE Type
496** Type of the record to remove.
497**
498** gctPOINTER Data
499** Data of the record to remove.
500**
501** OUTPUT:
502**
503** gctSIZE_T_PTR Bytes
504** Pointer to a variable that receives the size of the record deleted.
505** Can be gcvNULL if the size is not required.
506*/
507static gceSTATUS
508gckKERNEL_DeleteRecord(
509 IN gckKERNEL Kernel,
510 IN gcsDATABASE_PTR Database,
511 IN gceDATABASE_TYPE Type,
512 IN gctPOINTER Data,
513 OUT gctSIZE_T_PTR Bytes OPTIONAL
514 )
515{
516 gceSTATUS status;
517 gctBOOL acquired = gcvFALSE;
518 gcsDATABASE_RECORD_PTR record, previous;
519 gctUINT32 slot = _GetSlot(Database, Data);
520
521 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
522 Kernel, Database, Type, Data);
523
524 /* Acquire the database mutex. */
525 gcmkONERROR(
526 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
527 acquired = gcvTRUE;
528
529 /* Scan the database for this record. */
530 for (record = Database->list[slot], previous = gcvNULL;
531 record != gcvNULL;
532 record = record->next
533 )
534 {
535 if ((record->type == Type)
536 && (record->data == Data)
537 )
538 {
539 /* Found it! */
540 break;
541 }
542
543 previous = record;
544 }
545
546 if (record == gcvNULL)
547 {
548 /* Ouch! This record is not found? */
549 gcmkONERROR(gcvSTATUS_INVALID_DATA);
550 }
551
552 if (Bytes != gcvNULL)
553 {
554 /* Return size of record. */
555 *Bytes = record->bytes;
556 }
557
558 /* Remove record from database. */
559 if (previous == gcvNULL)
560 {
561 Database->list[slot] = record->next;
562 }
563 else
564 {
565 previous->next = record->next;
566 }
567
568 /* Insert record in free list. */
569 record->next = Kernel->db->freeRecord;
570 Kernel->db->freeRecord = record;
571
572 /* Release the database mutex. */
573 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
574
575 /* Success. */
576 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
577 return gcvSTATUS_OK;
578
579OnError:
580 if (acquired)
581 {
582 /* Release the database mutex. */
583 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
584 }
585
586 /* Return the status. */
587 gcmkFOOTER();
588 return status;
589}
590
591/*******************************************************************************
592** gckKERNEL_FindRecord
593**
594** Find a database record from the database.
595**
596** INPUT:
597**
598** gckKERNEL Kernel
599** Pointer to a gckKERNEL object.
600**
601** gcsDATABASE_PTR Database
602** Pointer to a database structure.
603**
604** gceDATABASE_TYPE Type
605** Type of the record to remove.
606**
607** gctPOINTER Data
608** Data of the record to remove.
609**
610** OUTPUT:
611**
612** gctSIZE_T_PTR Bytes
613** Pointer to a variable that receives the size of the record deleted.
614** Can be gcvNULL if the size is not required.
615*/
616static gceSTATUS
617gckKERNEL_FindRecord(
618 IN gckKERNEL Kernel,
619 IN gcsDATABASE_PTR Database,
620 IN gceDATABASE_TYPE Type,
621 IN gctPOINTER Data,
622 OUT gcsDATABASE_RECORD_PTR Record
623 )
624{
625 gceSTATUS status;
626 gctBOOL acquired = gcvFALSE;
627 gcsDATABASE_RECORD_PTR record;
628 gctUINT32 slot = _GetSlot(Database, Data);
629
630 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
631 Kernel, Database, Type, Data);
632
633 /* Acquire the database mutex. */
634 gcmkONERROR(
635 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
636 acquired = gcvTRUE;
637
638 /* Scan the database for this record. */
639 for (record = Database->list[slot];
640 record != gcvNULL;
641 record = record->next
642 )
643 {
644 if ((record->type == Type)
645 && (record->data == Data)
646 )
647 {
648 /* Found it! */
649 break;
650 }
651 }
652
653 if (record == gcvNULL)
654 {
655 /* Ouch! This record is not found? */
656 gcmkONERROR(gcvSTATUS_INVALID_DATA);
657 }
658
659 if (Record != gcvNULL)
660 {
661 /* Return information of record. */
662 gcmkONERROR(
663 gckOS_MemCopy(Record, record, sizeof(gcsDATABASE_RECORD)));
664 }
665
666 /* Release the database mutex. */
667 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
668
669 /* Success. */
670 gcmkFOOTER_ARG("Record=0x%x", Record);
671 return gcvSTATUS_OK;
672
673OnError:
674 if (acquired)
675 {
676 /* Release the database mutex. */
677 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
678 }
679
680 /* Return the status. */
681 gcmkFOOTER();
682 return status;
683}
684
685/*******************************************************************************
686***** Public API **************************************************************/
687
688/*******************************************************************************
689** gckKERNEL_CreateProcessDB
690**
691** Create a new process database.
692**
693** INPUT:
694**
695** gckKERNEL Kernel
696** Pointer to a gckKERNEL object.
697**
698** gctUINT32 ProcessID
699** Process ID used to identify the database.
700**
701** OUTPUT:
702**
703** Nothing.
704*/
705gceSTATUS
706gckKERNEL_CreateProcessDB(
707 IN gckKERNEL Kernel,
708 IN gctUINT32 ProcessID
709 )
710{
711 gceSTATUS status;
712 gcsDATABASE_PTR database = gcvNULL;
713 gctUINT32 i;
714
715 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
716
717 /* Verify the arguments. */
718 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
719
720 /* Create a new database. */
721 gcmkONERROR(gckKERNEL_NewDatabase(Kernel, ProcessID, &database));
722
723 /* Initialize the database. */
724 database->processID = ProcessID;
725 database->vidMem.bytes = 0;
726 database->vidMem.maxBytes = 0;
727 database->vidMem.totalBytes = 0;
728 database->nonPaged.bytes = 0;
729 database->nonPaged.maxBytes = 0;
730 database->nonPaged.totalBytes = 0;
731 database->contiguous.bytes = 0;
732 database->contiguous.maxBytes = 0;
733 database->contiguous.totalBytes = 0;
734 database->mapMemory.bytes = 0;
735 database->mapMemory.maxBytes = 0;
736 database->mapMemory.totalBytes = 0;
737 database->mapUserMemory.bytes = 0;
738 database->mapUserMemory.maxBytes = 0;
739 database->mapUserMemory.totalBytes = 0;
740 database->virtualCommandBuffer.bytes = 0;
741 database->virtualCommandBuffer.maxBytes = 0;
742 database->virtualCommandBuffer.totalBytes = 0;
743
744 for (i = 0; i < gcmCOUNTOF(database->list); i++)
745 {
746 database->list[i] = gcvNULL;
747 }
748
749 for (i = 0; i < gcvSURF_NUM_TYPES; i++)
750 {
751 database->vidMemType[i].bytes = 0;
752 database->vidMemType[i].maxBytes = 0;
753 database->vidMemType[i].totalBytes = 0;
754 }
755
756 for (i = 0; i < gcvPOOL_NUMBER_OF_POOLS; i++)
757 {
758 database->vidMemPool[i].bytes = 0;
759 database->vidMemPool[i].maxBytes = 0;
760 database->vidMemPool[i].totalBytes = 0;
761 }
762
763 gcmkASSERT(database->handleDatabase == gcvNULL);
764 gcmkONERROR(
765 gckKERNEL_CreateIntegerDatabase(Kernel, &database->handleDatabase));
766
767 gcmkASSERT(database->handleDatabaseMutex == gcvNULL);
768 gcmkONERROR(
769 gckOS_CreateMutex(Kernel->os, &database->handleDatabaseMutex));
770
771#if gcdPROCESS_ADDRESS_SPACE
772 gcmkASSERT(database->mmu == gcvNULL);
773 gcmkONERROR(
774 gckMMU_Construct(Kernel, gcdMMU_SIZE, &database->mmu));
775#endif
776
777#if gcdSECURE_USER
778 {
779 gctINT slot;
780 gcskSECURE_CACHE * cache = &database->cache;
781
782 /* Setup the linked list of cache nodes. */
783 for (slot = 1; slot <= gcdSECURE_CACHE_SLOTS; ++slot)
784 {
785 cache->cache[slot].logical = gcvNULL;
786
787#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
788 cache->cache[slot].prev = &cache->cache[slot - 1];
789 cache->cache[slot].next = &cache->cache[slot + 1];
790# endif
791#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
792 cache->cache[slot].nextHash = gcvNULL;
793 cache->cache[slot].prevHash = gcvNULL;
794# endif
795 }
796
797#if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
798 /* Setup the head and tail of the cache. */
799 cache->cache[0].next = &cache->cache[1];
800 cache->cache[0].prev = &cache->cache[gcdSECURE_CACHE_SLOTS];
801 cache->cache[0].logical = gcvNULL;
802
803 /* Fix up the head and tail pointers. */
804 cache->cache[0].next->prev = &cache->cache[0];
805 cache->cache[0].prev->next = &cache->cache[0];
806# endif
807
808#if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
809 /* Zero out the hash table. */
810 for (slot = 0; slot < gcmCOUNTOF(cache->hash); ++slot)
811 {
812 cache->hash[slot].logical = gcvNULL;
813 cache->hash[slot].nextHash = gcvNULL;
814 }
815# endif
816
817 /* Initialize cache index. */
818 cache->cacheIndex = gcvNULL;
819 cache->cacheFree = 1;
820 cache->cacheStamp = 0;
821 }
822#endif
823
824 /* Reset idle timer. */
825 Kernel->db->lastIdle = 0;
826
827 /* Success. */
828 gcmkFOOTER_NO();
829 return gcvSTATUS_OK;
830
831OnError:
832 /* Return the status. */
833 gcmkFOOTER();
834 return status;
835}
836
837/*******************************************************************************
838** gckKERNEL_AddProcessDB
839**
840** Add a record to a process database.
841**
842** INPUT:
843**
844** gckKERNEL Kernel
845** Pointer to a gckKERNEL object.
846**
847** gctUINT32 ProcessID
848** Process ID used to identify the database.
849**
850** gceDATABASE_TYPE TYPE
851** Type of the record to add.
852**
853** gctPOINTER Pointer
854** Data of the record to add.
855**
856** gctPHYS_ADDR Physical
857** Physical address of the record to add.
858**
859** gctSIZE_T Size
860** Size of the record to add.
861**
862** OUTPUT:
863**
864** Nothing.
865*/
866gceSTATUS
867gckKERNEL_AddProcessDB(
868 IN gckKERNEL Kernel,
869 IN gctUINT32 ProcessID,
870 IN gceDATABASE_TYPE Type,
871 IN gctPOINTER Pointer,
872 IN gctPHYS_ADDR Physical,
873 IN gctSIZE_T Size
874 )
875{
876 gceSTATUS status;
877 gcsDATABASE_PTR database;
878 gcsDATABASE_RECORD_PTR record = gcvNULL;
879 gcsDATABASE_COUNTERS * count;
880 gctUINT32 vidMemType;
881 gcePOOL vidMemPool;
882
883 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
884 "Physical=0x%x Size=%lu",
885 Kernel, ProcessID, Type, Pointer, Physical, Size);
886
887 /* Verify the arguments. */
888 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
889
890 /* Decode type. */
891 vidMemType = (Type & gcdDB_VIDEO_MEMORY_TYPE_MASK) >> gcdDB_VIDEO_MEMORY_TYPE_SHIFT;
892 vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
893
894 Type &= gcdDATABASE_TYPE_MASK;
895
896 /* Special case the idle record. */
897 if (Type == gcvDB_IDLE)
898 {
899 gctUINT64 time;
900
901 /* Get the current profile time. */
902 gcmkONERROR(gckOS_GetProfileTick(&time));
903
904 if ((ProcessID == 0) && (Kernel->db->lastIdle != 0))
905 {
906 /* Out of idle, adjust time it was idle. */
907 Kernel->db->idleTime += time - Kernel->db->lastIdle;
908 Kernel->db->lastIdle = 0;
909 }
910 else if (ProcessID == 1)
911 {
912 /* Save current idle time. */
913 Kernel->db->lastIdle = time;
914 }
915
916#if gcdDYNAMIC_SPEED
917 {
918 /* Test for first call. */
919 if (Kernel->db->lastSlowdown == 0)
920 {
921 /* Save milliseconds. */
922 Kernel->db->lastSlowdown = time;
923 Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
924 }
925 else
926 {
927 /* Compute ellapsed time in milliseconds. */
928 gctUINT delta = gckOS_ProfileToMS(time - Kernel->db->lastSlowdown);
929
930 /* Test for end of period. */
931 if (delta >= gcdDYNAMIC_SPEED)
932 {
933 /* Compute number of idle milliseconds. */
934 gctUINT idle = gckOS_ProfileToMS(
935 Kernel->db->idleTime - Kernel->db->lastSlowdownIdle);
936
937 /* Broadcast to slow down the GPU. */
938 gcmkONERROR(gckOS_BroadcastCalibrateSpeed(Kernel->os,
939 Kernel->hardware,
940 idle,
941 delta));
942
943 /* Save current time. */
944 Kernel->db->lastSlowdown = time;
945 Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
946 }
947 }
948 }
949#endif
950
951 /* Success. */
952 gcmkFOOTER_NO();
953 return gcvSTATUS_OK;
954 }
955
956 /* Verify the arguments. */
957 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
958
959 /* Find the database. */
960 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
961
962 /* Create a new record in the database. */
963 gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, _GetSlot(database, Pointer), &record));
964
965 /* Initialize the record. */
966 record->kernel = Kernel;
967 record->type = Type;
968 record->data = Pointer;
969 record->physical = Physical;
970 record->bytes = Size;
971
972 /* Get pointer to counters. */
973 switch (Type)
974 {
975 case gcvDB_VIDEO_MEMORY:
976 count = &database->vidMem;
977 break;
978
979 case gcvDB_NON_PAGED:
980 count = &database->nonPaged;
981 break;
982
983 case gcvDB_CONTIGUOUS:
984 count = &database->contiguous;
985 break;
986
987 case gcvDB_MAP_MEMORY:
988 count = &database->mapMemory;
989 break;
990
991 case gcvDB_MAP_USER_MEMORY:
992 count = &database->mapUserMemory;
993 break;
994
995 case gcvDB_COMMAND_BUFFER:
996 count = &database->virtualCommandBuffer;
997 break;
998
999 default:
1000 count = gcvNULL;
1001 break;
1002 }
1003
1004 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
1005
1006 if (count != gcvNULL)
1007 {
1008 /* Adjust counters. */
1009 count->totalBytes += Size;
1010 count->bytes += Size;
1011 count->allocCount++;
1012
1013 if (count->bytes > count->maxBytes)
1014 {
1015 count->maxBytes = count->bytes;
1016 }
1017 }
1018
1019 if (Type == gcvDB_VIDEO_MEMORY)
1020 {
1021 count = &database->vidMemType[vidMemType];
1022
1023 /* Adjust counters. */
1024 count->totalBytes += Size;
1025 count->bytes += Size;
1026 count->allocCount++;
1027
1028 if (count->bytes > count->maxBytes)
1029 {
1030 count->maxBytes = count->bytes;
1031 }
1032
1033 count = &database->vidMemPool[vidMemPool];
1034
1035 /* Adjust counters. */
1036 count->totalBytes += Size;
1037 count->bytes += Size;
1038 count->allocCount++;
1039
1040 if (count->bytes > count->maxBytes)
1041 {
1042 count->maxBytes = count->bytes;
1043 }
1044 }
1045
1046 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
1047
1048 /* Success. */
1049 gcmkFOOTER_NO();
1050 return gcvSTATUS_OK;
1051
1052OnError:
1053 /* Return the status. */
1054 gcmkFOOTER();
1055 return status;
1056}
1057
1058/*******************************************************************************
1059** gckKERNEL_RemoveProcessDB
1060**
1061** Remove a record from a process database.
1062**
1063** INPUT:
1064**
1065** gckKERNEL Kernel
1066** Pointer to a gckKERNEL object.
1067**
1068** gctUINT32 ProcessID
1069** Process ID used to identify the database.
1070**
1071** gceDATABASE_TYPE TYPE
1072** Type of the record to remove.
1073**
1074** gctPOINTER Pointer
1075** Data of the record to remove.
1076**
1077** OUTPUT:
1078**
1079** Nothing.
1080*/
1081gceSTATUS
1082gckKERNEL_RemoveProcessDB(
1083 IN gckKERNEL Kernel,
1084 IN gctUINT32 ProcessID,
1085 IN gceDATABASE_TYPE Type,
1086 IN gctPOINTER Pointer
1087 )
1088{
1089 gceSTATUS status;
1090 gcsDATABASE_PTR database;
1091 gctSIZE_T bytes = 0;
1092 gctUINT32 vidMemType;
1093 gcePOOL vidMempool;
1094
1095 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
1096 Kernel, ProcessID, Type, Pointer);
1097
1098 /* Verify the arguments. */
1099 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1100 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
1101
1102 /* Decode type. */
1103 vidMemType = (Type & gcdDB_VIDEO_MEMORY_TYPE_MASK) >> gcdDB_VIDEO_MEMORY_TYPE_SHIFT;
1104 vidMempool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
1105
1106 Type &= gcdDATABASE_TYPE_MASK;
1107
1108 /* Find the database. */
1109 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1110
1111 /* Delete the record. */
1112 gcmkONERROR(
1113 gckKERNEL_DeleteRecord(Kernel, database, Type, Pointer, &bytes));
1114
1115 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
1116
1117 /* Update counters. */
1118 switch (Type)
1119 {
1120 case gcvDB_VIDEO_MEMORY:
1121 database->vidMem.bytes -= bytes;
1122 database->vidMem.freeCount++;
1123 database->vidMemType[vidMemType].bytes -= bytes;
1124 database->vidMemType[vidMemType].freeCount++;
1125 database->vidMemPool[vidMempool].bytes -= bytes;
1126 database->vidMemPool[vidMempool].freeCount++;
1127 break;
1128
1129 case gcvDB_NON_PAGED:
1130 database->nonPaged.bytes -= bytes;
1131 database->nonPaged.freeCount++;
1132 break;
1133
1134 case gcvDB_CONTIGUOUS:
1135 database->contiguous.bytes -= bytes;
1136 database->contiguous.freeCount++;
1137 break;
1138
1139 case gcvDB_MAP_MEMORY:
1140 database->mapMemory.bytes -= bytes;
1141 database->mapMemory.freeCount++;
1142 break;
1143
1144 case gcvDB_MAP_USER_MEMORY:
1145 database->mapUserMemory.bytes -= bytes;
1146 database->mapUserMemory.freeCount++;
1147 break;
1148
1149 case gcvDB_COMMAND_BUFFER:
1150 database->virtualCommandBuffer.bytes -= bytes;
1151 database->virtualCommandBuffer.freeCount++;
1152 break;
1153
1154 default:
1155 break;
1156 }
1157
1158 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
1159
1160 /* Success. */
1161 gcmkFOOTER_NO();
1162 return gcvSTATUS_OK;
1163
1164OnError:
1165 /* Return the status. */
1166 gcmkFOOTER();
1167 return status;
1168}
1169
1170/*******************************************************************************
1171** gckKERNEL_FindProcessDB
1172**
1173** Find a record from a process database.
1174**
1175** INPUT:
1176**
1177** gckKERNEL Kernel
1178** Pointer to a gckKERNEL object.
1179**
1180** gctUINT32 ProcessID
1181** Process ID used to identify the database.
1182**
1183** gceDATABASE_TYPE TYPE
1184** Type of the record to remove.
1185**
1186** gctPOINTER Pointer
1187** Data of the record to remove.
1188**
1189** OUTPUT:
1190**
1191** gcsDATABASE_RECORD_PTR Record
1192** Copy of record.
1193*/
1194gceSTATUS
1195gckKERNEL_FindProcessDB(
1196 IN gckKERNEL Kernel,
1197 IN gctUINT32 ProcessID,
1198 IN gctUINT32 ThreadID,
1199 IN gceDATABASE_TYPE Type,
1200 IN gctPOINTER Pointer,
1201 OUT gcsDATABASE_RECORD_PTR Record
1202 )
1203{
1204 gceSTATUS status;
1205 gcsDATABASE_PTR database;
1206
1207 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
1208 Kernel, ProcessID, ThreadID, Type, Pointer);
1209
1210 /* Verify the arguments. */
1211 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1212 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
1213
1214 /* Find the database. */
1215 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1216
1217 /* Find the record. */
1218 gcmkONERROR(
1219 gckKERNEL_FindRecord(Kernel, database, Type, Pointer, Record));
1220
1221 /* Success. */
1222 gcmkFOOTER_NO();
1223 return gcvSTATUS_OK;
1224
1225OnError:
1226 /* Return the status. */
1227 gcmkFOOTER();
1228 return status;
1229}
1230
1231/*******************************************************************************
1232** gckKERNEL_DestroyProcessDB
1233**
1234** Destroy a process database. If the database contains any records, the data
1235** inside those records will be deleted as well. This aids in the cleanup if
1236** a process has died unexpectedly or has memory leaks.
1237**
1238** INPUT:
1239**
1240** gckKERNEL Kernel
1241** Pointer to a gckKERNEL object.
1242**
1243** gctUINT32 ProcessID
1244** Process ID used to identify the database.
1245**
1246** OUTPUT:
1247**
1248** Nothing.
1249*/
1250gceSTATUS
1251gckKERNEL_DestroyProcessDB(
1252 IN gckKERNEL Kernel,
1253 IN gctUINT32 ProcessID
1254 )
1255{
1256 gceSTATUS status;
1257 gcsDATABASE_PTR database;
1258 gcsDATABASE_RECORD_PTR record, next;
1259 gctBOOL asynchronous = gcvTRUE;
1260 gckVIDMEM_NODE nodeObject;
1261 gctPHYS_ADDR physical;
1262 gckKERNEL kernel = Kernel;
1263 gctUINT32 handle;
1264 gctUINT32 i;
1265
1266 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
1267
1268 /* Verify the arguments. */
1269 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1270
1271 /* Find the database. */
1272 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1273
1274 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1275 "DB(%d): VidMem: total=%lu max=%lu",
1276 ProcessID, database->vidMem.totalBytes,
1277 database->vidMem.maxBytes);
1278 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1279 "DB(%d): NonPaged: total=%lu max=%lu",
1280 ProcessID, database->nonPaged.totalBytes,
1281 database->nonPaged.maxBytes);
1282 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1283 "DB(%d): Contiguous: total=%lu max=%lu",
1284 ProcessID, database->contiguous.totalBytes,
1285 database->contiguous.maxBytes);
1286 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1287 "DB(%d): Idle time=%llu",
1288 ProcessID, Kernel->db->idleTime);
1289 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1290 "DB(%d): Map: total=%lu max=%lu",
1291 ProcessID, database->mapMemory.totalBytes,
1292 database->mapMemory.maxBytes);
1293 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1294 "DB(%d): Map: total=%lu max=%lu",
1295 ProcessID, database->mapUserMemory.totalBytes,
1296 database->mapUserMemory.maxBytes);
1297
1298 if (database->list != gcvNULL)
1299 {
1300 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1301 "Process %d has entries in its database:",
1302 ProcessID);
1303 }
1304
1305 for(i = 0; i < gcmCOUNTOF(database->list); i++)
1306 {
1307
1308 /* Walk all records. */
1309 for (record = database->list[i]; record != gcvNULL; record = next)
1310 {
1311 /* Next next record. */
1312 next = record->next;
1313
1314 /* Dispatch on record type. */
1315 switch (record->type)
1316 {
1317 case gcvDB_VIDEO_MEMORY:
1318 gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
1319 ProcessID,
1320 gcmPTR2INT32(record->data),
1321 &nodeObject));
1322
1323 /* Free the video memory. */
1324 gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
1325 ProcessID,
1326 gcmPTR2INT32(record->data)));
1327
1328 gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
1329 nodeObject));
1330
1331 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1332 "DB: VIDEO_MEMORY 0x%x (status=%d)",
1333 record->data, status);
1334 break;
1335
1336 case gcvDB_NON_PAGED:
1337 physical = gcmNAME_TO_PTR(record->physical);
1338 /* Unmap user logical memory first. */
1339 status = gckOS_UnmapUserLogical(Kernel->os,
1340 physical,
1341 record->bytes,
1342 record->data);
1343
1344 /* Free the non paged memory. */
1345 status = gckEVENT_FreeNonPagedMemory(Kernel->eventObj,
1346 record->bytes,
1347 physical,
1348 record->data,
1349 gcvKERNEL_PIXEL);
1350 gcmRELEASE_NAME(record->physical);
1351
1352 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1353 "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
1354 record->data, record->bytes, status);
1355 break;
1356
1357 case gcvDB_COMMAND_BUFFER:
1358 /* Free the command buffer. */
1359 status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj,
1360 record->bytes,
1361 gcmNAME_TO_PTR(record->physical),
1362 record->data,
1363 gcvKERNEL_PIXEL);
1364 gcmRELEASE_NAME(record->physical);
1365
1366 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1367 "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)",
1368 record->data, record->bytes, status);
1369 break;
1370
1371 case gcvDB_CONTIGUOUS:
1372 physical = gcmNAME_TO_PTR(record->physical);
1373 /* Unmap user logical memory first. */
1374 status = gckOS_UnmapUserLogical(Kernel->os,
1375 physical,
1376 record->bytes,
1377 record->data);
1378
1379 /* Free the contiguous memory. */
1380 status = gckEVENT_FreeContiguousMemory(Kernel->eventObj,
1381 record->bytes,
1382 physical,
1383 record->data,
1384 gcvKERNEL_PIXEL);
1385 gcmRELEASE_NAME(record->physical);
1386
1387 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1388 "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
1389 record->data, record->bytes, status);
1390 break;
1391
1392 case gcvDB_SIGNAL:
1393#if USE_NEW_LINUX_SIGNAL
1394 status = gcvSTATUS_NOT_SUPPORTED;
1395#else
1396 /* Free the user signal. */
1397 status = gckOS_DestroyUserSignal(Kernel->os,
1398 gcmPTR2INT32(record->data));
1399#endif /* USE_NEW_LINUX_SIGNAL */
1400
1401 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1402 "DB: SIGNAL %d (status=%d)",
1403 (gctINT)(gctUINTPTR_T)record->data, status);
1404 break;
1405
1406 case gcvDB_VIDEO_MEMORY_LOCKED:
1407 handle = gcmPTR2INT32(record->data);
1408
1409 gcmkERR_BREAK(gckVIDMEM_HANDLE_Lookup(record->kernel,
1410 ProcessID,
1411 handle,
1412 &nodeObject));
1413
1414 /* Unlock what we still locked */
1415 status = gckVIDMEM_Unlock(record->kernel,
1416 nodeObject,
1417 nodeObject->type,
1418 &asynchronous);
1419
1420 {
1421 gcmkVERIFY_OK(gckVIDMEM_HANDLE_Dereference(record->kernel,
1422 ProcessID,
1423 handle));
1424
1425 if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
1426 {
1427 status = gckEVENT_Unlock(record->kernel->eventObj,
1428 gcvKERNEL_PIXEL,
1429 nodeObject,
1430 nodeObject->type);
1431 }
1432 else
1433 {
1434 gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(record->kernel,
1435 nodeObject));
1436 }
1437 }
1438
1439 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1440 "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
1441 record->data, status);
1442 break;
1443
1444 case gcvDB_CONTEXT:
1445 /* TODO: Free the context */
1446 status = gckCOMMAND_Detach(Kernel->command, gcmNAME_TO_PTR(record->data));
1447 gcmRELEASE_NAME(record->data);
1448
1449 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1450 "DB: CONTEXT 0x%x (status=%d)",
1451 record->data, status);
1452 break;
1453
1454 case gcvDB_MAP_MEMORY:
1455 /* Unmap memory. */
1456 status = gckKERNEL_UnmapMemory(Kernel,
1457 record->physical,
1458 record->bytes,
1459 record->data);
1460
1461 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1462 "DB: MAP MEMORY %d (status=%d)",
1463 gcmPTR2INT32(record->data), status);
1464 break;
1465
1466 case gcvDB_MAP_USER_MEMORY:
1467 /* TODO: Unmap user memory. */
1468 status = gckOS_UnmapUserMemory(Kernel->os,
1469 Kernel->core,
1470 record->physical,
1471 record->bytes,
1472 gcmNAME_TO_PTR(record->data),
1473 0);
1474 gcmRELEASE_NAME(record->data);
1475
1476 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1477 "DB: MAP USER MEMORY %d (status=%d)",
1478 gcmPTR2INT32(record->data), status);
1479 break;
1480
1481#if gcdANDROID_NATIVE_FENCE_SYNC
1482 case gcvDB_SYNC_POINT:
1483 /* Free the user signal. */
1484 status = gckOS_DestroySyncPoint(Kernel->os,
1485 (gctSYNC_POINT) record->data);
1486
1487 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1488 "DB: SYNC POINT %d (status=%d)",
1489 (gctINT)(gctUINTPTR_T)record->data, status);
1490 break;
1491#endif
1492
1493 case gcvDB_SHBUF:
1494 /* Free shared buffer. */
1495 status = gckKERNEL_DestroyShBuffer(Kernel,
1496 (gctSHBUF) record->data);
1497
1498 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1499 "DB: SHBUF %u (status=%d)",
1500 (gctUINT32)(gctUINTPTR_T) record->data, status);
1501 break;
1502
1503 default:
1504 gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
1505 "DB: Correcupted record=0x%08x type=%d",
1506 record, record->type);
1507 break;
1508 }
1509
1510 /* Delete the record. */
1511 gcmkONERROR(gckKERNEL_DeleteRecord(Kernel,
1512 database,
1513 record->type,
1514 record->data,
1515 gcvNULL));
1516 }
1517
1518 }
1519
1520 /* Delete the database. */
1521 gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
1522
1523 /* Success. */
1524 gcmkFOOTER_NO();
1525 return gcvSTATUS_OK;
1526
1527OnError:
1528 /* Return the status. */
1529 gcmkFOOTER();
1530 return status;
1531}
1532
1533/*******************************************************************************
1534** gckKERNEL_QueryProcessDB
1535**
1536** Query a process database for the current usage of a particular record type.
1537**
1538** INPUT:
1539**
1540** gckKERNEL Kernel
1541** Pointer to a gckKERNEL object.
1542**
1543** gctUINT32 ProcessID
1544** Process ID used to identify the database.
1545**
1546** gctBOOL LastProcessID
1547** gcvTRUE if searching for the last known process ID. gcvFALSE if
1548** we need to search for the process ID specified by the ProcessID
1549** argument.
1550**
1551** gceDATABASE_TYPE Type
1552** Type of the record to query.
1553**
1554** OUTPUT:
1555**
1556** gcuDATABASE_INFO * Info
1557** Pointer to a variable that receives the requested information.
1558*/
1559gceSTATUS
1560gckKERNEL_QueryProcessDB(
1561 IN gckKERNEL Kernel,
1562 IN gctUINT32 ProcessID,
1563 IN gctBOOL LastProcessID,
1564 IN gceDATABASE_TYPE Type,
1565 OUT gcuDATABASE_INFO * Info
1566 )
1567{
1568 gceSTATUS status;
1569 gcsDATABASE_PTR database;
1570 gcePOOL vidMemPool;
1571
1572 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
1573 Kernel, ProcessID, Type, Info);
1574
1575 /* Verify the arguments. */
1576 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1577 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
1578
1579 /* Deocde pool. */
1580 vidMemPool = (Type & gcdDB_VIDEO_MEMORY_POOL_MASK) >> gcdDB_VIDEO_MEMORY_POOL_SHIFT;
1581
1582 Type &= gcdDATABASE_TYPE_MASK;
1583
1584 /* Find the database. */
1585 gcmkONERROR(
1586 gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
1587
1588
1589 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, database->counterMutex, gcvINFINITE));
1590
1591 /* Get pointer to counters. */
1592 switch (Type)
1593 {
1594 case gcvDB_VIDEO_MEMORY:
1595 if (vidMemPool != gcvPOOL_UNKNOWN)
1596 {
1597 gckOS_MemCopy(&Info->counters,
1598 &database->vidMemPool[vidMemPool],
1599 gcmSIZEOF(database->vidMemPool[vidMemPool]));
1600 }
1601 else
1602 {
1603 gckOS_MemCopy(&Info->counters,
1604 &database->vidMem,
1605 gcmSIZEOF(database->vidMem));
1606 }
1607 break;
1608
1609 case gcvDB_NON_PAGED:
1610 gckOS_MemCopy(&Info->counters,
1611 &database->nonPaged,
1612 gcmSIZEOF(database->vidMem));
1613 break;
1614
1615 case gcvDB_CONTIGUOUS:
1616 gckOS_MemCopy(&Info->counters,
1617 &database->contiguous,
1618 gcmSIZEOF(database->vidMem));
1619 break;
1620
1621 case gcvDB_IDLE:
1622 Info->time = Kernel->db->idleTime;
1623 Kernel->db->idleTime = 0;
1624 break;
1625
1626 case gcvDB_MAP_MEMORY:
1627 gckOS_MemCopy(&Info->counters,
1628 &database->mapMemory,
1629 gcmSIZEOF(database->mapMemory));
1630 break;
1631
1632 case gcvDB_MAP_USER_MEMORY:
1633 gckOS_MemCopy(&Info->counters,
1634 &database->mapUserMemory,
1635 gcmSIZEOF(database->mapUserMemory));
1636 break;
1637
1638 case gcvDB_COMMAND_BUFFER:
1639 gckOS_MemCopy(&Info->counters,
1640 &database->virtualCommandBuffer,
1641 gcmSIZEOF(database->virtualCommandBuffer));
1642 break;
1643
1644 default:
1645 break;
1646 }
1647
1648 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, database->counterMutex));
1649
1650 /* Success. */
1651 gcmkFOOTER_NO();
1652 return gcvSTATUS_OK;
1653
1654OnError:
1655 /* Return the status. */
1656 gcmkFOOTER();
1657 return status;
1658}
1659
1660gceSTATUS
1661gckKERNEL_FindHandleDatbase(
1662 IN gckKERNEL Kernel,
1663 IN gctUINT32 ProcessID,
1664 OUT gctPOINTER * HandleDatabase,
1665 OUT gctPOINTER * HandleDatabaseMutex
1666 )
1667{
1668 gceSTATUS status;
1669 gcsDATABASE_PTR database;
1670
1671 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d",
1672 Kernel, ProcessID);
1673
1674 /* Verify the arguments. */
1675 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1676
1677 /* Find the database. */
1678 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1679
1680 *HandleDatabase = database->handleDatabase;
1681 *HandleDatabaseMutex = database->handleDatabaseMutex;
1682
1683 /* Success. */
1684 gcmkFOOTER_NO();
1685 return gcvSTATUS_OK;
1686
1687OnError:
1688 /* Return the status. */
1689 gcmkFOOTER();
1690 return status;
1691}
1692
1693#if gcdPROCESS_ADDRESS_SPACE
1694gceSTATUS
1695gckKERNEL_GetProcessMMU(
1696 IN gckKERNEL Kernel,
1697 OUT gckMMU * Mmu
1698 )
1699{
1700 gceSTATUS status;
1701 gcsDATABASE_PTR database;
1702 gctUINT32 processID;
1703
1704 gcmkONERROR(gckOS_GetProcessID(&processID));
1705
1706 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, processID, gcvFALSE, &database));
1707
1708 *Mmu = database->mmu;
1709
1710 return gcvSTATUS_OK;
1711
1712OnError:
1713 return status;
1714}
1715#endif
1716
1717#if gcdSECURE_USER
1718/*******************************************************************************
1719** gckKERNEL_GetProcessDBCache
1720**
1721** Get teh secure cache from a process database.
1722**
1723** INPUT:
1724**
1725** gckKERNEL Kernel
1726** Pointer to a gckKERNEL object.
1727**
1728** gctUINT32 ProcessID
1729** Process ID used to identify the database.
1730**
1731** OUTPUT:
1732**
1733** gcskSECURE_CACHE_PTR * Cache
1734** Pointer to a variable that receives the secure cache pointer.
1735*/
1736gceSTATUS
1737gckKERNEL_GetProcessDBCache(
1738 IN gckKERNEL Kernel,
1739 IN gctUINT32 ProcessID,
1740 OUT gcskSECURE_CACHE_PTR * Cache
1741 )
1742{
1743 gceSTATUS status;
1744 gcsDATABASE_PTR database;
1745
1746 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
1747
1748 /* Verify the arguments. */
1749 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1750 gcmkVERIFY_ARGUMENT(Cache != gcvNULL);
1751
1752 /* Find the database. */
1753 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1754
1755 /* Return the pointer to the cache. */
1756 *Cache = &database->cache;
1757
1758 /* Success. */
1759 gcmkFOOTER_ARG("*Cache=0x%x", *Cache);
1760 return gcvSTATUS_OK;
1761
1762OnError:
1763 /* Return the status. */
1764 gcmkFOOTER();
1765 return status;
1766}
1767#endif
1768
1769gceSTATUS
1770gckKERNEL_DumpProcessDB(
1771 IN gckKERNEL Kernel
1772 )
1773{
1774 gcsDATABASE_PTR database;
1775 gctINT i, pid;
1776 gctUINT8 name[24];
1777
1778 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
1779
1780 /* Acquire the database mutex. */
1781 gcmkVERIFY_OK(
1782 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
1783
1784 gcmkPRINT("**************************\n");
1785 gcmkPRINT("*** PROCESS DB DUMP ***\n");
1786 gcmkPRINT("**************************\n");
1787
1788 gcmkPRINT_N(8, "%-8s%s\n", "PID", "NAME");
1789 /* Walk the databases. */
1790 for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
1791 {
1792 for (database = Kernel->db->db[i];
1793 database != gcvNULL;
1794 database = database->next)
1795 {
1796 pid = database->processID;
1797
1798 gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
1799
1800 gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
1801
1802 gcmkPRINT_N(8, "%-8d%s\n", pid, name);
1803 }
1804 }
1805
1806 /* Release the database mutex. */
1807 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
1808
1809 /* Success. */
1810 gcmkFOOTER_NO();
1811 return gcvSTATUS_OK;
1812}
1813
1814void
1815_DumpCounter(
1816 IN gcsDATABASE_COUNTERS * Counter,
1817 IN gctCONST_STRING Name
1818 )
1819{
1820 gcmkPRINT("%s:", Name);
1821 gcmkPRINT(" Currently allocated : %10lld", Counter->bytes);
1822 gcmkPRINT(" Maximum allocated : %10lld", Counter->maxBytes);
1823 gcmkPRINT(" Total allocated : %10lld", Counter->totalBytes);
1824}
1825
1826gceSTATUS
1827gckKERNEL_DumpVidMemUsage(
1828 IN gckKERNEL Kernel,
1829 IN gctINT32 ProcessID
1830 )
1831{
1832 gceSTATUS status;
1833 gcsDATABASE_PTR database;
1834 gcsDATABASE_COUNTERS * counter;
1835 gctUINT32 i = 0;
1836
1837 static gctCONST_STRING surfaceTypes[] = {
1838 "UNKNOWN",
1839 "INDEX",
1840 "VERTEX",
1841 "TEXTURE",
1842 "RENDER_TARGET",
1843 "DEPTH",
1844 "BITMAP",
1845 "TILE_STATUS",
1846 "IMAGE",
1847 "MASK",
1848 "SCISSOR",
1849 "HIERARCHICAL_DEPTH",
1850 };
1851
1852 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d",
1853 Kernel, ProcessID);
1854
1855 /* Verify the arguments. */
1856 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1857
1858 /* Find the database. */
1859 gcmkONERROR(
1860 gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1861
1862 gcmkPRINT("VidMem Usage (Process %d):", ProcessID);
1863
1864 /* Get pointer to counters. */
1865 counter = &database->vidMem;
1866
1867 _DumpCounter(counter, "Total Video Memory");
1868
1869 for (i = 0; i < gcvSURF_NUM_TYPES; i++)
1870 {
1871 counter = &database->vidMemType[i];
1872
1873 _DumpCounter(counter, surfaceTypes[i]);
1874 }
1875
1876 /* Success. */
1877 gcmkFOOTER_NO();
1878 return gcvSTATUS_OK;
1879
1880OnError:
1881 /* Return the status. */
1882 gcmkFOOTER();
1883 return status;
1884}
diff --git a/src/hal/kernel/gc_hal_kernel_debug.c b/src/hal/kernel/gc_hal_kernel_debug.c
new file mode 100755
index 0000000..7bd0c57
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_debug.c
@@ -0,0 +1,2821 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57#include <gc_hal_kernel_debug.h>
58
59/******************************************************************************\
60******************************** Debug Variables *******************************
61\******************************************************************************/
62
63static gceSTATUS _lastError = gcvSTATUS_OK;
64static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
65/*
66_debugZones config value
67Please Reference define in gc_hal_base.h
68*/
69static gctUINT32 _debugZones = gcvZONE_NONE;
70
71/******************************************************************************\
72********************************* Debug Switches *******************************
73\******************************************************************************/
74
75/*
76 gcdBUFFERED_OUTPUT
77
78 When set to non-zero, all output is collected into a buffer with the
79 specified size. Once the buffer gets full, the debug buffer will be
80 printed to the console. gcdBUFFERED_SIZE determines the size of the buffer.
81*/
82#define gcdBUFFERED_OUTPUT 0
83
84/*
85 gcdBUFFERED_SIZE
86
87 When set to non-zero, all output is collected into a buffer with the
88 specified size. Once the buffer gets full, the debug buffer will be
89 printed to the console.
90*/
91#define gcdBUFFERED_SIZE (1024 * 1024 * 2)
92
93/*
94 gcdDMA_BUFFER_COUNT
95
96 If greater then zero, the debugger will attempt to find the command buffer
97 where DMA is currently executing and then print this buffer and
98 (gcdDMA_BUFFER_COUNT - 1) buffers before the current one. If set to zero
99 or the current buffer is not found, all buffers are printed.
100*/
101#define gcdDMA_BUFFER_COUNT 0
102
103/*
104 gcdTHREAD_BUFFERS
105
106 When greater then one, will accumulate messages from the specified number
107 of threads in separate output buffers.
108*/
109#define gcdTHREAD_BUFFERS 1
110
111/*
112 gcdENABLE_OVERFLOW
113
114 When set to non-zero, and the output buffer gets full, instead of being
115 printed, it will be allowed to overflow removing the oldest messages.
116*/
117#define gcdENABLE_OVERFLOW 1
118
119/*
120 gcdSHOW_LINE_NUMBER
121
122 When enabledm each print statement will be preceeded with the current
123 line number.
124*/
125#define gcdSHOW_LINE_NUMBER 0
126
127/*
128 gcdSHOW_PROCESS_ID
129
130 When enabledm each print statement will be preceeded with the current
131 process ID.
132*/
133#define gcdSHOW_PROCESS_ID 0
134
135/*
136 gcdSHOW_THREAD_ID
137
138 When enabledm each print statement will be preceeded with the current
139 thread ID.
140*/
141#define gcdSHOW_THREAD_ID 0
142
143/*
144 gcdSHOW_TIME
145
146 When enabled each print statement will be preceeded with the current
147 high-resolution time.
148*/
149#define gcdSHOW_TIME 0
150
151
152/******************************************************************************\
153****************************** Miscellaneous Macros ****************************
154\******************************************************************************/
155
156#if gcmIS_DEBUG(gcdDEBUG_TRACE)
157# define gcmDBGASSERT(Expression, Format, Value) \
158 if (!(Expression)) \
159 { \
160 _DirectPrint( \
161 "*** gcmDBGASSERT ***************************\n" \
162 " function : %s\n" \
163 " line : %d\n" \
164 " expression : " #Expression "\n" \
165 " actual value : " Format "\n", \
166 __FUNCTION__, __LINE__, Value \
167 ); \
168 }
169#else
170# define gcmDBGASSERT(Expression, Format, Value)
171#endif
172
173#define gcmPTRALIGNMENT(Pointer, Alignemnt) \
174( \
175 gcmALIGN(gcmPTR2INT32(Pointer), Alignemnt) - gcmPTR2INT32(Pointer) \
176)
177
178#if gcdALIGNBYSIZE
179# define gcmISALIGNED(Offset, Alignment) \
180 (((Offset) & ((Alignment) - 1)) == 0)
181
182# define gcmkALIGNPTR(Type, Pointer, Alignment) \
183 Pointer = (Type) gcmINT2PTR(gcmALIGN(gcmPTR2INT32(Pointer), Alignment))
184#else
185# define gcmISALIGNED(Offset, Alignment) \
186 gcvTRUE
187
188# define gcmkALIGNPTR(Type, Pointer, Alignment)
189#endif
190
191#define gcmALIGNSIZE(Offset, Size) \
192 ((Size - Offset) + Size)
193
194#define gcdHAVEPREFIX \
195( \
196 gcdSHOW_TIME \
197 || gcdSHOW_LINE_NUMBER \
198 || gcdSHOW_PROCESS_ID \
199 || gcdSHOW_THREAD_ID \
200)
201
202#if gcdHAVEPREFIX
203
204# define gcdOFFSET 0
205
206#if gcdSHOW_TIME
207#if gcmISALIGNED(gcdOFFSET, 8)
208# define gcdTIMESIZE gcmSIZEOF(gctUINT64)
209# elif gcdOFFSET == 4
210# define gcdTIMESIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
211# else
212# error "Unexpected offset value."
213# endif
214# undef gcdOFFSET
215# define gcdOFFSET 8
216#if !defined(gcdPREFIX_LEADER)
217# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
218# define gcdTIMEFORMAT "0x%016llX"
219# else
220# define gcdTIMEFORMAT ", 0x%016llX"
221# endif
222# else
223# define gcdTIMESIZE 0
224# define gcdTIMEFORMAT
225# endif
226
227#if gcdSHOW_LINE_NUMBER
228#if gcmISALIGNED(gcdOFFSET, 8)
229# define gcdNUMSIZE gcmSIZEOF(gctUINT64)
230# elif gcdOFFSET == 4
231# define gcdNUMSIZE gcmALIGNSIZE(4, gcmSIZEOF(gctUINT64))
232# else
233# error "Unexpected offset value."
234# endif
235# undef gcdOFFSET
236# define gcdOFFSET 8
237#if !defined(gcdPREFIX_LEADER)
238# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT64)
239# define gcdNUMFORMAT "%8llu"
240# else
241# define gcdNUMFORMAT ", %8llu"
242# endif
243# else
244# define gcdNUMSIZE 0
245# define gcdNUMFORMAT
246# endif
247
248#if gcdSHOW_PROCESS_ID
249#if gcmISALIGNED(gcdOFFSET, 4)
250# define gcdPIDSIZE gcmSIZEOF(gctUINT32)
251# else
252# error "Unexpected offset value."
253# endif
254# undef gcdOFFSET
255# define gcdOFFSET 4
256#if !defined(gcdPREFIX_LEADER)
257# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
258# define gcdPIDFORMAT "pid=%5d"
259# else
260# define gcdPIDFORMAT ", pid=%5d"
261# endif
262# else
263# define gcdPIDSIZE 0
264# define gcdPIDFORMAT
265# endif
266
267#if gcdSHOW_THREAD_ID
268#if gcmISALIGNED(gcdOFFSET, 4)
269# define gcdTIDSIZE gcmSIZEOF(gctUINT32)
270# else
271# error "Unexpected offset value."
272# endif
273# undef gcdOFFSET
274# define gcdOFFSET 4
275#if !defined(gcdPREFIX_LEADER)
276# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
277# define gcdTIDFORMAT "tid=%5d"
278# else
279# define gcdTIDFORMAT ", tid=%5d"
280# endif
281# else
282# define gcdTIDSIZE 0
283# define gcdTIDFORMAT
284# endif
285
286# define gcdPREFIX_SIZE \
287 ( \
288 gcdTIMESIZE \
289 + gcdNUMSIZE \
290 + gcdPIDSIZE \
291 + gcdTIDSIZE \
292 )
293
294 static const char * _prefixFormat =
295 "["
296 gcdTIMEFORMAT
297 gcdNUMFORMAT
298 gcdPIDFORMAT
299 gcdTIDFORMAT
300 "] ";
301
302#else
303
304# define gcdPREFIX_LEADER gcmSIZEOF(gctUINT32)
305# define gcdPREFIX_SIZE 0
306
307#endif
308
309/* Assumed largest variable argument leader size. */
310#define gcdVARARG_LEADER gcmSIZEOF(gctUINT64)
311
312/* Alignnments. */
313#if gcdALIGNBYSIZE
314# define gcdPREFIX_ALIGNMENT gcdPREFIX_LEADER
315# define gcdVARARG_ALIGNMENT gcdVARARG_LEADER
316#else
317# define gcdPREFIX_ALIGNMENT 0
318# define gcdVARARG_ALIGNMENT 0
319#endif
320
321#if gcdBUFFERED_OUTPUT
322# define gcdOUTPUTPREFIX _AppendPrefix
323# define gcdOUTPUTSTRING _AppendString
324# define gcdOUTPUTCOPY _AppendCopy
325# define gcdOUTPUTBUFFER _AppendBuffer
326#else
327# define gcdOUTPUTPREFIX _PrintPrefix
328# define gcdOUTPUTSTRING _PrintString
329# define gcdOUTPUTCOPY _PrintString
330# define gcdOUTPUTBUFFER _PrintBuffer
331#endif
332
333/******************************************************************************\
334****************************** Private Structures ******************************
335\******************************************************************************/
336
337typedef enum _gceBUFITEM
338{
339 gceBUFITEM_NONE,
340 gcvBUFITEM_PREFIX,
341 gcvBUFITEM_STRING,
342 gcvBUFITEM_COPY,
343 gcvBUFITEM_BUFFER
344}
345gceBUFITEM;
346
347/* Common item head/buffer terminator. */
348typedef struct _gcsBUFITEM_HEAD * gcsBUFITEM_HEAD_PTR;
349typedef struct _gcsBUFITEM_HEAD
350{
351 gceBUFITEM type;
352}
353gcsBUFITEM_HEAD;
354
355/* String prefix (for ex. [ 1,tid=0x019A]) */
356typedef struct _gcsBUFITEM_PREFIX * gcsBUFITEM_PREFIX_PTR;
357typedef struct _gcsBUFITEM_PREFIX
358{
359 gceBUFITEM type;
360#if gcdHAVEPREFIX
361 gctPOINTER prefixData;
362#endif
363}
364gcsBUFITEM_PREFIX;
365
366/* Buffered string. */
367typedef struct _gcsBUFITEM_STRING * gcsBUFITEM_STRING_PTR;
368typedef struct _gcsBUFITEM_STRING
369{
370 gceBUFITEM type;
371 gctINT indent;
372 gctCONST_STRING message;
373 gctPOINTER messageData;
374 gctUINT messageDataSize;
375}
376gcsBUFITEM_STRING;
377
378/* Buffered string (copy of the string is included with the record). */
379typedef struct _gcsBUFITEM_COPY * gcsBUFITEM_COPY_PTR;
380typedef struct _gcsBUFITEM_COPY
381{
382 gceBUFITEM type;
383 gctINT indent;
384 gctPOINTER messageData;
385 gctUINT messageDataSize;
386}
387gcsBUFITEM_COPY;
388
389/* Memory buffer. */
390typedef struct _gcsBUFITEM_BUFFER * gcsBUFITEM_BUFFER_PTR;
391typedef struct _gcsBUFITEM_BUFFER
392{
393 gceBUFITEM type;
394 gctINT indent;
395 gceDUMP_BUFFER bufferType;
396
397#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
398 gctUINT32 dmaAddress;
399#endif
400
401 gctUINT dataSize;
402 gctUINT32 address;
403#if gcdHAVEPREFIX
404 gctPOINTER prefixData;
405#endif
406}
407gcsBUFITEM_BUFFER;
408
409typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR;
410typedef struct _gcsBUFFERED_OUTPUT
411{
412#if gcdTHREAD_BUFFERS > 1
413 gctUINT32 threadID;
414#endif
415
416#if gcdSHOW_LINE_NUMBER
417 gctUINT64 lineNumber;
418#endif
419
420 gctINT indent;
421
422#if gcdBUFFERED_OUTPUT
423 gctINT start;
424 gctINT index;
425 gctINT count;
426 gctUINT8 buffer[gcdBUFFERED_SIZE];
427#endif
428
429 gcsBUFFERED_OUTPUT_PTR prev;
430 gcsBUFFERED_OUTPUT_PTR next;
431}
432gcsBUFFERED_OUTPUT;
433
434typedef gctUINT (* gcfPRINTSTRING) (
435 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
436 IN gcsBUFITEM_HEAD_PTR Item
437 );
438
439typedef gctINT (* gcfGETITEMSIZE) (
440 IN gcsBUFITEM_HEAD_PTR Item
441 );
442
443/******************************************************************************\
444******************************* Private Variables ******************************
445\******************************************************************************/
446
447static gcsBUFFERED_OUTPUT _outputBuffer[gcdTHREAD_BUFFERS];
448static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL;
449static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL;
450
451/******************************************************************************\
452****************************** Item Size Functions *****************************
453\******************************************************************************/
454
455#if gcdBUFFERED_OUTPUT
456static gctINT
457_GetTerminatorItemSize(
458 IN gcsBUFITEM_HEAD_PTR Item
459 )
460{
461 return gcmSIZEOF(gcsBUFITEM_HEAD);
462}
463
464static gctINT
465_GetPrefixItemSize(
466 IN gcsBUFITEM_HEAD_PTR Item
467 )
468{
469#if gcdHAVEPREFIX
470 gcsBUFITEM_PREFIX_PTR item = (gcsBUFITEM_PREFIX_PTR) Item;
471 gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
472 return vlen + gcdPREFIX_SIZE;
473#else
474 return gcmSIZEOF(gcsBUFITEM_PREFIX);
475#endif
476}
477
478static gctINT
479_GetStringItemSize(
480 IN gcsBUFITEM_HEAD_PTR Item
481 )
482{
483 gcsBUFITEM_STRING_PTR item = (gcsBUFITEM_STRING_PTR) Item;
484 gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
485 return vlen + item->messageDataSize;
486}
487
488static gctINT
489_GetCopyItemSize(
490 IN gcsBUFITEM_HEAD_PTR Item
491 )
492{
493 gcsBUFITEM_COPY_PTR item = (gcsBUFITEM_COPY_PTR) Item;
494 gctUINT vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
495 return vlen + item->messageDataSize;
496}
497
498static gctINT
499_GetBufferItemSize(
500 IN gcsBUFITEM_HEAD_PTR Item
501 )
502{
503#if gcdHAVEPREFIX
504 gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
505 gctUINT vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
506 return vlen + gcdPREFIX_SIZE + item->dataSize;
507#else
508 gcsBUFITEM_BUFFER_PTR item = (gcsBUFITEM_BUFFER_PTR) Item;
509 return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
510#endif
511}
512
513static gcfGETITEMSIZE _itemSize[] =
514{
515 _GetTerminatorItemSize,
516 _GetPrefixItemSize,
517 _GetStringItemSize,
518 _GetCopyItemSize,
519 _GetBufferItemSize
520};
521#endif
522
523/******************************************************************************\
524******************************* Printing Functions *****************************
525\******************************************************************************/
526
527#if gcdDEBUG || gcdBUFFERED_OUTPUT
528static void
529_DirectPrint(
530 gctCONST_STRING Message,
531 ...
532 )
533{
534 gctINT len;
535 char buffer[768];
536 gctARGUMENTS arguments;
537
538 gcmkARGUMENTS_START(arguments, Message);
539 len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), Message, &arguments);
540 gcmkARGUMENTS_END(arguments);
541
542 buffer[len] = '\0';
543 gcmkOUTPUT_STRING(buffer);
544}
545#endif
546
547static int
548_AppendIndent(
549 IN gctINT Indent,
550 IN char * Buffer,
551 IN int BufferSize
552 )
553{
554 gctINT i;
555
556 gctINT len = 0;
557 gctINT indent = Indent % 40;
558
559 for (i = 0; i < indent; i += 1)
560 {
561 Buffer[len++] = ' ';
562 }
563
564 if (indent != Indent)
565 {
566 len += gcmkSPRINTF(
567 Buffer + len, BufferSize - len, " <%d> ", Indent
568 );
569
570 Buffer[len] = '\0';
571 }
572
573 return len;
574}
575
576#if gcdHAVEPREFIX
577static void
578_PrintPrefix(
579 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
580 IN gctPOINTER Data
581 )
582{
583 char buffer[768];
584 gctINT len;
585
586 /* Format the string. */
587 len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, Data);
588 buffer[len] = '\0';
589
590 /* Print the string. */
591 gcmkOUTPUT_STRING(buffer);
592}
593#endif
594
595static void
596_PrintString(
597 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
598 IN gctINT Indent,
599 IN gctCONST_STRING Message,
600 IN gctUINT ArgumentSize,
601 IN gctPOINTER Data
602 )
603{
604 char buffer[768];
605 gctINT len;
606
607 /* Append the indent string. */
608 len = _AppendIndent(Indent, buffer, gcmSIZEOF(buffer));
609
610 /* Format the string. */
611 len += gcmkVSPRINTF(buffer + len, gcmSIZEOF(buffer) - len, Message, Data);
612 buffer[len] = '\0';
613
614 /* Add end-of-line if missing. */
615 if (buffer[len - 1] != '\n')
616 {
617 buffer[len++] = '\n';
618 buffer[len] = '\0';
619 }
620
621 /* Print the string. */
622 gcmkOUTPUT_STRING(buffer);
623}
624
625static void
626_PrintBuffer(
627 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
628 IN gctINT Indent,
629 IN gctPOINTER PrefixData,
630 IN gctPOINTER Data,
631 IN gctUINT Address,
632 IN gctUINT DataSize,
633 IN gceDUMP_BUFFER Type,
634 IN gctUINT32 DmaAddress
635 )
636{
637 static gctCONST_STRING _titleString[] =
638 {
639 "CONTEXT BUFFER",
640 "USER COMMAND BUFFER",
641 "KERNEL COMMAND BUFFER",
642 "LINK BUFFER",
643 "WAIT LINK BUFFER",
644 ""
645 };
646
647 static const gctINT COLUMN_COUNT = 8;
648
649 gctUINT i, count, column, address;
650 gctUINT32_PTR data;
651 gctCHAR buffer[768];
652 gctUINT indent, len;
653 gctBOOL command;
654
655 /* Append space for the prefix. */
656#if gcdHAVEPREFIX
657 indent = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer), _prefixFormat, PrefixData);
658 buffer[indent] = '\0';
659#else
660 indent = 0;
661#endif
662
663 /* Append the indent string. */
664 indent += _AppendIndent(
665 Indent, buffer + indent, gcmSIZEOF(buffer) - indent
666 );
667
668 switch (Type)
669 {
670 case gceDUMP_BUFFER_CONTEXT:
671 case gceDUMP_BUFFER_USER:
672 case gceDUMP_BUFFER_KERNEL:
673 case gceDUMP_BUFFER_LINK:
674 case gceDUMP_BUFFER_WAITLINK:
675 /* Form and print the title string. */
676 gcmkSPRINTF2(
677 buffer + indent, gcmSIZEOF(buffer) - indent,
678 "%s%s\n", _titleString[Type],
679 ((DmaAddress >= Address) && (DmaAddress < Address + DataSize))
680 ? " (CURRENT)" : ""
681 );
682
683 gcmkOUTPUT_STRING(buffer);
684
685 /* Terminate the string. */
686 buffer[indent] = '\0';
687
688 /* This is a command buffer. */
689 command = gcvTRUE;
690 break;
691
692 case gceDUMP_BUFFER_FROM_USER:
693 /* This is not a command buffer. */
694 command = gcvFALSE;
695
696 /* No title. */
697 break;
698
699 default:
700 gcmDBGASSERT(gcvFALSE, "%s", "invalid buffer type");
701
702 /* This is not a command buffer. */
703 command = gcvFALSE;
704 }
705
706 /* Overwrite the prefix with spaces. */
707 for (i = 0; i < indent; i += 1)
708 {
709 buffer[i] = ' ';
710 }
711
712 /* Form and print the opening string. */
713 if (command)
714 {
715 gcmkSPRINTF2(
716 buffer + indent, gcmSIZEOF(buffer) - indent,
717 "@[kernel.command %08X %08X\n", Address, DataSize
718 );
719
720 gcmkOUTPUT_STRING(buffer);
721
722 /* Terminate the string. */
723 buffer[indent] = '\0';
724 }
725
726 /* Get initial address. */
727 address = Address;
728
729 /* Cast the data pointer. */
730 data = (gctUINT32_PTR) Data;
731
732 /* Compute the number of double words. */
733 count = DataSize / gcmSIZEOF(gctUINT32);
734
735 /* Print the buffer. */
736 for (i = 0, len = indent, column = 0; i < count; i += 1)
737 {
738 /* Append the address. */
739 if (column == 0)
740 {
741 len += gcmkSPRINTF(
742 buffer + len, gcmSIZEOF(buffer) - len, "0x%08X:", address
743 );
744 }
745
746 /* Append the data value. */
747 len += gcmkSPRINTF2(
748 buffer + len, gcmSIZEOF(buffer) - len, "%c%08X",
749 (address == DmaAddress)? '>' : ' ', data[i]
750 );
751
752 buffer[len] = '\0';
753
754 /* Update the address. */
755 address += gcmSIZEOF(gctUINT32);
756
757 /* Advance column count. */
758 column += 1;
759
760 /* End of line? */
761 if ((column % COLUMN_COUNT) == 0)
762 {
763 /* Append EOL. */
764 gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
765
766 /* Print the string. */
767 gcmkOUTPUT_STRING(buffer);
768
769 /* Reset. */
770 len = indent;
771 column = 0;
772 }
773 }
774
775 /* Print the last partial string. */
776 if (column != 0)
777 {
778 /* Append EOL. */
779 gcmkSTRCAT(buffer + len, gcmSIZEOF(buffer) - len, "\n");
780
781 /* Print the string. */
782 gcmkOUTPUT_STRING(buffer);
783 }
784
785 /* Form and print the opening string. */
786 if (command)
787 {
788 buffer[indent] = '\0';
789 gcmkSTRCAT(buffer, gcmSIZEOF(buffer), "] -- command\n");
790 gcmkOUTPUT_STRING(buffer);
791 }
792}
793
794#if gcdBUFFERED_OUTPUT
795static gctUINT
796_PrintNone(
797 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
798 IN gcsBUFITEM_HEAD_PTR Item
799 )
800{
801 /* Return the size of the node. */
802 return gcmSIZEOF(gcsBUFITEM_HEAD);
803}
804
805static gctUINT
806_PrintPrefixWrapper(
807 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
808 IN gcsBUFITEM_HEAD_PTR Item
809 )
810{
811#if gcdHAVEPREFIX
812 gcsBUFITEM_PREFIX_PTR item;
813 gctUINT vlen;
814
815 /* Get access to the data. */
816 item = (gcsBUFITEM_PREFIX_PTR) Item;
817
818 /* Print the message. */
819 _PrintPrefix(OutputBuffer, item->prefixData);
820
821 /* Compute the size of the variable portion of the structure. */
822 vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
823
824 /* Return the size of the node. */
825 return vlen + gcdPREFIX_SIZE;
826#else
827 return gcmSIZEOF(gcsBUFITEM_PREFIX);
828#endif
829}
830
831static gctUINT
832_PrintStringWrapper(
833 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
834 IN gcsBUFITEM_HEAD_PTR Item
835 )
836{
837 gcsBUFITEM_STRING_PTR item;
838 gctUINT vlen;
839
840 /* Get access to the data. */
841 item = (gcsBUFITEM_STRING_PTR) Item;
842
843 /* Print the message. */
844 _PrintString(
845 OutputBuffer,
846 item->indent, item->message, item->messageDataSize, item->messageData
847 );
848
849 /* Compute the size of the variable portion of the structure. */
850 vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
851
852 /* Return the size of the node. */
853 return vlen + item->messageDataSize;
854}
855
856static gctUINT
857_PrintCopyWrapper(
858 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
859 IN gcsBUFITEM_HEAD_PTR Item
860 )
861{
862 gcsBUFITEM_COPY_PTR item;
863 gctCONST_STRING message;
864 gctUINT vlen;
865
866 /* Get access to the data. */
867 item = (gcsBUFITEM_COPY_PTR) Item;
868
869 /* Determine the string pointer. */
870 message = (gctCONST_STRING) (item + 1);
871
872 /* Print the message. */
873 _PrintString(
874 OutputBuffer,
875 item->indent, message, item->messageDataSize, item->messageData
876 );
877
878 /* Compute the size of the variable portion of the structure. */
879 vlen = ((gctUINT8_PTR) item->messageData) - ((gctUINT8_PTR) item);
880
881 /* Return the size of the node. */
882 return vlen + item->messageDataSize;
883}
884
885static gctUINT
886_PrintBufferWrapper(
887 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
888 IN gcsBUFITEM_HEAD_PTR Item
889 )
890{
891#if gcdHAVEPREFIX
892 gctUINT32 dmaAddress;
893 gcsBUFITEM_BUFFER_PTR item;
894 gctPOINTER data;
895 gctUINT vlen;
896
897 /* Get access to the data. */
898 item = (gcsBUFITEM_BUFFER_PTR) Item;
899
900#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
901 dmaAddress = item->dmaAddress;
902#else
903 dmaAddress = 0xFFFFFFFF;
904#endif
905
906 if (dmaAddress != 0)
907 {
908 /* Compute the data address. */
909 data = ((gctUINT8_PTR) item->prefixData) + gcdPREFIX_SIZE;
910
911 /* Print buffer. */
912 _PrintBuffer(
913 OutputBuffer,
914 item->indent, item->prefixData,
915 data, item->address, item->dataSize,
916 item->bufferType, dmaAddress
917 );
918 }
919
920 /* Compute the size of the variable portion of the structure. */
921 vlen = ((gctUINT8_PTR) item->prefixData) - ((gctUINT8_PTR) item);
922
923 /* Return the size of the node. */
924 return vlen + gcdPREFIX_SIZE + item->dataSize;
925#else
926 gctUINT32 dmaAddress;
927 gcsBUFITEM_BUFFER_PTR item;
928
929 /* Get access to the data. */
930 item = (gcsBUFITEM_BUFFER_PTR) Item;
931
932#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
933 dmaAddress = item->dmaAddress;
934#else
935 dmaAddress = 0xFFFFFFFF;
936#endif
937
938 if (dmaAddress != 0)
939 {
940 /* Print buffer. */
941 _PrintBuffer(
942 OutputBuffer,
943 item->indent, gcvNULL,
944 item + 1, item->address, item->dataSize,
945 item->bufferType, dmaAddress
946 );
947 }
948
949 /* Return the size of the node. */
950 return gcmSIZEOF(gcsBUFITEM_BUFFER) + item->dataSize;
951#endif
952}
953
954static gcfPRINTSTRING _printArray[] =
955{
956 _PrintNone,
957 _PrintPrefixWrapper,
958 _PrintStringWrapper,
959 _PrintCopyWrapper,
960 _PrintBufferWrapper
961};
962#endif
963
964/******************************************************************************\
965******************************* Private Functions ******************************
966\******************************************************************************/
967
968#if gcdBUFFERED_OUTPUT
969
970#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
971static gcsBUFITEM_BUFFER_PTR
972_FindCurrentDMABuffer(
973 gctUINT32 DmaAddress
974 )
975{
976 gctINT i, skip;
977 gcsBUFITEM_HEAD_PTR item;
978 gcsBUFITEM_BUFFER_PTR dmaCurrent;
979
980 /* Reset the current buffer. */
981 dmaCurrent = gcvNULL;
982
983 /* Get the first stored item. */
984 item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
985
986 /* Run through all items. */
987 for (i = 0; i < _outputBufferHead->count; i += 1)
988 {
989 /* Buffer item? */
990 if (item->type == gcvBUFITEM_BUFFER)
991 {
992 gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
993
994 if ((DmaAddress >= buffer->address) &&
995 (DmaAddress < buffer->address + buffer->dataSize))
996 {
997 dmaCurrent = buffer;
998 }
999 }
1000
1001 /* Get the item size and skip it. */
1002 skip = (* _itemSize[item->type]) (item);
1003 item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
1004
1005 /* End of the buffer? Wrap around. */
1006 if (item->type == gceBUFITEM_NONE)
1007 {
1008 item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
1009 }
1010 }
1011
1012 /* Return result. */
1013 return dmaCurrent;
1014}
1015
1016static void
1017_EnableAllDMABuffers(
1018 void
1019 )
1020{
1021 gctINT i, skip;
1022 gcsBUFITEM_HEAD_PTR item;
1023
1024 /* Get the first stored item. */
1025 item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
1026
1027 /* Run through all items. */
1028 for (i = 0; i < _outputBufferHead->count; i += 1)
1029 {
1030 /* Buffer item? */
1031 if (item->type == gcvBUFITEM_BUFFER)
1032 {
1033 gcsBUFITEM_BUFFER_PTR buffer = (gcsBUFITEM_BUFFER_PTR) item;
1034
1035 /* Enable the buffer. */
1036 buffer->dmaAddress = ~0U;
1037 }
1038
1039 /* Get the item size and skip it. */
1040 skip = (* _itemSize[item->type]) (item);
1041 item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
1042
1043 /* End of the buffer? Wrap around. */
1044 if (item->type == gceBUFITEM_NONE)
1045 {
1046 item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
1047 }
1048 }
1049}
1050
1051static void
1052_EnableDMABuffers(
1053 gctUINT32 DmaAddress,
1054 gcsBUFITEM_BUFFER_PTR CurrentDMABuffer
1055 )
1056{
1057 gctINT i, skip, index;
1058 gcsBUFITEM_HEAD_PTR item;
1059 gcsBUFITEM_BUFFER_PTR buffers[gcdDMA_BUFFER_COUNT];
1060
1061 /* Reset buffer pointers. */
1062 gckOS_ZeroMemory(buffers, gcmSIZEOF(buffers));
1063
1064 /* Set the current buffer index. */
1065 index = -1;
1066
1067 /* Get the first stored item. */
1068 item = (gcsBUFITEM_HEAD_PTR) &_outputBufferHead->buffer[_outputBufferHead->start];
1069
1070 /* Run through all items until the current DMA buffer is found. */
1071 for (i = 0; i < _outputBufferHead->count; i += 1)
1072 {
1073 /* Buffer item? */
1074 if (item->type == gcvBUFITEM_BUFFER)
1075 {
1076 /* Advance the index. */
1077 index = (index + 1) % gcdDMA_BUFFER_COUNT;
1078
1079 /* Add to the buffer array. */
1080 buffers[index] = (gcsBUFITEM_BUFFER_PTR) item;
1081
1082 /* Stop if this is the current DMA buffer. */
1083 if ((gcsBUFITEM_BUFFER_PTR) item == CurrentDMABuffer)
1084 {
1085 break;
1086 }
1087 }
1088
1089 /* Get the item size and skip it. */
1090 skip = (* _itemSize[item->type]) (item);
1091 item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
1092
1093 /* End of the buffer? Wrap around. */
1094 if (item->type == gceBUFITEM_NONE)
1095 {
1096 item = (gcsBUFITEM_HEAD_PTR) _outputBufferHead->buffer;
1097 }
1098 }
1099
1100 /* Enable the found buffers. */
1101 gcmDBGASSERT(index != -1, "%d", index);
1102
1103 for (i = 0; i < gcdDMA_BUFFER_COUNT; i += 1)
1104 {
1105 if (buffers[index] == gcvNULL)
1106 {
1107 break;
1108 }
1109
1110 buffers[index]->dmaAddress = DmaAddress;
1111
1112 index -= 1;
1113
1114 if (index == -1)
1115 {
1116 index = gcdDMA_BUFFER_COUNT - 1;
1117 }
1118 }
1119}
1120#endif
1121
1122static void
1123_Flush(
1124 gctUINT32 DmaAddress
1125 )
1126{
1127 gctINT i, skip;
1128 gcsBUFITEM_HEAD_PTR item;
1129
1130 gcsBUFFERED_OUTPUT_PTR outputBuffer = _outputBufferHead;
1131
1132#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
1133 if ((outputBuffer != gcvNULL) && (outputBuffer->count != 0))
1134 {
1135 /* Find the current DMA buffer. */
1136 gcsBUFITEM_BUFFER_PTR dmaCurrent = _FindCurrentDMABuffer(DmaAddress);
1137
1138 /* Was the current buffer found? */
1139 if (dmaCurrent == gcvNULL)
1140 {
1141 /* No, print all buffers. */
1142 _EnableAllDMABuffers();
1143 }
1144 else
1145 {
1146 /* Yes, enable only specified number of buffers. */
1147 _EnableDMABuffers(DmaAddress, dmaCurrent);
1148 }
1149 }
1150#endif
1151
1152 while (outputBuffer != gcvNULL)
1153 {
1154 if (outputBuffer->count != 0)
1155 {
1156 _DirectPrint("********************************************************************************\n");
1157 _DirectPrint("FLUSHING DEBUG OUTPUT BUFFER (%d elements).\n", outputBuffer->count);
1158 _DirectPrint("********************************************************************************\n");
1159
1160 item = (gcsBUFITEM_HEAD_PTR) &outputBuffer->buffer[outputBuffer->start];
1161
1162 for (i = 0; i < outputBuffer->count; i += 1)
1163 {
1164 skip = (* _printArray[item->type]) (outputBuffer, item);
1165
1166 item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
1167
1168 if (item->type == gceBUFITEM_NONE)
1169 {
1170 item = (gcsBUFITEM_HEAD_PTR) outputBuffer->buffer;
1171 }
1172 }
1173
1174 outputBuffer->start = 0;
1175 outputBuffer->index = 0;
1176 outputBuffer->count = 0;
1177 }
1178
1179 outputBuffer = outputBuffer->next;
1180 }
1181}
1182
1183static gcsBUFITEM_HEAD_PTR
1184_AllocateItem(
1185 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
1186 IN gctINT Size
1187 )
1188{
1189 gctINT skip;
1190 gcsBUFITEM_HEAD_PTR item, next;
1191
1192#if gcdENABLE_OVERFLOW
1193 if (
1194 (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
1195 ||
1196 (
1197 (OutputBuffer->index < OutputBuffer->start) &&
1198 (OutputBuffer->index + Size >= OutputBuffer->start)
1199 )
1200 )
1201 {
1202 if (OutputBuffer->index + Size >= gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
1203 {
1204 if (OutputBuffer->index < OutputBuffer->start)
1205 {
1206 item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
1207
1208 while (item->type != gceBUFITEM_NONE)
1209 {
1210 skip = (* _itemSize[item->type]) (item);
1211
1212 OutputBuffer->start += skip;
1213 OutputBuffer->count -= 1;
1214
1215 item->type = gceBUFITEM_NONE;
1216 item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
1217 }
1218
1219 OutputBuffer->start = 0;
1220 }
1221
1222 OutputBuffer->index = 0;
1223 }
1224
1225 item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->start];
1226
1227 while (OutputBuffer->start - OutputBuffer->index <= Size)
1228 {
1229 skip = (* _itemSize[item->type]) (item);
1230
1231 OutputBuffer->start += skip;
1232 OutputBuffer->count -= 1;
1233
1234 item->type = gceBUFITEM_NONE;
1235 item = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + skip);
1236
1237 if (item->type == gceBUFITEM_NONE)
1238 {
1239 OutputBuffer->start = 0;
1240 break;
1241 }
1242 }
1243 }
1244#else
1245 if (OutputBuffer->index + Size > gcdBUFFERED_SIZE - gcmSIZEOF(gcsBUFITEM_HEAD))
1246 {
1247 _DirectPrint("\nMessage buffer full; forcing message flush.\n\n");
1248 _Flush(~0U);
1249 }
1250#endif
1251
1252 item = (gcsBUFITEM_HEAD_PTR) &OutputBuffer->buffer[OutputBuffer->index];
1253
1254 OutputBuffer->index += Size;
1255 OutputBuffer->count += 1;
1256
1257 next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) item + Size);
1258 next->type = gceBUFITEM_NONE;
1259
1260 return item;
1261}
1262
1263#if gcdALIGNBYSIZE
1264static void
1265_FreeExtraSpace(
1266 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
1267 IN gctPOINTER Item,
1268 IN gctINT ItemSize,
1269 IN gctINT FreeSize
1270 )
1271{
1272 gcsBUFITEM_HEAD_PTR next;
1273
1274 OutputBuffer->index -= FreeSize;
1275
1276 next = (gcsBUFITEM_HEAD_PTR) ((gctUINT8_PTR) Item + ItemSize);
1277 next->type = gceBUFITEM_NONE;
1278}
1279#endif
1280
1281#if gcdHAVEPREFIX
1282static void
1283_AppendPrefix(
1284 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
1285 IN gctPOINTER Data
1286 )
1287{
1288 gctUINT8_PTR prefixData;
1289 gcsBUFITEM_PREFIX_PTR item;
1290 gctINT allocSize;
1291
1292#if gcdALIGNBYSIZE
1293 gctUINT alignment;
1294 gctINT size, freeSize;
1295#endif
1296
1297 gcmDBGASSERT(Data != gcvNULL, "%p", Data);
1298
1299 /* Determine the maximum item size. */
1300 allocSize
1301 = gcmSIZEOF(gcsBUFITEM_PREFIX)
1302 + gcdPREFIX_SIZE
1303 + gcdPREFIX_ALIGNMENT;
1304
1305 /* Allocate prefix item. */
1306 item = (gcsBUFITEM_PREFIX_PTR) _AllocateItem(OutputBuffer, allocSize);
1307
1308 /* Compute the initial prefix data pointer. */
1309 prefixData = (gctUINT8_PTR) (item + 1);
1310
1311 /* Align the data pointer as necessary. */
1312#if gcdALIGNBYSIZE
1313 alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
1314 prefixData += alignment;
1315#endif
1316
1317 /* Set item data. */
1318 item->type = gcvBUFITEM_PREFIX;
1319 item->prefixData = prefixData;
1320
1321 /* Copy argument value. */
1322 gcmkMEMCPY(prefixData, Data, gcdPREFIX_SIZE);
1323
1324#if gcdALIGNBYSIZE
1325 /* Compute the actual node size. */
1326 size = gcmSIZEOF(gcsBUFITEM_PREFIX) + gcdPREFIX_SIZE + alignment;
1327
1328 /* Free extra memory if any. */
1329 freeSize = allocSize - size;
1330 if (freeSize != 0)
1331 {
1332 _FreeExtraSpace(OutputBuffer, item, size, freeSize);
1333 }
1334#endif
1335}
1336#endif
1337
1338static void
1339_AppendString(
1340 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
1341 IN gctINT Indent,
1342 IN gctCONST_STRING Message,
1343 IN gctUINT ArgumentSize,
1344 IN gctPOINTER Data
1345 )
1346{
1347 gctUINT8_PTR messageData;
1348 gcsBUFITEM_STRING_PTR item;
1349 gctINT allocSize;
1350
1351#if gcdALIGNBYSIZE
1352 gctUINT alignment;
1353 gctINT size, freeSize;
1354#endif
1355
1356 /* Determine the maximum item size. */
1357 allocSize
1358 = gcmSIZEOF(gcsBUFITEM_STRING)
1359 + ArgumentSize
1360 + gcdVARARG_ALIGNMENT;
1361
1362 /* Allocate prefix item. */
1363 item = (gcsBUFITEM_STRING_PTR) _AllocateItem(OutputBuffer, allocSize);
1364
1365 /* Compute the initial message data pointer. */
1366 messageData = (gctUINT8_PTR) (item + 1);
1367
1368 /* Align the data pointer as necessary. */
1369#if gcdALIGNBYSIZE
1370 alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
1371 messageData += alignment;
1372#endif
1373
1374 /* Set item data. */
1375 item->type = gcvBUFITEM_STRING;
1376 item->indent = Indent;
1377 item->message = Message;
1378 item->messageData = messageData;
1379 item->messageDataSize = ArgumentSize;
1380
1381 /* Copy argument value. */
1382 if (ArgumentSize != 0)
1383 {
1384 gcmkMEMCPY(messageData, Data, ArgumentSize);
1385 }
1386
1387#if gcdALIGNBYSIZE
1388 /* Compute the actual node size. */
1389 size = gcmSIZEOF(gcsBUFITEM_STRING) + ArgumentSize + alignment;
1390
1391 /* Free extra memory if any. */
1392 freeSize = allocSize - size;
1393 if (freeSize != 0)
1394 {
1395 _FreeExtraSpace(OutputBuffer, item, size, freeSize);
1396 }
1397#endif
1398}
1399
1400static void
1401_AppendCopy(
1402 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
1403 IN gctINT Indent,
1404 IN gctCONST_STRING Message,
1405 IN gctUINT ArgumentSize,
1406 IN gctPOINTER Data
1407 )
1408{
1409 gctUINT8_PTR messageData;
1410 gcsBUFITEM_COPY_PTR item;
1411 gctINT allocSize;
1412 gctINT messageLength;
1413 gctCONST_STRING message;
1414
1415#if gcdALIGNBYSIZE
1416 gctUINT alignment;
1417 gctINT size, freeSize;
1418#endif
1419
1420 /* Get the length of the string. */
1421 messageLength = strlen(Message) + 1;
1422
1423 /* Determine the maximum item size. */
1424 allocSize
1425 = gcmSIZEOF(gcsBUFITEM_COPY)
1426 + messageLength
1427 + ArgumentSize
1428 + gcdVARARG_ALIGNMENT;
1429
1430 /* Allocate prefix item. */
1431 item = (gcsBUFITEM_COPY_PTR) _AllocateItem(OutputBuffer, allocSize);
1432
1433 /* Determine the message placement. */
1434 message = (gctCONST_STRING) (item + 1);
1435
1436 /* Compute the initial message data pointer. */
1437 messageData = (gctUINT8_PTR) message + messageLength;
1438
1439 /* Align the data pointer as necessary. */
1440#if gcdALIGNBYSIZE
1441 if (ArgumentSize == 0)
1442 {
1443 alignment = 0;
1444 }
1445 else
1446 {
1447 alignment = gcmPTRALIGNMENT(messageData, gcdVARARG_ALIGNMENT);
1448 messageData += alignment;
1449 }
1450#endif
1451
1452 /* Set item data. */
1453 item->type = gcvBUFITEM_COPY;
1454 item->indent = Indent;
1455 item->messageData = messageData;
1456 item->messageDataSize = ArgumentSize;
1457
1458 /* Copy the message. */
1459 gcmkMEMCPY((gctPOINTER) message, Message, messageLength);
1460
1461 /* Copy argument value. */
1462 if (ArgumentSize != 0)
1463 {
1464 gcmkMEMCPY(messageData, Data, ArgumentSize);
1465 }
1466
1467#if gcdALIGNBYSIZE
1468 /* Compute the actual node size. */
1469 size
1470 = gcmSIZEOF(gcsBUFITEM_COPY)
1471 + messageLength
1472 + ArgumentSize
1473 + alignment;
1474
1475 /* Free extra memory if any. */
1476 freeSize = allocSize - size;
1477 if (freeSize != 0)
1478 {
1479 _FreeExtraSpace(OutputBuffer, item, size, freeSize);
1480 }
1481#endif
1482}
1483
1484static void
1485_AppendBuffer(
1486 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
1487 IN gctINT Indent,
1488 IN gctPOINTER PrefixData,
1489 IN gctPOINTER Data,
1490 IN gctUINT Address,
1491 IN gctUINT DataSize,
1492 IN gceDUMP_BUFFER Type,
1493 IN gctUINT32 DmaAddress
1494 )
1495{
1496#if gcdHAVEPREFIX
1497 gctUINT8_PTR prefixData;
1498 gcsBUFITEM_BUFFER_PTR item;
1499 gctINT allocSize;
1500 gctPOINTER data;
1501
1502#if gcdALIGNBYSIZE
1503 gctUINT alignment;
1504 gctINT size, freeSize;
1505#endif
1506
1507 gcmDBGASSERT(DataSize != 0, "%d", DataSize);
1508 gcmDBGASSERT(Data != gcvNULL, "%p", Data);
1509
1510 /* Determine the maximum item size. */
1511 allocSize
1512 = gcmSIZEOF(gcsBUFITEM_BUFFER)
1513 + gcdPREFIX_SIZE
1514 + gcdPREFIX_ALIGNMENT
1515 + DataSize;
1516
1517 /* Allocate prefix item. */
1518 item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, allocSize);
1519
1520 /* Compute the initial prefix data pointer. */
1521 prefixData = (gctUINT8_PTR) (item + 1);
1522
1523#if gcdALIGNBYSIZE
1524 /* Align the data pointer as necessary. */
1525 alignment = gcmPTRALIGNMENT(prefixData, gcdPREFIX_ALIGNMENT);
1526 prefixData += alignment;
1527#endif
1528
1529 /* Set item data. */
1530 item->type = gcvBUFITEM_BUFFER;
1531 item->indent = Indent;
1532 item->bufferType = Type;
1533 item->dataSize = DataSize;
1534 item->address = Address;
1535 item->prefixData = prefixData;
1536
1537#if gcdDMA_BUFFER_COUNT && (gcdTHREAD_BUFFERS == 1)
1538 item->dmaAddress = DmaAddress;
1539#endif
1540
1541 /* Copy prefix data. */
1542 gcmkMEMCPY(prefixData, PrefixData, gcdPREFIX_SIZE);
1543
1544 /* Compute the data pointer. */
1545 data = prefixData + gcdPREFIX_SIZE;
1546
1547 /* Copy argument value. */
1548 gcmkMEMCPY(data, Data, DataSize);
1549
1550#if gcdALIGNBYSIZE
1551 /* Compute the actual node size. */
1552 size
1553 = gcmSIZEOF(gcsBUFITEM_BUFFER)
1554 + gcdPREFIX_SIZE
1555 + alignment
1556 + DataSize;
1557
1558 /* Free extra memory if any. */
1559 freeSize = allocSize - size;
1560 if (freeSize != 0)
1561 {
1562 _FreeExtraSpace(OutputBuffer, item, size, freeSize);
1563 }
1564#endif
1565#else
1566 gcsBUFITEM_BUFFER_PTR item;
1567 gctINT size;
1568
1569 gcmDBGASSERT(DataSize != 0, "%d", DataSize);
1570 gcmDBGASSERT(Data != gcvNULL, "%p", Data);
1571
1572 /* Determine the maximum item size. */
1573 size = gcmSIZEOF(gcsBUFITEM_BUFFER) + DataSize;
1574
1575 /* Allocate prefix item. */
1576 item = (gcsBUFITEM_BUFFER_PTR) _AllocateItem(OutputBuffer, size);
1577
1578 /* Set item data. */
1579 item->type = gcvBUFITEM_BUFFER;
1580 item->indent = Indent;
1581 item->dataSize = DataSize;
1582 item->address = Address;
1583
1584 /* Copy argument value. */
1585 gcmkMEMCPY(item + 1, Data, DataSize);
1586#endif
1587}
1588#endif
1589
1590static gcmINLINE void
1591_InitBuffers(
1592 void
1593 )
1594{
1595 int i;
1596
1597 if (_outputBufferHead == gcvNULL)
1598 {
1599 for (i = 0; i < gcdTHREAD_BUFFERS; i += 1)
1600 {
1601 if (_outputBufferTail == gcvNULL)
1602 {
1603 _outputBufferHead = &_outputBuffer[i];
1604 }
1605 else
1606 {
1607 _outputBufferTail->next = &_outputBuffer[i];
1608 }
1609
1610#if gcdTHREAD_BUFFERS > 1
1611 _outputBuffer[i].threadID = ~0U;
1612#endif
1613
1614 _outputBuffer[i].prev = _outputBufferTail;
1615 _outputBuffer[i].next = gcvNULL;
1616
1617 _outputBufferTail = &_outputBuffer[i];
1618 }
1619 }
1620}
1621
1622static gcmINLINE gcsBUFFERED_OUTPUT_PTR
1623_GetOutputBuffer(
1624 void
1625 )
1626{
1627 gcsBUFFERED_OUTPUT_PTR outputBuffer;
1628
1629#if gcdTHREAD_BUFFERS > 1
1630 /* Get the current thread ID. */
1631 gctUINT32 ThreadID = gcmkGETTHREADID();
1632
1633 /* Locate the output buffer for the thread. */
1634 outputBuffer = _outputBufferHead;
1635
1636 while (outputBuffer != gcvNULL)
1637 {
1638 if (outputBuffer->threadID == ThreadID)
1639 {
1640 break;
1641 }
1642
1643 outputBuffer = outputBuffer->next;
1644 }
1645
1646 /* No matching buffer found? */
1647 if (outputBuffer == gcvNULL)
1648 {
1649 /* Get the tail for the buffer. */
1650 outputBuffer = _outputBufferTail;
1651
1652 /* Move it to the head. */
1653 _outputBufferTail = _outputBufferTail->prev;
1654 _outputBufferTail->next = gcvNULL;
1655
1656 outputBuffer->prev = gcvNULL;
1657 outputBuffer->next = _outputBufferHead;
1658
1659 _outputBufferHead->prev = outputBuffer;
1660 _outputBufferHead = outputBuffer;
1661
1662 /* Reset the buffer. */
1663 outputBuffer->threadID = ThreadID;
1664#if gcdBUFFERED_OUTPUT
1665 outputBuffer->start = 0;
1666 outputBuffer->index = 0;
1667 outputBuffer->count = 0;
1668#endif
1669#if gcdSHOW_LINE_NUMBER
1670 outputBuffer->lineNumber = 0;
1671#endif
1672 }
1673#else
1674 outputBuffer = _outputBufferHead;
1675#endif
1676
1677 return outputBuffer;
1678}
1679
1680static gcmINLINE int _GetArgumentSize(
1681 IN gctCONST_STRING Message
1682 )
1683{
1684 int i, count;
1685
1686 gcmDBGASSERT(Message != gcvNULL, "%p", Message);
1687
1688 for (i = 0, count = 0; Message[i]; i += 1)
1689 {
1690 if (Message[i] == '%')
1691 {
1692 count += 1;
1693 }
1694 }
1695
1696 return count * gcmSIZEOF(gctUINT32);
1697}
1698
1699#if gcdHAVEPREFIX
1700static void
1701_InitPrefixData(
1702 IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
1703 IN gctPOINTER Data
1704 )
1705{
1706 gctUINT8_PTR data = (gctUINT8_PTR) Data;
1707
1708#if gcdSHOW_TIME
1709 {
1710 gctUINT64 time;
1711 gckOS_GetProfileTick(&time);
1712 gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
1713 * ((gctUINT64_PTR) data) = time;
1714 data += gcmSIZEOF(gctUINT64);
1715 }
1716#endif
1717
1718#if gcdSHOW_LINE_NUMBER
1719 {
1720 gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT64));
1721 * ((gctUINT64_PTR) data) = OutputBuffer->lineNumber;
1722 data += gcmSIZEOF(gctUINT64);
1723 }
1724#endif
1725
1726#if gcdSHOW_PROCESS_ID
1727 {
1728 gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
1729 * ((gctUINT32_PTR) data) = gcmkGETPROCESSID();
1730 data += gcmSIZEOF(gctUINT32);
1731 }
1732#endif
1733
1734#if gcdSHOW_THREAD_ID
1735 {
1736 gcmkALIGNPTR(gctUINT8_PTR, data, gcmSIZEOF(gctUINT32));
1737 * ((gctUINT32_PTR) data) = gcmkGETTHREADID();
1738 }
1739#endif
1740}
1741#endif
1742
1743static void
1744_Print(
1745 IN gctUINT ArgumentSize,
1746 IN gctBOOL CopyMessage,
1747 IN gctCONST_STRING Message,
1748 IN gctARGUMENTS * Arguments
1749 )
1750{
1751 gcsBUFFERED_OUTPUT_PTR outputBuffer;
1752 gcmkDECLARE_LOCK(lockHandle);
1753
1754 gcmkLOCKSECTION(lockHandle);
1755
1756 /* Initialize output buffer list. */
1757 _InitBuffers();
1758
1759 /* Locate the proper output buffer. */
1760 outputBuffer = _GetOutputBuffer();
1761
1762 /* Update the line number. */
1763#if gcdSHOW_LINE_NUMBER
1764 outputBuffer->lineNumber += 1;
1765#endif
1766
1767 /* Print prefix. */
1768#if gcdHAVEPREFIX
1769 {
1770 gctUINT8_PTR alignedPrefixData;
1771 gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
1772
1773 /* Compute aligned pointer. */
1774 alignedPrefixData = prefixData;
1775 gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
1776
1777 /* Initialize the prefix data. */
1778 _InitPrefixData(outputBuffer, alignedPrefixData);
1779
1780 /* Print the prefix. */
1781 gcdOUTPUTPREFIX(outputBuffer, alignedPrefixData);
1782 }
1783#endif
1784
1785 /* Form the indent string. */
1786 if (strncmp(Message, "--", 2) == 0)
1787 {
1788 outputBuffer->indent -= 2;
1789 }
1790
1791 /* Print the message. */
1792 if (CopyMessage)
1793 {
1794 gcdOUTPUTCOPY(
1795 outputBuffer, outputBuffer->indent,
1796 Message, ArgumentSize, (gctPOINTER) Arguments
1797 );
1798 }
1799 else
1800 {
1801 gcdOUTPUTSTRING(
1802 outputBuffer, outputBuffer->indent,
1803 Message, ArgumentSize, ((gctPOINTER) Arguments)
1804 );
1805 }
1806
1807 /* Check increasing indent. */
1808 if (strncmp(Message, "++", 2) == 0)
1809 {
1810 outputBuffer->indent += 2;
1811 }
1812
1813 gcmkUNLOCKSECTION(lockHandle);
1814}
1815
1816
1817/******************************************************************************\
1818********************************* Debug Macros *********************************
1819\******************************************************************************/
1820
1821#ifdef __QNXNTO__
1822
1823extern volatile unsigned g_nQnxInIsrs;
1824
1825#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
1826{ \
1827 if (atomic_add_value(&g_nQnxInIsrs, 1) == 0) \
1828 { \
1829 gctARGUMENTS __arguments__; \
1830 gcmkARGUMENTS_START(__arguments__, Message); \
1831 _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
1832 gcmkARGUMENTS_END(__arguments__); \
1833 } \
1834 atomic_sub(&g_nQnxInIsrs, 1); \
1835}
1836
1837#else
1838
1839#define gcmDEBUGPRINT(ArgumentSize, CopyMessage, Message) \
1840{ \
1841 gctARGUMENTS __arguments__; \
1842 gcmkARGUMENTS_START(__arguments__, Message); \
1843 _Print(ArgumentSize, CopyMessage, Message, &__arguments__); \
1844 gcmkARGUMENTS_END(__arguments__); \
1845}
1846
1847#endif
1848
1849/******************************************************************************\
1850********************************** Debug Code **********************************
1851\******************************************************************************/
1852
1853/*******************************************************************************
1854**
1855** gckOS_Print
1856**
1857** Send a message to the debugger.
1858**
1859** INPUT:
1860**
1861** gctCONST_STRING Message
1862** Pointer to message.
1863**
1864** ...
1865** Optional arguments.
1866**
1867** OUTPUT:
1868**
1869** Nothing.
1870*/
1871
1872void
1873gckOS_Print(
1874 IN gctCONST_STRING Message,
1875 ...
1876 )
1877{
1878 gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
1879}
1880
1881/*******************************************************************************
1882**
1883** gckOS_PrintN
1884**
1885** Send a message to the debugger.
1886**
1887** INPUT:
1888**
1889** gctUINT ArgumentSize
1890** The size of the optional arguments in bytes.
1891**
1892** gctCONST_STRING Message
1893** Pointer to message.
1894**
1895** ...
1896** Optional arguments.
1897**
1898** OUTPUT:
1899**
1900** Nothing.
1901*/
1902
1903void
1904gckOS_PrintN(
1905 IN gctUINT ArgumentSize,
1906 IN gctCONST_STRING Message,
1907 ...
1908 )
1909{
1910 gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
1911}
1912
1913/*******************************************************************************
1914**
1915** gckOS_CopyPrint
1916**
1917** Send a message to the debugger. If in buffered output mode, the entire
1918** message will be copied into the buffer instead of using the pointer to
1919** the string.
1920**
1921** INPUT:
1922**
1923** gctCONST_STRING Message
1924** Pointer to message.
1925**
1926** ...
1927** Optional arguments.
1928**
1929** OUTPUT:
1930**
1931** Nothing.
1932*/
1933
1934void
1935gckOS_CopyPrint(
1936 IN gctCONST_STRING Message,
1937 ...
1938 )
1939{
1940 gcmDEBUGPRINT(_GetArgumentSize(Message), gcvTRUE, Message);
1941}
1942
1943/*******************************************************************************
1944**
1945** gckOS_DumpBuffer
1946**
1947** Print the contents of the specified buffer.
1948**
1949** INPUT:
1950**
1951** gckOS Os
1952** Pointer to gckOS object.
1953**
1954** gctPOINTER Buffer
1955** Pointer to the buffer to print.
1956**
1957** gctUINT Size
1958** Size of the buffer.
1959**
1960** gceDUMP_BUFFER Type
1961** Buffer type.
1962**
1963** OUTPUT:
1964**
1965** Nothing.
1966*/
1967
1968void
1969gckOS_DumpBuffer(
1970 IN gckOS Os,
1971 IN gctPOINTER Buffer,
1972 IN gctUINT Size,
1973 IN gceDUMP_BUFFER Type,
1974 IN gctBOOL CopyMessage
1975 )
1976{
1977 gctPHYS_ADDR_T physical;
1978 gctUINT32 address = 0;
1979 gcsBUFFERED_OUTPUT_PTR outputBuffer = gcvNULL;
1980 static gctBOOL userLocked;
1981 gctCHAR *buffer = (gctCHAR*)Buffer;
1982
1983 gcmkDECLARE_LOCK(lockHandle);
1984
1985 /* Request lock when not coming from user,
1986 or coming from user and not yet locked
1987 and message is starting with @[. */
1988 if (Type == gceDUMP_BUFFER_FROM_USER)
1989 {
1990 if ((Size > 2)
1991 && (buffer[0] == '@')
1992 && (buffer[1] == '['))
1993 {
1994 /* Beginning of a user dump. */
1995 gcmkLOCKSECTION(lockHandle);
1996 userLocked = gcvTRUE;
1997 }
1998 /* Else, let it pass through. */
1999 }
2000 else
2001 {
2002 gcmkLOCKSECTION(lockHandle);
2003 userLocked = gcvFALSE;
2004 }
2005
2006 if (Buffer != gcvNULL)
2007 {
2008 /* Initialize output buffer list. */
2009 _InitBuffers();
2010
2011 /* Locate the proper output buffer. */
2012 outputBuffer = _GetOutputBuffer();
2013
2014 /* Update the line number. */
2015#if gcdSHOW_LINE_NUMBER
2016 outputBuffer->lineNumber += 1;
2017#endif
2018
2019 /* Get the physical address of the buffer. */
2020 if (Type != gceDUMP_BUFFER_FROM_USER)
2021 {
2022 gcmkVERIFY_OK(gckOS_GetPhysicalAddress(Os, Buffer, &physical));
2023 gcmkSAFECASTPHYSADDRT(address, physical);
2024 }
2025 else
2026 {
2027 address = 0;
2028 }
2029
2030#if gcdHAVEPREFIX
2031 {
2032 gctUINT8_PTR alignedPrefixData;
2033 gctUINT8 prefixData[gcdPREFIX_SIZE + gcdPREFIX_ALIGNMENT];
2034
2035 /* Compute aligned pointer. */
2036 alignedPrefixData = prefixData;
2037 gcmkALIGNPTR(gctUINT8_PTR, alignedPrefixData, gcdPREFIX_ALIGNMENT);
2038
2039 /* Initialize the prefix data. */
2040 _InitPrefixData(outputBuffer, alignedPrefixData);
2041
2042 /* Print/schedule the buffer. */
2043 gcdOUTPUTBUFFER(
2044 outputBuffer, outputBuffer->indent,
2045 alignedPrefixData, Buffer, address, Size, Type, 0
2046 );
2047 }
2048#else
2049 /* Print/schedule the buffer. */
2050 if (Type == gceDUMP_BUFFER_FROM_USER)
2051 {
2052 gcdOUTPUTSTRING(
2053 outputBuffer, outputBuffer->indent,
2054 Buffer, 0, gcvNULL
2055 );
2056 }
2057 else
2058 {
2059 gcdOUTPUTBUFFER(
2060 outputBuffer, outputBuffer->indent,
2061 gcvNULL, Buffer, address, Size, Type, 0
2062 );
2063 }
2064#endif
2065 }
2066
2067 /* Unlock when not coming from user,
2068 or coming from user and not yet locked. */
2069 if (userLocked)
2070 {
2071 if ((Size > 4)
2072 && (buffer[0] == ']')
2073 && (buffer[1] == ' ')
2074 && (buffer[2] == '-')
2075 && (buffer[3] == '-'))
2076 {
2077 /* End of a user dump. */
2078 gcmkUNLOCKSECTION(lockHandle);
2079 userLocked = gcvFALSE;
2080 }
2081 /* Else, let it pass through, don't unlock. */
2082 }
2083 else
2084 {
2085 gcmkUNLOCKSECTION(lockHandle);
2086 }
2087}
2088
2089/*******************************************************************************
2090**
2091** gckOS_DebugTrace
2092**
2093** Send a leveled message to the debugger.
2094**
2095** INPUT:
2096**
2097** gctUINT32 Level
2098** Debug level of message.
2099**
2100** gctCONST_STRING Message
2101** Pointer to message.
2102**
2103** ...
2104** Optional arguments.
2105**
2106** OUTPUT:
2107**
2108** Nothing.
2109*/
2110
2111void
2112gckOS_DebugTrace(
2113 IN gctUINT32 Level,
2114 IN gctCONST_STRING Message,
2115 ...
2116 )
2117{
2118 if (Level > _debugLevel)
2119 {
2120 return;
2121 }
2122
2123 gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
2124}
2125
2126/*******************************************************************************
2127**
2128** gckOS_DebugTraceN
2129**
2130** Send a leveled message to the debugger.
2131**
2132** INPUT:
2133**
2134** gctUINT32 Level
2135** Debug level of message.
2136**
2137** gctUINT ArgumentSize
2138** The size of the optional arguments in bytes.
2139**
2140** gctCONST_STRING Message
2141** Pointer to message.
2142**
2143** ...
2144** Optional arguments.
2145**
2146** OUTPUT:
2147**
2148** Nothing.
2149*/
2150
2151void
2152gckOS_DebugTraceN(
2153 IN gctUINT32 Level,
2154 IN gctUINT ArgumentSize,
2155 IN gctCONST_STRING Message,
2156 ...
2157 )
2158{
2159 if (Level > _debugLevel)
2160 {
2161 return;
2162 }
2163
2164 gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
2165}
2166
2167/*******************************************************************************
2168**
2169** gckOS_DebugTraceZone
2170**
2171** Send a leveled and zoned message to the debugger.
2172**
2173** INPUT:
2174**
2175** gctUINT32 Level
2176** Debug level for message.
2177**
2178** gctUINT32 Zone
2179** Debug zone for message.
2180**
2181** gctCONST_STRING Message
2182** Pointer to message.
2183**
2184** ...
2185** Optional arguments.
2186**
2187** OUTPUT:
2188**
2189** Nothing.
2190*/
2191
2192void
2193gckOS_DebugTraceZone(
2194 IN gctUINT32 Level,
2195 IN gctUINT32 Zone,
2196 IN gctCONST_STRING Message,
2197 ...
2198 )
2199{
2200 if ((Level > _debugLevel) || !(Zone & _debugZones))
2201 {
2202 return;
2203 }
2204
2205 gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
2206}
2207
2208/*******************************************************************************
2209**
2210** gckOS_DebugTraceZoneN
2211**
2212** Send a leveled and zoned message to the debugger.
2213**
2214** INPUT:
2215**
2216** gctUINT32 Level
2217** Debug level for message.
2218**
2219** gctUINT32 Zone
2220** Debug zone for message.
2221**
2222** gctUINT ArgumentSize
2223** The size of the optional arguments in bytes.
2224**
2225** gctCONST_STRING Message
2226** Pointer to message.
2227**
2228** ...
2229** Optional arguments.
2230**
2231** OUTPUT:
2232**
2233** Nothing.
2234*/
2235
2236void
2237gckOS_DebugTraceZoneN(
2238 IN gctUINT32 Level,
2239 IN gctUINT32 Zone,
2240 IN gctUINT ArgumentSize,
2241 IN gctCONST_STRING Message,
2242 ...
2243 )
2244{
2245 if ((Level > _debugLevel) || !(Zone & _debugZones))
2246 {
2247 return;
2248 }
2249
2250 gcmDEBUGPRINT(ArgumentSize, gcvFALSE, Message);
2251}
2252
2253/*******************************************************************************
2254**
2255** gckOS_DebugBreak
2256**
2257** Break into the debugger.
2258**
2259** INPUT:
2260**
2261** Nothing.
2262**
2263** OUTPUT:
2264**
2265** Nothing.
2266*/
2267void
2268gckOS_DebugBreak(
2269 void
2270 )
2271{
2272 gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__);
2273}
2274
2275/*******************************************************************************
2276**
2277** gckOS_DebugFatal
2278**
2279** Send a message to the debugger and break into the debugger.
2280**
2281** INPUT:
2282**
2283** gctCONST_STRING Message
2284** Pointer to message.
2285**
2286** ...
2287** Optional arguments.
2288**
2289** OUTPUT:
2290**
2291** Nothing.
2292*/
2293void
2294gckOS_DebugFatal(
2295 IN gctCONST_STRING Message,
2296 ...
2297 )
2298{
2299 gcmkPRINT_VERSION();
2300 gcmDEBUGPRINT(_GetArgumentSize(Message), gcvFALSE, Message);
2301
2302 /* Break into the debugger. */
2303 gckOS_DebugBreak();
2304}
2305
2306/*******************************************************************************
2307**
2308** gckOS_SetDebugLevel
2309**
2310** Set the debug level.
2311**
2312** INPUT:
2313**
2314** gctUINT32 Level
2315** New debug level.
2316**
2317** OUTPUT:
2318**
2319** Nothing.
2320*/
2321
2322void
2323gckOS_SetDebugLevel(
2324 IN gctUINT32 Level
2325 )
2326{
2327 _debugLevel = Level;
2328}
2329
2330/*******************************************************************************
2331**
2332** gckOS_SetDebugZone
2333**
2334** Set the debug zone.
2335**
2336** INPUT:
2337**
2338** gctUINT32 Zone
2339** New debug zone.
2340**
2341** OUTPUT:
2342**
2343** Nothing.
2344*/
2345void
2346gckOS_SetDebugZone(
2347 IN gctUINT32 Zone
2348 )
2349{
2350 _debugZones = Zone;
2351}
2352
2353/*******************************************************************************
2354**
2355** gckOS_SetDebugLevelZone
2356**
2357** Set the debug level and zone.
2358**
2359** INPUT:
2360**
2361** gctUINT32 Level
2362** New debug level.
2363**
2364** gctUINT32 Zone
2365** New debug zone.
2366**
2367** OUTPUT:
2368**
2369** Nothing.
2370*/
2371
2372void
2373gckOS_SetDebugLevelZone(
2374 IN gctUINT32 Level,
2375 IN gctUINT32 Zone
2376 )
2377{
2378 _debugLevel = Level;
2379 _debugZones = Zone;
2380}
2381
2382/*******************************************************************************
2383**
2384** gckOS_SetDebugZones
2385**
2386** Enable or disable debug zones.
2387**
2388** INPUT:
2389**
2390** gctUINT32 Zones
2391** Debug zones to enable or disable.
2392**
2393** gctBOOL Enable
2394** Set to gcvTRUE to enable the zones (or the Zones with the current
2395** zones) or gcvFALSE to disable the specified Zones.
2396**
2397** OUTPUT:
2398**
2399** Nothing.
2400*/
2401
2402void
2403gckOS_SetDebugZones(
2404 IN gctUINT32 Zones,
2405 IN gctBOOL Enable
2406 )
2407{
2408 if (Enable)
2409 {
2410 /* Enable the zones. */
2411 _debugZones |= Zones;
2412 }
2413 else
2414 {
2415 /* Disable the zones. */
2416 _debugZones &= ~Zones;
2417 }
2418}
2419
2420/*******************************************************************************
2421**
2422** gckOS_Verify
2423**
2424** Called to verify the result of a function call.
2425**
2426** INPUT:
2427**
2428** gceSTATUS Status
2429** Function call result.
2430**
2431** OUTPUT:
2432**
2433** Nothing.
2434*/
2435
2436void
2437gckOS_Verify(
2438 IN gceSTATUS status
2439 )
2440{
2441 _lastError = status;
2442}
2443
2444/*******************************************************************************
2445**
2446** gckOS_DebugFlush
2447**
2448** Force messages to be flushed out.
2449**
2450** INPUT:
2451**
2452** gctCONST_STRING CallerName
2453** Name of the caller function.
2454**
2455** gctUINT LineNumber
2456** Line number of the caller.
2457**
2458** gctUINT32 DmaAddress
2459** The current DMA address or ~0U to ignore.
2460**
2461** OUTPUT:
2462**
2463** Nothing.
2464*/
2465
2466void
2467gckOS_DebugFlush(
2468 gctCONST_STRING CallerName,
2469 gctUINT LineNumber,
2470 gctUINT32 DmaAddress
2471 )
2472{
2473#if gcdBUFFERED_OUTPUT
2474 _DirectPrint("\nFlush requested by %s(%d).\n\n", CallerName, LineNumber);
2475 _Flush(DmaAddress);
2476#endif
2477}
2478gctCONST_STRING
2479gckOS_DebugStatus2Name(
2480 gceSTATUS status
2481 )
2482{
2483 switch (status)
2484 {
2485 case gcvSTATUS_OK:
2486 return "gcvSTATUS_OK";
2487 case gcvSTATUS_TRUE:
2488 return "gcvSTATUS_TRUE";
2489 case gcvSTATUS_NO_MORE_DATA:
2490 return "gcvSTATUS_NO_MORE_DATA";
2491 case gcvSTATUS_CACHED:
2492 return "gcvSTATUS_CACHED";
2493 case gcvSTATUS_MIPMAP_TOO_LARGE:
2494 return "gcvSTATUS_MIPMAP_TOO_LARGE";
2495 case gcvSTATUS_NAME_NOT_FOUND:
2496 return "gcvSTATUS_NAME_NOT_FOUND";
2497 case gcvSTATUS_NOT_OUR_INTERRUPT:
2498 return "gcvSTATUS_NOT_OUR_INTERRUPT";
2499 case gcvSTATUS_MISMATCH:
2500 return "gcvSTATUS_MISMATCH";
2501 case gcvSTATUS_MIPMAP_TOO_SMALL:
2502 return "gcvSTATUS_MIPMAP_TOO_SMALL";
2503 case gcvSTATUS_LARGER:
2504 return "gcvSTATUS_LARGER";
2505 case gcvSTATUS_SMALLER:
2506 return "gcvSTATUS_SMALLER";
2507 case gcvSTATUS_CHIP_NOT_READY:
2508 return "gcvSTATUS_CHIP_NOT_READY";
2509 case gcvSTATUS_NEED_CONVERSION:
2510 return "gcvSTATUS_NEED_CONVERSION";
2511 case gcvSTATUS_SKIP:
2512 return "gcvSTATUS_SKIP";
2513 case gcvSTATUS_DATA_TOO_LARGE:
2514 return "gcvSTATUS_DATA_TOO_LARGE";
2515 case gcvSTATUS_INVALID_CONFIG:
2516 return "gcvSTATUS_INVALID_CONFIG";
2517 case gcvSTATUS_CHANGED:
2518 return "gcvSTATUS_CHANGED";
2519 case gcvSTATUS_NOT_SUPPORT_DITHER:
2520 return "gcvSTATUS_NOT_SUPPORT_DITHER";
2521
2522 case gcvSTATUS_INVALID_ARGUMENT:
2523 return "gcvSTATUS_INVALID_ARGUMENT";
2524 case gcvSTATUS_INVALID_OBJECT:
2525 return "gcvSTATUS_INVALID_OBJECT";
2526 case gcvSTATUS_OUT_OF_MEMORY:
2527 return "gcvSTATUS_OUT_OF_MEMORY";
2528 case gcvSTATUS_MEMORY_LOCKED:
2529 return "gcvSTATUS_MEMORY_LOCKED";
2530 case gcvSTATUS_MEMORY_UNLOCKED:
2531 return "gcvSTATUS_MEMORY_UNLOCKED";
2532 case gcvSTATUS_HEAP_CORRUPTED:
2533 return "gcvSTATUS_HEAP_CORRUPTED";
2534 case gcvSTATUS_GENERIC_IO:
2535 return "gcvSTATUS_GENERIC_IO";
2536 case gcvSTATUS_INVALID_ADDRESS:
2537 return "gcvSTATUS_INVALID_ADDRESS";
2538 case gcvSTATUS_CONTEXT_LOSSED:
2539 return "gcvSTATUS_CONTEXT_LOSSED";
2540 case gcvSTATUS_TOO_COMPLEX:
2541 return "gcvSTATUS_TOO_COMPLEX";
2542 case gcvSTATUS_BUFFER_TOO_SMALL:
2543 return "gcvSTATUS_BUFFER_TOO_SMALL";
2544 case gcvSTATUS_INTERFACE_ERROR:
2545 return "gcvSTATUS_INTERFACE_ERROR";
2546 case gcvSTATUS_NOT_SUPPORTED:
2547 return "gcvSTATUS_NOT_SUPPORTED";
2548 case gcvSTATUS_MORE_DATA:
2549 return "gcvSTATUS_MORE_DATA";
2550 case gcvSTATUS_TIMEOUT:
2551 return "gcvSTATUS_TIMEOUT";
2552 case gcvSTATUS_OUT_OF_RESOURCES:
2553 return "gcvSTATUS_OUT_OF_RESOURCES";
2554 case gcvSTATUS_INVALID_DATA:
2555 return "gcvSTATUS_INVALID_DATA";
2556 case gcvSTATUS_INVALID_MIPMAP:
2557 return "gcvSTATUS_INVALID_MIPMAP";
2558 case gcvSTATUS_NOT_FOUND:
2559 return "gcvSTATUS_NOT_FOUND";
2560 case gcvSTATUS_NOT_ALIGNED:
2561 return "gcvSTATUS_NOT_ALIGNED";
2562 case gcvSTATUS_INVALID_REQUEST:
2563 return "gcvSTATUS_INVALID_REQUEST";
2564 case gcvSTATUS_GPU_NOT_RESPONDING:
2565 return "gcvSTATUS_GPU_NOT_RESPONDING";
2566 case gcvSTATUS_TIMER_OVERFLOW:
2567 return "gcvSTATUS_TIMER_OVERFLOW";
2568 case gcvSTATUS_VERSION_MISMATCH:
2569 return "gcvSTATUS_VERSION_MISMATCH";
2570 case gcvSTATUS_LOCKED:
2571 return "gcvSTATUS_LOCKED";
2572 case gcvSTATUS_INTERRUPTED:
2573 return "gcvSTATUS_INTERRUPTED";
2574 case gcvSTATUS_DEVICE:
2575 return "gcvSTATUS_DEVICE";
2576 case gcvSTATUS_NOT_MULTI_PIPE_ALIGNED:
2577 return "gcvSTATUS_NOT_MULTI_PIPE_ALIGNED";
2578
2579 /* Linker errors. */
2580 case gcvSTATUS_GLOBAL_TYPE_MISMATCH:
2581 return "gcvSTATUS_GLOBAL_TYPE_MISMATCH";
2582 case gcvSTATUS_TOO_MANY_ATTRIBUTES:
2583 return "gcvSTATUS_TOO_MANY_ATTRIBUTES";
2584 case gcvSTATUS_TOO_MANY_UNIFORMS:
2585 return "gcvSTATUS_TOO_MANY_UNIFORMS";
2586 case gcvSTATUS_TOO_MANY_SAMPLER:
2587 return "gcvSTATUS_TOO_MANY_SAMPLER";
2588 case gcvSTATUS_TOO_MANY_VARYINGS:
2589 return "gcvSTATUS_TOO_MANY_VARYINGS";
2590 case gcvSTATUS_UNDECLARED_VARYING:
2591 return "gcvSTATUS_UNDECLARED_VARYING";
2592 case gcvSTATUS_VARYING_TYPE_MISMATCH:
2593 return "gcvSTATUS_VARYING_TYPE_MISMATCH";
2594 case gcvSTATUS_MISSING_MAIN:
2595 return "gcvSTATUS_MISSING_MAIN";
2596 case gcvSTATUS_NAME_MISMATCH:
2597 return "gcvSTATUS_NAME_MISMATCH";
2598 case gcvSTATUS_INVALID_INDEX:
2599 return "gcvSTATUS_INVALID_INDEX";
2600 case gcvSTATUS_UNIFORM_MISMATCH:
2601 return "gcvSTATUS_UNIFORM_MISMATCH";
2602 case gcvSTATUS_UNSAT_LIB_SYMBOL:
2603 return "gcvSTATUS_UNSAT_LIB_SYMBOL";
2604 case gcvSTATUS_TOO_MANY_SHADERS:
2605 return "gcvSTATUS_TOO_MANY_SHADERS";
2606 case gcvSTATUS_LINK_INVALID_SHADERS:
2607 return "gcvSTATUS_LINK_INVALID_SHADERS";
2608 case gcvSTATUS_CS_NO_WORKGROUP_SIZE:
2609 return "gcvSTATUS_CS_NO_WORKGROUP_SIZE";
2610 case gcvSTATUS_LINK_LIB_ERROR:
2611 return "gcvSTATUS_LINK_LIB_ERROR";
2612 case gcvSTATUS_SHADER_VERSION_MISMATCH:
2613 return "gcvSTATUS_SHADER_VERSION_MISMATCH";
2614 case gcvSTATUS_TOO_MANY_INSTRUCTION:
2615 return "gcvSTATUS_TOO_MANY_INSTRUCTION";
2616 case gcvSTATUS_SSBO_MISMATCH:
2617 return "gcvSTATUS_SSBO_MISMATCH";
2618 case gcvSTATUS_TOO_MANY_OUTPUT:
2619 return "gcvSTATUS_TOO_MANY_OUTPUT";
2620 case gcvSTATUS_TOO_MANY_INPUT:
2621 return "gcvSTATUS_TOO_MANY_INPUT";
2622 case gcvSTATUS_NOT_SUPPORT_CL:
2623 return "gcvSTATUS_NOT_SUPPORT_CL";
2624 case gcvSTATUS_NOT_SUPPORT_INTEGER:
2625 return "gcvSTATUS_NOT_SUPPORT_INTEGER";
2626
2627 /* Compiler errors. */
2628 case gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR:
2629 return "gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR";
2630 case gcvSTATUS_COMPILER_FE_PARSER_ERROR:
2631 return "gcvSTATUS_COMPILER_FE_PARSER_ERROR";
2632
2633 default:
2634 return "nil";
2635 }
2636}
2637
2638/*******************************************************************************
2639***** Binary Trace *************************************************************
2640*******************************************************************************/
2641
2642/*******************************************************************************
2643** _VerifyMessage
2644**
2645** Verify a binary trace message, decode it to human readable string and print
2646** it.
2647**
2648** ARGUMENTS:
2649**
2650** gctCONST_STRING Buffer
2651** Pointer to buffer to store.
2652**
2653** gctSIZE_T Bytes
2654** Buffer length.
2655*/
2656void
2657_VerifyMessage(
2658 IN gctCONST_STRING Buffer,
2659 IN gctSIZE_T Bytes
2660 )
2661{
2662 char arguments[150] = {0};
2663 char format[100] = {0};
2664
2665 gctSTRING function;
2666 gctPOINTER args;
2667 gctUINT32 numArguments;
2668 int i = 0;
2669 gctUINT32 functionBytes;
2670
2671 gcsBINARY_TRACE_MESSAGE_PTR message = (gcsBINARY_TRACE_MESSAGE_PTR)Buffer;
2672
2673 /* Check signature. */
2674 if (message->signature != 0x7FFFFFFF)
2675 {
2676 gcmkPRINT("Signature error");
2677 return;
2678 }
2679
2680 /* Get function name. */
2681 function = (gctSTRING)&message->payload;
2682 functionBytes = (gctUINT32)strlen(function) + 1;
2683
2684 /* Get arguments number. */
2685 numArguments = message->numArguments;
2686
2687 /* Get arguments . */
2688 args = function + functionBytes;
2689
2690 /* Prepare format string. */
2691 while (numArguments--)
2692 {
2693 format[i++] = '%';
2694 format[i++] = 'x';
2695 format[i++] = ' ';
2696 }
2697
2698 format[i] = '\0';
2699
2700 if (numArguments)
2701 {
2702 gcmkVSPRINTF(arguments, 150, format, (gctARGUMENTS *) &args);
2703 }
2704
2705 gcmkPRINT("[%d](%d): %s(%d) %s",
2706 message->pid,
2707 message->tid,
2708 function,
2709 message->line,
2710 arguments);
2711}
2712
2713
2714/*******************************************************************************
2715** gckOS_WriteToRingBuffer
2716**
2717** Store a buffer to ring buffer.
2718**
2719** ARGUMENTS:
2720**
2721** gctCONST_STRING Buffer
2722** Pointer to buffer to store.
2723**
2724** gctSIZE_T Bytes
2725** Buffer length.
2726*/
2727void
2728gckOS_WriteToRingBuffer(
2729 IN gctCONST_STRING Buffer,
2730 IN gctSIZE_T Bytes
2731 )
2732{
2733
2734}
2735
2736/*******************************************************************************
2737** gckOS_BinaryTrace
2738**
2739** Output a binary trace message.
2740**
2741** ARGUMENTS:
2742**
2743** gctCONST_STRING Function
2744** Pointer to function name.
2745**
2746** gctINT Line
2747** Line number.
2748**
2749** gctCONST_STRING Text OPTIONAL
2750** Optional pointer to a descriptive text.
2751**
2752** ...
2753** Optional arguments to the descriptive text.
2754*/
2755void
2756gckOS_BinaryTrace(
2757 IN gctCONST_STRING Function,
2758 IN gctINT Line,
2759 IN gctCONST_STRING Text OPTIONAL,
2760 ...
2761 )
2762{
2763 static gctUINT32 messageSignature = 0x7FFFFFFF;
2764 char buffer[gcdBINARY_TRACE_MESSAGE_SIZE];
2765 gctUINT32 numArguments = 0;
2766 gctUINT32 functionBytes;
2767 gctUINT32 i = 0;
2768 gctSTRING payload;
2769 gcsBINARY_TRACE_MESSAGE_PTR message = (gcsBINARY_TRACE_MESSAGE_PTR)buffer;
2770
2771 /* Calculate arguments number. */
2772 if (Text)
2773 {
2774 while (Text[i] != '\0')
2775 {
2776 if (Text[i] == '%')
2777 {
2778 numArguments++;
2779 }
2780 i++;
2781 }
2782 }
2783
2784 message->signature = messageSignature;
2785 message->pid = gcmkGETPROCESSID();
2786 message->tid = gcmkGETTHREADID();
2787 message->line = Line;
2788 message->numArguments = numArguments;
2789
2790 payload = (gctSTRING)&message->payload;
2791
2792 /* Function name. */
2793 functionBytes = (gctUINT32)gcmkSTRLEN(Function) + 1;
2794 gcmkMEMCPY(payload, Function, functionBytes);
2795
2796 /* Advance to next payload. */
2797 payload += functionBytes;
2798
2799 /* Arguments value. */
2800 if (numArguments)
2801 {
2802 gctARGUMENTS p;
2803 gcmkARGUMENTS_START(p, Text);
2804
2805 for (i = 0; i < numArguments; ++i)
2806 {
2807 gctPOINTER value = gcmkARGUMENTS_ARG(p, gctPOINTER);
2808 gcmkMEMCPY(payload, &value, gcmSIZEOF(gctPOINTER));
2809 payload += gcmSIZEOF(gctPOINTER);
2810 }
2811
2812 gcmkARGUMENTS_END(p);
2813 }
2814
2815 gcmkASSERT(payload - buffer <= gcdBINARY_TRACE_MESSAGE_SIZE);
2816
2817
2818 /* Send buffer to ring buffer. */
2819 gckOS_WriteToRingBuffer(buffer, (gctUINT32)(payload - buffer));
2820}
2821
diff --git a/src/hal/kernel/gc_hal_kernel_event.c b/src/hal/kernel/gc_hal_kernel_event.c
new file mode 100755
index 0000000..d6c14fc
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_event.c
@@ -0,0 +1,3145 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57#include "gc_hal_kernel_buffer.h"
58
59#ifdef __QNXNTO__
60#include <atomic.h>
61#include "gc_hal_kernel_qnx.h"
62#endif
63
64#define _GC_OBJ_ZONE gcvZONE_EVENT
65
66#define gcdEVENT_ALLOCATION_COUNT (4096 / gcmSIZEOF(gcsHAL_INTERFACE))
67#define gcdEVENT_MIN_THRESHOLD 4
68
69/******************************************************************************\
70********************************* Support Code *********************************
71\******************************************************************************/
72
73static gceSTATUS
74gckEVENT_AllocateQueue(
75 IN gckEVENT Event,
76 OUT gcsEVENT_QUEUE_PTR * Queue
77 )
78{
79 gceSTATUS status;
80
81 gcmkHEADER_ARG("Event=0x%x", Event);
82
83 /* Verify the arguments. */
84 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
85 gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
86
87 /* Do we have free queues? */
88 if (Event->freeList == gcvNULL)
89 {
90 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
91 }
92
93 /* Move one free queue from the free list. */
94 * Queue = Event->freeList;
95 Event->freeList = Event->freeList->next;
96
97 /* Success. */
98 gcmkFOOTER_ARG("*Queue=0x%x", gcmOPT_POINTER(Queue));
99 return gcvSTATUS_OK;
100
101OnError:
102 /* Return the status. */
103 gcmkFOOTER();
104 return status;
105}
106
107static gceSTATUS
108gckEVENT_FreeQueue(
109 IN gckEVENT Event,
110 OUT gcsEVENT_QUEUE_PTR Queue
111 )
112{
113 gceSTATUS status = gcvSTATUS_OK;
114
115 gcmkHEADER_ARG("Event=0x%x", Event);
116
117 /* Verify the arguments. */
118 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
119 gcmkVERIFY_ARGUMENT(Queue != gcvNULL);
120
121 /* Move one free queue from the free list. */
122 Queue->next = Event->freeList;
123 Event->freeList = Queue;
124
125 /* Success. */
126 gcmkFOOTER();
127 return status;
128}
129
130static gceSTATUS
131gckEVENT_FreeRecord(
132 IN gckEVENT Event,
133 IN gcsEVENT_PTR Record
134 )
135{
136 gceSTATUS status;
137 gctBOOL acquired = gcvFALSE;
138
139 gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
140
141 /* Verify the arguments. */
142 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
143 gcmkVERIFY_ARGUMENT(Record != gcvNULL);
144
145 /* Acquire the mutex. */
146 gcmkONERROR(gckOS_AcquireMutex(Event->os,
147 Event->freeEventMutex,
148 gcvINFINITE));
149 acquired = gcvTRUE;
150
151 /* Push the record on the free list. */
152 Record->next = Event->freeEventList;
153 Event->freeEventList = Record;
154 Event->freeEventCount += 1;
155
156 /* Release the mutex. */
157 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
158
159 /* Success. */
160 gcmkFOOTER_NO();
161 return gcvSTATUS_OK;
162
163OnError:
164 /* Roll back. */
165 if (acquired)
166 {
167 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
168 }
169
170 /* Return the status. */
171 gcmkFOOTER();
172 return gcvSTATUS_OK;
173}
174
175static gceSTATUS
176gckEVENT_IsEmpty(
177 IN gckEVENT Event,
178 OUT gctBOOL_PTR IsEmpty
179 )
180{
181 gceSTATUS status;
182 gctSIZE_T i;
183
184 gcmkHEADER_ARG("Event=0x%x", Event);
185
186 /* Verify the arguments. */
187 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
188 gcmkVERIFY_ARGUMENT(IsEmpty != gcvNULL);
189
190 /* Assume the event queue is empty. */
191 *IsEmpty = gcvTRUE;
192
193 /* Walk the event queue. */
194 for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
195 {
196 /* Check whether this event is in use. */
197 if (Event->queues[i].head != gcvNULL)
198 {
199 /* The event is in use, hence the queue is not empty. */
200 *IsEmpty = gcvFALSE;
201 break;
202 }
203 }
204
205 /* Try acquiring the mutex. */
206 status = gckOS_AcquireMutex(Event->os, Event->eventQueueMutex, 0);
207 if (status == gcvSTATUS_TIMEOUT)
208 {
209 /* Timeout - queue is no longer empty. */
210 *IsEmpty = gcvFALSE;
211 }
212 else
213 {
214 /* Bail out on error. */
215 gcmkONERROR(status);
216
217 /* Release the mutex. */
218 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
219 }
220
221 /* Success. */
222 gcmkFOOTER_ARG("*IsEmpty=%d", gcmOPT_VALUE(IsEmpty));
223 return gcvSTATUS_OK;
224
225OnError:
226 /* Return the status. */
227 gcmkFOOTER();
228 return status;
229}
230
231static gceSTATUS
232_TryToIdleGPU(
233 IN gckEVENT Event
234)
235{
236 gceSTATUS status;
237 gctBOOL empty = gcvFALSE, idle = gcvFALSE;
238 gctBOOL powerLocked = gcvFALSE;
239 gckHARDWARE hardware;
240
241 gcmkHEADER_ARG("Event=0x%x", Event);
242
243 /* Verify the arguments. */
244 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
245
246 /* Grab gckHARDWARE object. */
247 hardware = Event->kernel->hardware;
248 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
249
250 /* Check whether the event queue is empty. */
251 gcmkONERROR(gckEVENT_IsEmpty(Event, &empty));
252
253 if (empty)
254 {
255 status = gckOS_AcquireMutex(hardware->os, hardware->powerMutex, 0);
256 if (status == gcvSTATUS_TIMEOUT)
257 {
258 gcmkFOOTER_NO();
259 return gcvSTATUS_OK;
260 }
261
262 powerLocked = gcvTRUE;
263
264 /* Query whether the hardware is idle. */
265 gcmkONERROR(gckHARDWARE_QueryIdle(Event->kernel->hardware, &idle));
266
267 gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
268 powerLocked = gcvFALSE;
269
270 if (idle)
271 {
272 /* Inform the system of idle GPU. */
273 gcmkONERROR(gckOS_Broadcast(Event->os,
274 Event->kernel->hardware,
275 gcvBROADCAST_GPU_IDLE));
276 }
277 }
278
279 gcmkFOOTER_NO();
280 return gcvSTATUS_OK;
281
282OnError:
283 if (powerLocked)
284 {
285 gcmkONERROR(gckOS_ReleaseMutex(hardware->os, hardware->powerMutex));
286 }
287
288 gcmkFOOTER();
289 return status;
290}
291
292static gceSTATUS
293__RemoveRecordFromProcessDB(
294 IN gckEVENT Event,
295 IN gcsEVENT_PTR Record
296 )
297{
298 gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
299 gcmkVERIFY_ARGUMENT(Record != gcvNULL);
300
301 while (Record != gcvNULL)
302 {
303 if (Record->info.command == gcvHAL_SIGNAL)
304 {
305 /* TODO: Find a better place to bind signal to hardware.*/
306 gcmkVERIFY_OK(gckOS_SignalSetHardware(Event->os,
307 gcmUINT64_TO_PTR(Record->info.u.Signal.signal),
308 Event->kernel->hardware));
309 }
310
311 if (Record->fromKernel)
312 {
313 /* No need to check db if event is from kernel. */
314 Record = Record->next;
315 continue;
316 }
317
318 switch (Record->info.command)
319 {
320 case gcvHAL_FREE_NON_PAGED_MEMORY:
321 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
322 Event->kernel,
323 Record->processID,
324 gcvDB_NON_PAGED,
325 gcmUINT64_TO_PTR(Record->info.u.FreeNonPagedMemory.logical)));
326 break;
327
328 case gcvHAL_FREE_CONTIGUOUS_MEMORY:
329 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
330 Event->kernel,
331 Record->processID,
332 gcvDB_CONTIGUOUS,
333 gcmUINT64_TO_PTR(Record->info.u.FreeContiguousMemory.logical)));
334 break;
335
336 case gcvHAL_UNLOCK_VIDEO_MEMORY:
337 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
338 Event->kernel,
339 Record->processID,
340 gcvDB_VIDEO_MEMORY_LOCKED,
341 gcmUINT64_TO_PTR(Record->info.u.UnlockVideoMemory.node)));
342 break;
343
344 case gcvHAL_UNMAP_USER_MEMORY:
345 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
346 Event->kernel,
347 Record->processID,
348 gcvDB_MAP_USER_MEMORY,
349 gcmINT2PTR(Record->info.u.UnmapUserMemory.info)));
350 break;
351
352 case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
353 gcmkVERIFY_OK(gckKERNEL_RemoveProcessDB(
354 Event->kernel,
355 Record->processID,
356 gcvDB_COMMAND_BUFFER,
357 gcmUINT64_TO_PTR(Record->info.u.FreeVirtualCommandBuffer.logical)));
358 break;
359
360 default:
361 break;
362 }
363
364 Record = Record->next;
365 }
366 gcmkFOOTER_NO();
367 return gcvSTATUS_OK;
368}
369
370gceSTATUS
371_ReleaseVideoMemoryHandle(
372 IN gckKERNEL Kernel,
373 IN OUT gcsEVENT_PTR Record,
374 IN OUT gcsHAL_INTERFACE * Interface
375 )
376{
377 gceSTATUS status;
378 gckVIDMEM_NODE nodeObject;
379 gctUINT32 handle;
380
381 switch(Interface->command)
382 {
383 case gcvHAL_UNLOCK_VIDEO_MEMORY:
384 handle = (gctUINT32)Interface->u.UnlockVideoMemory.node;
385
386 gcmkONERROR(gckVIDMEM_HANDLE_Lookup(
387 Kernel, Record->processID, handle, &nodeObject));
388
389 Record->info.u.UnlockVideoMemory.node = gcmPTR_TO_UINT64(nodeObject);
390
391 gckVIDMEM_HANDLE_Dereference(Kernel, Record->processID, handle);
392 break;
393
394 default:
395 break;
396 }
397
398 return gcvSTATUS_OK;
399OnError:
400 return status;
401}
402
403/*******************************************************************************
404**
405** _QueryFlush
406**
407** Check the type of surfaces which will be released by current event and
408** determine the cache needed to flush.
409**
410*/
411static gceSTATUS
412_QueryFlush(
413 IN gckEVENT Event,
414 IN gcsEVENT_PTR Record,
415 OUT gceKERNEL_FLUSH *Flush
416 )
417{
418 gceKERNEL_FLUSH flush = 0;
419 gcmkHEADER_ARG("Event=0x%x Record=0x%x", Event, Record);
420 gcmkVERIFY_ARGUMENT(Record != gcvNULL);
421
422 while (Record != gcvNULL)
423 {
424 switch (Record->info.command)
425 {
426 case gcvHAL_UNLOCK_VIDEO_MEMORY:
427 switch(Record->info.u.UnlockVideoMemory.type)
428 {
429 case gcvSURF_TILE_STATUS:
430 flush |= gcvFLUSH_TILE_STATUS;
431 break;
432 case gcvSURF_RENDER_TARGET:
433 flush |= gcvFLUSH_COLOR;
434 break;
435 case gcvSURF_DEPTH:
436 flush |= gcvFLUSH_DEPTH;
437 break;
438 case gcvSURF_TEXTURE:
439 flush |= gcvFLUSH_TEXTURE;
440 break;
441 case gcvSURF_TYPE_UNKNOWN:
442 gcmkASSERT(0);
443 break;
444 default:
445 break;
446 }
447 break;
448 case gcvHAL_UNMAP_USER_MEMORY:
449 *Flush = gcvFLUSH_ALL;
450 return gcvSTATUS_OK;
451
452 default:
453 break;
454 }
455
456 Record = Record->next;
457 }
458
459 *Flush = flush;
460
461 gcmkFOOTER_NO();
462 return gcvSTATUS_OK;
463}
464
465void
466_SubmitTimerFunction(
467 gctPOINTER Data
468 )
469{
470 gckEVENT event = (gckEVENT)Data;
471 gcmkVERIFY_OK(gckEVENT_Submit(event, gcvTRUE, gcvFALSE));
472}
473
474/******************************************************************************\
475******************************* gckEVENT API Code *******************************
476\******************************************************************************/
477
478/*******************************************************************************
479**
480** gckEVENT_Construct
481**
482** Construct a new gckEVENT object.
483**
484** INPUT:
485**
486** gckKERNEL Kernel
487** Pointer to an gckKERNEL object.
488**
489** OUTPUT:
490**
491** gckEVENT * Event
492** Pointer to a variable that receives the gckEVENT object pointer.
493*/
494gceSTATUS
495gckEVENT_Construct(
496 IN gckKERNEL Kernel,
497 OUT gckEVENT * Event
498 )
499{
500 gckOS os;
501 gceSTATUS status;
502 gckEVENT eventObj = gcvNULL;
503 int i;
504 gcsEVENT_PTR record;
505 gctPOINTER pointer = gcvNULL;
506
507 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
508
509 /* Verify the arguments. */
510 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
511 gcmkVERIFY_ARGUMENT(Event != gcvNULL);
512
513 /* Extract the pointer to the gckOS object. */
514 os = Kernel->os;
515 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
516
517 /* Allocate the gckEVENT object. */
518 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckEVENT), &pointer));
519
520 eventObj = pointer;
521
522 /* Reset the object. */
523 gcmkVERIFY_OK(gckOS_ZeroMemory(eventObj, gcmSIZEOF(struct _gckEVENT)));
524
525 /* Initialize the gckEVENT object. */
526 eventObj->object.type = gcvOBJ_EVENT;
527 eventObj->kernel = Kernel;
528 eventObj->os = os;
529
530 /* Create the mutexes. */
531 gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventQueueMutex));
532 gcmkONERROR(gckOS_CreateMutex(os, &eventObj->freeEventMutex));
533 gcmkONERROR(gckOS_CreateMutex(os, &eventObj->eventListMutex));
534
535 /* Create a bunch of event reccords. */
536 for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
537 {
538 /* Allocate an event record. */
539 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsEVENT), &pointer));
540
541 record = pointer;
542
543 /* Push it on the free list. */
544 record->next = eventObj->freeEventList;
545 eventObj->freeEventList = record;
546 eventObj->freeEventCount += 1;
547 }
548
549 /* Initialize the free list of event queues. */
550 for (i = 0; i < gcdREPO_LIST_COUNT; i += 1)
551 {
552 eventObj->repoList[i].next = eventObj->freeList;
553 eventObj->freeList = &eventObj->repoList[i];
554 }
555
556 /* Construct the atom. */
557 gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->freeAtom));
558 gcmkONERROR(gckOS_AtomSet(os,
559 eventObj->freeAtom,
560 gcmCOUNTOF(eventObj->queues)));
561
562#if gcdSMP
563 gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->pending));
564
565
566#endif
567
568 gcmkVERIFY_OK(gckOS_CreateTimer(os,
569 _SubmitTimerFunction,
570 (gctPOINTER)eventObj,
571 &eventObj->submitTimer));
572
573#if gcdINTERRUPT_STATISTIC
574 gcmkONERROR(gckOS_AtomConstruct(os, &eventObj->interruptCount));
575 gcmkONERROR(gckOS_AtomSet(os,eventObj->interruptCount, 0));
576#endif
577
578 /* Return pointer to the gckEVENT object. */
579 *Event = eventObj;
580
581 /* Success. */
582 gcmkFOOTER_ARG("*Event=0x%x", *Event);
583 return gcvSTATUS_OK;
584
585OnError:
586 /* Roll back. */
587 if (eventObj != gcvNULL)
588 {
589 if (eventObj->eventQueueMutex != gcvNULL)
590 {
591 gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventQueueMutex));
592 }
593
594 if (eventObj->freeEventMutex != gcvNULL)
595 {
596 gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->freeEventMutex));
597 }
598
599 if (eventObj->eventListMutex != gcvNULL)
600 {
601 gcmkVERIFY_OK(gckOS_DeleteMutex(os, eventObj->eventListMutex));
602 }
603
604 while (eventObj->freeEventList != gcvNULL)
605 {
606 record = eventObj->freeEventList;
607 eventObj->freeEventList = record->next;
608
609 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, record));
610 }
611
612 if (eventObj->freeAtom != gcvNULL)
613 {
614 gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->freeAtom));
615 }
616
617#if gcdSMP
618 if (eventObj->pending != gcvNULL)
619 {
620 gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->pending));
621 }
622
623#endif
624
625#if gcdINTERRUPT_STATISTIC
626 if (eventObj->interruptCount)
627 {
628 gcmkVERIFY_OK(gckOS_AtomDestroy(os, eventObj->interruptCount));
629 }
630#endif
631 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, eventObj));
632 }
633
634 /* Return the status. */
635 gcmkFOOTER();
636 return status;
637}
638
639/*******************************************************************************
640**
641** gckEVENT_Destroy
642**
643** Destroy an gckEVENT object.
644**
645** INPUT:
646**
647** gckEVENT Event
648** Pointer to an gckEVENT object.
649**
650** OUTPUT:
651**
652** Nothing.
653*/
654gceSTATUS
655gckEVENT_Destroy(
656 IN gckEVENT Event
657 )
658{
659 gcsEVENT_PTR record;
660 gcsEVENT_QUEUE_PTR queue;
661
662 gcmkHEADER_ARG("Event=0x%x", Event);
663
664 /* Verify the arguments. */
665 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
666
667 if (Event->submitTimer != gcvNULL)
668 {
669 gcmkVERIFY_OK(gckOS_StopTimer(Event->os, Event->submitTimer));
670 gcmkVERIFY_OK(gckOS_DestroyTimer(Event->os, Event->submitTimer));
671 }
672
673 /* Delete the queue mutex. */
674 gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventQueueMutex));
675
676 /* Free all free events. */
677 while (Event->freeEventList != gcvNULL)
678 {
679 record = Event->freeEventList;
680 Event->freeEventList = record->next;
681
682 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
683 }
684
685 /* Delete the free mutex. */
686 gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->freeEventMutex));
687
688 /* Free all pending queues. */
689 while (Event->queueHead != gcvNULL)
690 {
691 /* Get the current queue. */
692 queue = Event->queueHead;
693
694 /* Free all pending events. */
695 while (queue->head != gcvNULL)
696 {
697 record = queue->head;
698 queue->head = record->next;
699
700 gcmkTRACE_ZONE_N(
701 gcvLEVEL_WARNING, gcvZONE_EVENT,
702 gcmSIZEOF(record) + gcmSIZEOF(queue->source),
703 "Event record 0x%x is still pending for %d.",
704 record, queue->source
705 );
706
707 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, record));
708 }
709
710 /* Remove the top queue from the list. */
711 if (Event->queueHead == Event->queueTail)
712 {
713 Event->queueHead =
714 Event->queueTail = gcvNULL;
715 }
716 else
717 {
718 Event->queueHead = Event->queueHead->next;
719 }
720
721 /* Free the queue. */
722 gcmkVERIFY_OK(gckEVENT_FreeQueue(Event, queue));
723 }
724
725 /* Delete the list mutex. */
726 gcmkVERIFY_OK(gckOS_DeleteMutex(Event->os, Event->eventListMutex));
727
728 /* Delete the atom. */
729 gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->freeAtom));
730
731#if gcdSMP
732 gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->pending));
733
734#endif
735
736#if gcdINTERRUPT_STATISTIC
737 gcmkVERIFY_OK(gckOS_AtomDestroy(Event->os, Event->interruptCount));
738#endif
739
740 /* Mark the gckEVENT object as unknown. */
741 Event->object.type = gcvOBJ_UNKNOWN;
742
743 /* Free the gckEVENT object. */
744 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Event->os, Event));
745
746 /* Success. */
747 gcmkFOOTER_NO();
748 return gcvSTATUS_OK;
749}
750
751/*******************************************************************************
752**
753** gckEVENT_GetEvent
754**
755** Reserve the next available hardware event.
756**
757** INPUT:
758**
759** gckEVENT Event
760** Pointer to an gckEVENT object.
761**
762** gctBOOL Wait
763** Set to gcvTRUE to force the function to wait if no events are
764** immediately available.
765**
766** gceKERNEL_WHERE Source
767** Source of the event.
768**
769** OUTPUT:
770**
771** gctUINT8 * EventID
772** Reserved event ID.
773*/
774#define gcdINVALID_EVENT_PTR ((gcsEVENT_PTR)gcvMAXUINTPTR_T)
775
776gceSTATUS
777gckEVENT_GetEvent(
778 IN gckEVENT Event,
779 IN gctBOOL Wait,
780 OUT gctUINT8 * EventID,
781 IN gceKERNEL_WHERE Source
782 )
783{
784 gctINT i, id;
785 gceSTATUS status;
786 gctBOOL acquired = gcvFALSE;
787 gctINT32 free;
788
789 gcmkHEADER_ARG("Event=0x%x Source=%d", Event, Source);
790
791 while (gcvTRUE)
792 {
793 /* Grab the queue mutex. */
794 gcmkONERROR(gckOS_AcquireMutex(Event->os,
795 Event->eventQueueMutex,
796 gcvINFINITE));
797 acquired = gcvTRUE;
798
799 /* Walk through all events. */
800 id = Event->lastID;
801 for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
802 {
803 gctINT nextID = gckMATH_ModuloInt((id + 1),
804 gcmCOUNTOF(Event->queues));
805
806 if (Event->queues[id].head == gcvNULL)
807 {
808 *EventID = (gctUINT8) id;
809
810 Event->lastID = (gctUINT8) nextID;
811
812 /* Save time stamp of event. */
813 Event->queues[id].head = gcdINVALID_EVENT_PTR;
814 Event->queues[id].stamp = ++(Event->stamp);
815 Event->queues[id].source = Source;
816
817
818 gcmkONERROR(gckOS_AtomDecrement(Event->os,
819 Event->freeAtom,
820 &free));
821#if gcdDYNAMIC_SPEED
822 if (free <= gcdDYNAMIC_EVENT_THRESHOLD)
823 {
824 gcmkONERROR(gckOS_BroadcastHurry(
825 Event->os,
826 Event->kernel->hardware,
827 gcdDYNAMIC_EVENT_THRESHOLD - free));
828 }
829#endif
830
831 /* Release the queue mutex. */
832 gcmkONERROR(gckOS_ReleaseMutex(Event->os,
833 Event->eventQueueMutex));
834
835 /* Success. */
836 gcmkTRACE_ZONE_N(
837 gcvLEVEL_INFO, gcvZONE_EVENT,
838 gcmSIZEOF(id),
839 "Using id=%d",
840 id
841 );
842
843 gcmkFOOTER_ARG("*EventID=%u", *EventID);
844 return gcvSTATUS_OK;
845 }
846
847 id = nextID;
848 }
849
850#if gcdDYNAMIC_SPEED
851 /* No free events, speed up the GPU right now! */
852 gcmkONERROR(gckOS_BroadcastHurry(Event->os,
853 Event->kernel->hardware,
854 gcdDYNAMIC_EVENT_THRESHOLD));
855#endif
856
857 /* Release the queue mutex. */
858 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
859 acquired = gcvFALSE;
860
861 /* Fail if wait is not requested. */
862 if (!Wait)
863 {
864 /* Out of resources. */
865 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
866 }
867
868 /* Delay a while. */
869 gcmkONERROR(gckOS_Delay(Event->os, 1));
870 }
871
872OnError:
873 if (acquired)
874 {
875 /* Release the queue mutex. */
876 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
877 }
878
879 /* Return the status. */
880 gcmkFOOTER();
881 return status;
882}
883
884/*******************************************************************************
885**
886** gckEVENT_AllocateRecord
887**
888** Allocate a record for the new event.
889**
890** INPUT:
891**
892** gckEVENT Event
893** Pointer to an gckEVENT object.
894**
895** gctBOOL AllocateAllowed
896** State for allocation if out of free events.
897**
898** OUTPUT:
899**
900** gcsEVENT_PTR * Record
901** Allocated event record.
902*/
903gceSTATUS
904gckEVENT_AllocateRecord(
905 IN gckEVENT Event,
906 IN gctBOOL AllocateAllowed,
907 OUT gcsEVENT_PTR * Record
908 )
909{
910 gceSTATUS status;
911 gctBOOL acquired = gcvFALSE;
912 gctINT i;
913 gcsEVENT_PTR record;
914 gctPOINTER pointer = gcvNULL;
915
916 gcmkHEADER_ARG("Event=0x%x AllocateAllowed=%d", Event, AllocateAllowed);
917
918 /* Verify the arguments. */
919 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
920 gcmkVERIFY_ARGUMENT(Record != gcvNULL);
921
922 /* Acquire the mutex. */
923 gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->freeEventMutex, gcvINFINITE));
924 acquired = gcvTRUE;
925
926 /* Test if we are below the allocation threshold. */
927 if ( (AllocateAllowed && (Event->freeEventCount < gcdEVENT_MIN_THRESHOLD)) ||
928 (Event->freeEventCount == 0) )
929 {
930 /* Allocate a bunch of records. */
931 for (i = 0; i < gcdEVENT_ALLOCATION_COUNT; i += 1)
932 {
933 /* Allocate an event record. */
934 gcmkONERROR(gckOS_Allocate(Event->os,
935 gcmSIZEOF(gcsEVENT),
936 &pointer));
937
938 record = pointer;
939
940 /* Push it on the free list. */
941 record->next = Event->freeEventList;
942 Event->freeEventList = record;
943 Event->freeEventCount += 1;
944 }
945 }
946
947 *Record = Event->freeEventList;
948 Event->freeEventList = Event->freeEventList->next;
949 Event->freeEventCount -= 1;
950
951 /* Release the mutex. */
952 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
953
954 /* Success. */
955 gcmkFOOTER_ARG("*Record=0x%x", gcmOPT_POINTER(Record));
956 return gcvSTATUS_OK;
957
958OnError:
959 /* Roll back. */
960 if (acquired)
961 {
962 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->freeEventMutex));
963 }
964
965 /* Return the status. */
966 gcmkFOOTER();
967 return status;
968}
969
970/*******************************************************************************
971**
972** gckEVENT_AddList
973**
974** Add a new event to the list of events.
975**
976** INPUT:
977**
978** gckEVENT Event
979** Pointer to an gckEVENT object.
980**
981** gcsHAL_INTERFACE_PTR Interface
982** Pointer to the interface for the event to be added.
983**
984** gceKERNEL_WHERE FromWhere
985** Place in the pipe where the event needs to be generated.
986**
987** gctBOOL AllocateAllowed
988** State for allocation if out of free events.
989**
990** OUTPUT:
991**
992** Nothing.
993*/
994gceSTATUS
995gckEVENT_AddList(
996 IN gckEVENT Event,
997 IN gcsHAL_INTERFACE_PTR Interface,
998 IN gceKERNEL_WHERE FromWhere,
999 IN gctBOOL AllocateAllowed,
1000 IN gctBOOL FromKernel
1001 )
1002{
1003 gceSTATUS status;
1004 gctBOOL acquired = gcvFALSE;
1005 gcsEVENT_PTR record = gcvNULL;
1006 gcsEVENT_QUEUE_PTR queue;
1007 gckVIRTUAL_COMMAND_BUFFER_PTR buffer;
1008 gckKERNEL kernel = Event->kernel;
1009
1010 gcmkHEADER_ARG("Event=0x%x Interface=0x%x",
1011 Event, Interface);
1012
1013 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, _GC_OBJ_ZONE,
1014 "FromWhere=%d AllocateAllowed=%d",
1015 FromWhere, AllocateAllowed);
1016
1017 /* Verify the arguments. */
1018 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1019 gcmkVERIFY_ARGUMENT(Interface != gcvNULL);
1020
1021 /* Verify the event command. */
1022 gcmkASSERT
1023 ( (Interface->command == gcvHAL_FREE_NON_PAGED_MEMORY)
1024 || (Interface->command == gcvHAL_FREE_CONTIGUOUS_MEMORY)
1025 || (Interface->command == gcvHAL_WRITE_DATA)
1026 || (Interface->command == gcvHAL_UNLOCK_VIDEO_MEMORY)
1027 || (Interface->command == gcvHAL_SIGNAL)
1028 || (Interface->command == gcvHAL_UNMAP_USER_MEMORY)
1029 || (Interface->command == gcvHAL_TIMESTAMP)
1030 || (Interface->command == gcvHAL_COMMIT_DONE)
1031 || (Interface->command == gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER)
1032 || (Interface->command == gcvHAL_SYNC_POINT)
1033 || (Interface->command == gcvHAL_DESTROY_MMU)
1034 );
1035
1036 /* Validate the source. */
1037 if ((FromWhere != gcvKERNEL_COMMAND) && (FromWhere != gcvKERNEL_PIXEL))
1038 {
1039 /* Invalid argument. */
1040 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
1041 }
1042
1043 /* Allocate a free record. */
1044 gcmkONERROR(gckEVENT_AllocateRecord(Event, AllocateAllowed, &record));
1045
1046 /* Termninate the record. */
1047 record->next = gcvNULL;
1048
1049 /* Record the committer. */
1050 record->fromKernel = FromKernel;
1051
1052 /* Copy the event interface into the record. */
1053 gckOS_MemCopy(&record->info, Interface, gcmSIZEOF(record->info));
1054
1055 /* Get process ID. */
1056 gcmkONERROR(gckOS_GetProcessID(&record->processID));
1057
1058 gcmkONERROR(__RemoveRecordFromProcessDB(Event, record));
1059
1060 /* Handle is belonged to current process, it must be released now. */
1061 if (FromKernel == gcvFALSE)
1062 {
1063 status = _ReleaseVideoMemoryHandle(Event->kernel, record, Interface);
1064
1065 if (gcmIS_ERROR(status))
1066 {
1067 /* Ingore error because there are other events in the queue. */
1068 status = gcvSTATUS_OK;
1069 goto OnError;
1070 }
1071 }
1072
1073#ifdef __QNXNTO__
1074 record->kernel = Event->kernel;
1075#endif
1076
1077 /* Acquire the mutex. */
1078 gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
1079 acquired = gcvTRUE;
1080
1081 /* Do we need to allocate a new queue? */
1082 if ((Event->queueTail == gcvNULL) || (Event->queueTail->source < FromWhere))
1083 {
1084 /* Allocate a new queue. */
1085 gcmkONERROR(gckEVENT_AllocateQueue(Event, &queue));
1086
1087 /* Initialize the queue. */
1088 queue->source = FromWhere;
1089 queue->head = gcvNULL;
1090 queue->next = gcvNULL;
1091
1092 /* Attach it to the list of allocated queues. */
1093 if (Event->queueTail == gcvNULL)
1094 {
1095 Event->queueHead =
1096 Event->queueTail = queue;
1097 }
1098 else
1099 {
1100 Event->queueTail->next = queue;
1101 Event->queueTail = queue;
1102 }
1103 }
1104 else
1105 {
1106 queue = Event->queueTail;
1107 }
1108
1109 /* Attach the record to the queue. */
1110 if (queue->head == gcvNULL)
1111 {
1112 queue->head = record;
1113 queue->tail = record;
1114 }
1115 else
1116 {
1117 queue->tail->next = record;
1118 queue->tail = record;
1119 }
1120
1121 /* Unmap user space logical address.
1122 * Linux kernel does not support unmap the memory of other process any more since 3.5.
1123 * Let's unmap memory of self process before submit the event to gpu.
1124 * */
1125 switch(Interface->command)
1126 {
1127 case gcvHAL_FREE_NON_PAGED_MEMORY:
1128 gcmkONERROR(gckOS_UnmapUserLogical(
1129 Event->os,
1130 gcmNAME_TO_PTR(Interface->u.FreeNonPagedMemory.physical),
1131 (gctSIZE_T) Interface->u.FreeNonPagedMemory.bytes,
1132 gcmUINT64_TO_PTR(Interface->u.FreeNonPagedMemory.logical)));
1133 break;
1134 case gcvHAL_FREE_CONTIGUOUS_MEMORY:
1135 gcmkONERROR(gckOS_UnmapUserLogical(
1136 Event->os,
1137 gcmNAME_TO_PTR(Interface->u.FreeContiguousMemory.physical),
1138 (gctSIZE_T) Interface->u.FreeContiguousMemory.bytes,
1139 gcmUINT64_TO_PTR(Interface->u.FreeContiguousMemory.logical)));
1140 break;
1141
1142 case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
1143 buffer = (gckVIRTUAL_COMMAND_BUFFER_PTR)gcmNAME_TO_PTR(Interface->u.FreeVirtualCommandBuffer.physical);
1144 if (buffer->userLogical)
1145 {
1146 gcmkONERROR(gckOS_DestroyUserVirtualMapping(
1147 Event->os,
1148 buffer->physical,
1149 (gctSIZE_T) Interface->u.FreeVirtualCommandBuffer.bytes,
1150 gcmUINT64_TO_PTR(Interface->u.FreeVirtualCommandBuffer.logical)));
1151 }
1152 break;
1153
1154 default:
1155 break;
1156 }
1157
1158 /* Release the mutex. */
1159 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
1160
1161 /* Success. */
1162 gcmkFOOTER_NO();
1163 return gcvSTATUS_OK;
1164
1165OnError:
1166 /* Roll back. */
1167 if (acquired)
1168 {
1169 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
1170 }
1171
1172 if (record != gcvNULL)
1173 {
1174 gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
1175 }
1176
1177 /* Return the status. */
1178 gcmkFOOTER();
1179 return status;
1180}
1181
1182/*******************************************************************************
1183**
1184** gckEVENT_Unlock
1185**
1186** Schedule an event to unlock virtual memory.
1187**
1188** INPUT:
1189**
1190** gckEVENT Event
1191** Pointer to an gckEVENT object.
1192**
1193** gceKERNEL_WHERE FromWhere
1194** Place in the pipe where the event needs to be generated.
1195**
1196** gcuVIDMEM_NODE_PTR Node
1197** Pointer to a gcuVIDMEM_NODE union that specifies the virtual memory
1198** to unlock.
1199**
1200** gceSURF_TYPE Type
1201** Type of surface to unlock.
1202**
1203** OUTPUT:
1204**
1205** Nothing.
1206*/
1207gceSTATUS
1208gckEVENT_Unlock(
1209 IN gckEVENT Event,
1210 IN gceKERNEL_WHERE FromWhere,
1211 IN gctPOINTER Node,
1212 IN gceSURF_TYPE Type
1213 )
1214{
1215 gceSTATUS status;
1216 gcsHAL_INTERFACE iface;
1217
1218 gcmkHEADER_ARG("Event=0x%x FromWhere=%d Node=0x%x Type=%d",
1219 Event, FromWhere, Node, Type);
1220
1221 /* Verify the arguments. */
1222 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1223 gcmkVERIFY_ARGUMENT(Node != gcvNULL);
1224
1225 /* Mark the event as an unlock. */
1226 iface.command = gcvHAL_UNLOCK_VIDEO_MEMORY;
1227 iface.u.UnlockVideoMemory.node = gcmPTR_TO_UINT64(Node);
1228 iface.u.UnlockVideoMemory.type = Type;
1229 iface.u.UnlockVideoMemory.asynchroneous = 0;
1230
1231 /* Append it to the queue. */
1232 gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
1233
1234 /* Success. */
1235 gcmkFOOTER_NO();
1236 return gcvSTATUS_OK;
1237
1238OnError:
1239 /* Return the status. */
1240 gcmkFOOTER();
1241 return status;
1242}
1243
1244/*******************************************************************************
1245**
1246** gckEVENT_FreeNonPagedMemory
1247**
1248** Schedule an event to free non-paged memory.
1249**
1250** INPUT:
1251**
1252** gckEVENT Event
1253** Pointer to an gckEVENT object.
1254**
1255** gctSIZE_T Bytes
1256** Number of bytes of non-paged memory to free.
1257**
1258** gctPHYS_ADDR Physical
1259** Physical address of non-paged memory to free.
1260**
1261** gctPOINTER Logical
1262** Logical address of non-paged memory to free.
1263**
1264** gceKERNEL_WHERE FromWhere
1265** Place in the pipe where the event needs to be generated.
1266*/
1267gceSTATUS
1268gckEVENT_FreeNonPagedMemory(
1269 IN gckEVENT Event,
1270 IN gctSIZE_T Bytes,
1271 IN gctPHYS_ADDR Physical,
1272 IN gctPOINTER Logical,
1273 IN gceKERNEL_WHERE FromWhere
1274 )
1275{
1276 gceSTATUS status;
1277 gcsHAL_INTERFACE iface;
1278 gckKERNEL kernel = Event->kernel;
1279
1280 gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
1281 "FromWhere=%d",
1282 Event, Bytes, Physical, Logical, FromWhere);
1283
1284 /* Verify the arguments. */
1285 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1286 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1287 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1288 gcmkVERIFY_ARGUMENT(Bytes > 0);
1289
1290 /* Create an event. */
1291 iface.command = gcvHAL_FREE_NON_PAGED_MEMORY;
1292 iface.u.FreeNonPagedMemory.bytes = Bytes;
1293 iface.u.FreeNonPagedMemory.physical = gcmPTR_TO_NAME(Physical);
1294 iface.u.FreeNonPagedMemory.logical = gcmPTR_TO_UINT64(Logical);
1295
1296 /* Append it to the queue. */
1297 gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
1298
1299 /* Success. */
1300 gcmkFOOTER_NO();
1301 return gcvSTATUS_OK;
1302
1303OnError:
1304 /* Return the status. */
1305 gcmkFOOTER();
1306 return status;
1307}
1308
1309gceSTATUS
1310gckEVENT_DestroyVirtualCommandBuffer(
1311 IN gckEVENT Event,
1312 IN gctSIZE_T Bytes,
1313 IN gctPHYS_ADDR Physical,
1314 IN gctPOINTER Logical,
1315 IN gceKERNEL_WHERE FromWhere
1316 )
1317{
1318 gceSTATUS status;
1319 gcsHAL_INTERFACE iface;
1320 gckKERNEL kernel = Event->kernel;
1321
1322 gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
1323 "FromWhere=%d",
1324 Event, Bytes, Physical, Logical, FromWhere);
1325
1326 /* Verify the arguments. */
1327 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1328 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1329 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1330 gcmkVERIFY_ARGUMENT(Bytes > 0);
1331
1332 /* Create an event. */
1333 iface.command = gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER;
1334 iface.u.FreeVirtualCommandBuffer.bytes = Bytes;
1335 iface.u.FreeVirtualCommandBuffer.physical = gcmPTR_TO_NAME(Physical);
1336 iface.u.FreeVirtualCommandBuffer.logical = gcmPTR_TO_UINT64(Logical);
1337
1338 /* Append it to the queue. */
1339 gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
1340
1341 /* Success. */
1342 gcmkFOOTER_NO();
1343 return gcvSTATUS_OK;
1344
1345OnError:
1346 /* Return the status. */
1347 gcmkFOOTER();
1348 return status;
1349}
1350
1351/*******************************************************************************
1352**
1353** gckEVENT_FreeContigiuousMemory
1354**
1355** Schedule an event to free contiguous memory.
1356**
1357** INPUT:
1358**
1359** gckEVENT Event
1360** Pointer to an gckEVENT object.
1361**
1362** gctSIZE_T Bytes
1363** Number of bytes of contiguous memory to free.
1364**
1365** gctPHYS_ADDR Physical
1366** Physical address of contiguous memory to free.
1367**
1368** gctPOINTER Logical
1369** Logical address of contiguous memory to free.
1370**
1371** gceKERNEL_WHERE FromWhere
1372** Place in the pipe where the event needs to be generated.
1373*/
1374gceSTATUS
1375gckEVENT_FreeContiguousMemory(
1376 IN gckEVENT Event,
1377 IN gctSIZE_T Bytes,
1378 IN gctPHYS_ADDR Physical,
1379 IN gctPOINTER Logical,
1380 IN gceKERNEL_WHERE FromWhere
1381 )
1382{
1383 gceSTATUS status;
1384 gcsHAL_INTERFACE iface;
1385 gckKERNEL kernel = Event->kernel;
1386
1387 gcmkHEADER_ARG("Event=0x%x Bytes=%lu Physical=0x%x Logical=0x%x "
1388 "FromWhere=%d",
1389 Event, Bytes, Physical, Logical, FromWhere);
1390
1391 /* Verify the arguments. */
1392 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1393 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1394 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1395 gcmkVERIFY_ARGUMENT(Bytes > 0);
1396
1397 /* Create an event. */
1398 iface.command = gcvHAL_FREE_CONTIGUOUS_MEMORY;
1399 iface.u.FreeContiguousMemory.bytes = Bytes;
1400 iface.u.FreeContiguousMemory.physical = gcmPTR_TO_NAME(Physical);
1401 iface.u.FreeContiguousMemory.logical = gcmPTR_TO_UINT64(Logical);
1402
1403 /* Append it to the queue. */
1404 gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
1405
1406 /* Success. */
1407 gcmkFOOTER_NO();
1408 return gcvSTATUS_OK;
1409
1410OnError:
1411 /* Return the status. */
1412 gcmkFOOTER();
1413 return status;
1414}
1415
1416/*******************************************************************************
1417**
1418** gckEVENT_Signal
1419**
1420** Schedule an event to trigger a signal.
1421**
1422** INPUT:
1423**
1424** gckEVENT Event
1425** Pointer to an gckEVENT object.
1426**
1427** gctSIGNAL Signal
1428** Pointer to the signal to trigger.
1429**
1430** gceKERNEL_WHERE FromWhere
1431** Place in the pipe where the event needs to be generated.
1432**
1433** OUTPUT:
1434**
1435** Nothing.
1436*/
1437gceSTATUS
1438gckEVENT_Signal(
1439 IN gckEVENT Event,
1440 IN gctSIGNAL Signal,
1441 IN gceKERNEL_WHERE FromWhere
1442 )
1443{
1444 gceSTATUS status;
1445 gcsHAL_INTERFACE iface;
1446
1447 gcmkHEADER_ARG("Event=0x%x Signal=0x%x FromWhere=%d",
1448 Event, Signal, FromWhere);
1449
1450 /* Verify the arguments. */
1451 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1452 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
1453
1454 /* Mark the event as a signal. */
1455 iface.command = gcvHAL_SIGNAL;
1456 iface.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
1457 iface.u.Signal.auxSignal = 0;
1458 iface.u.Signal.process = 0;
1459
1460#ifdef __QNXNTO__
1461 iface.u.Signal.coid = 0;
1462 iface.u.Signal.rcvid = 0;
1463
1464 gcmkONERROR(gckOS_SignalPending(Event->os, Signal));
1465#endif
1466
1467 /* Append it to the queue. */
1468 gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
1469
1470 /* Success. */
1471 gcmkFOOTER_NO();
1472 return gcvSTATUS_OK;
1473
1474OnError:
1475 /* Return the status. */
1476 gcmkFOOTER();
1477 return status;
1478}
1479
1480/*******************************************************************************
1481**
1482** gckEVENT_CommitDone
1483**
1484** Schedule an event to wake up work thread when commit is done by GPU.
1485**
1486** INPUT:
1487**
1488** gckEVENT Event
1489** Pointer to an gckEVENT object.
1490**
1491** gceKERNEL_WHERE FromWhere
1492** Place in the pipe where the event needs to be generated.
1493**
1494** OUTPUT:
1495**
1496** Nothing.
1497*/
1498gceSTATUS
1499gckEVENT_CommitDone(
1500 IN gckEVENT Event,
1501 IN gceKERNEL_WHERE FromWhere
1502 )
1503{
1504 gceSTATUS status;
1505 gcsHAL_INTERFACE iface;
1506
1507 gcmkHEADER_ARG("Event=0x%x FromWhere=%d", Event, FromWhere);
1508
1509 /* Verify the arguments. */
1510 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1511
1512 iface.command = gcvHAL_COMMIT_DONE;
1513
1514 /* Append it to the queue. */
1515 gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
1516
1517 /* Success. */
1518 gcmkFOOTER_NO();
1519 return gcvSTATUS_OK;
1520
1521OnError:
1522 /* Return the status. */
1523 gcmkFOOTER();
1524 return status;
1525}
1526
1527#if gcdPROCESS_ADDRESS_SPACE
1528gceSTATUS
1529gckEVENT_DestroyMmu(
1530 IN gckEVENT Event,
1531 IN gckMMU Mmu,
1532 IN gceKERNEL_WHERE FromWhere
1533 )
1534{
1535 gceSTATUS status;
1536 gcsHAL_INTERFACE iface;
1537
1538 gcmkHEADER_ARG("Event=0x%x FromWhere=%d", Event, FromWhere);
1539
1540 /* Verify the arguments. */
1541 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1542
1543 iface.command = gcvHAL_DESTROY_MMU;
1544 iface.u.DestroyMmu.mmu = gcmPTR_TO_UINT64(Mmu);
1545
1546 /* Append it to the queue. */
1547 gcmkONERROR(gckEVENT_AddList(Event, &iface, FromWhere, gcvFALSE, gcvTRUE));
1548
1549 /* Success. */
1550 gcmkFOOTER_NO();
1551 return gcvSTATUS_OK;
1552
1553OnError:
1554 /* Return the status. */
1555 gcmkFOOTER();
1556 return status;
1557}
1558#endif
1559
1560/*******************************************************************************
1561**
1562** gckEVENT_Submit
1563**
1564** Submit the current event queue to the GPU.
1565**
1566** INPUT:
1567**
1568** gckEVENT Event
1569** Pointer to an gckEVENT object.
1570**
1571** gctBOOL Wait
1572** Submit requires one vacant event; if Wait is set to not zero,
1573** and there are no vacant events at this time, the function will
1574** wait until an event becomes vacant so that submission of the
1575** queue is successful.
1576**
1577** gctBOOL FromPower
1578** Determines whether the call originates from inside the power
1579** management or not.
1580**
1581** OUTPUT:
1582**
1583** Nothing.
1584*/
1585gceSTATUS
1586gckEVENT_Submit(
1587 IN gckEVENT Event,
1588 IN gctBOOL Wait,
1589 IN gctBOOL FromPower
1590 )
1591{
1592 gceSTATUS status;
1593 gctUINT8 id = 0xFF;
1594 gcsEVENT_QUEUE_PTR queue;
1595 gctBOOL acquired = gcvFALSE;
1596 gckCOMMAND command = gcvNULL;
1597 gctBOOL commitEntered = gcvFALSE;
1598#if !gcdNULL_DRIVER
1599 gctUINT32 bytes;
1600 gctPOINTER buffer;
1601#endif
1602
1603
1604#if gcdINTERRUPT_STATISTIC
1605 gctINT32 oldValue;
1606#endif
1607
1608
1609 gctUINT32 flushBytes;
1610 gctUINT32 executeBytes;
1611 gckHARDWARE hardware;
1612
1613 gceKERNEL_FLUSH flush = gcvFALSE;
1614 gctUINT64 commitStamp;
1615
1616 gcmkHEADER_ARG("Event=0x%x Wait=%d", Event, Wait);
1617
1618 /* Get gckCOMMAND object. */
1619 command = Event->kernel->command;
1620 hardware = Event->kernel->hardware;
1621
1622 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
1623
1624 gckOS_GetTicks(&Event->lastCommitStamp);
1625
1626 /* Are there event queues? */
1627 if (Event->queueHead != gcvNULL)
1628 {
1629 /* Acquire the command queue. */
1630 gcmkONERROR(gckCOMMAND_EnterCommit(command, FromPower));
1631 commitEntered = gcvTRUE;
1632
1633 /* Get current commit stamp. */
1634 commitStamp = Event->kernel->command->commitStamp;
1635
1636 if (commitStamp)
1637 {
1638 commitStamp -= 1;
1639 }
1640
1641 /* Process all queues. */
1642 while (Event->queueHead != gcvNULL)
1643 {
1644 /* Acquire the list mutex. */
1645 gcmkONERROR(gckOS_AcquireMutex(Event->os,
1646 Event->eventListMutex,
1647 gcvINFINITE));
1648 acquired = gcvTRUE;
1649
1650 /* Get the current queue. */
1651 queue = Event->queueHead;
1652
1653 /* Allocate an event ID. */
1654 gcmkONERROR(gckEVENT_GetEvent(Event, Wait, &id, queue->source));
1655
1656 /* Copy event list to event ID queue. */
1657 Event->queues[id].head = queue->head;
1658
1659 /* Update current commit stamp. */
1660 Event->queues[id].commitStamp = commitStamp;
1661
1662 /* Remove the top queue from the list. */
1663 if (Event->queueHead == Event->queueTail)
1664 {
1665 Event->queueHead = gcvNULL;
1666 Event->queueTail = gcvNULL;
1667 }
1668 else
1669 {
1670 Event->queueHead = Event->queueHead->next;
1671 }
1672
1673 /* Free the queue. */
1674 gcmkONERROR(gckEVENT_FreeQueue(Event, queue));
1675
1676 /* Release the list mutex. */
1677 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
1678 acquired = gcvFALSE;
1679
1680 /* Determine cache needed to flush. */
1681 gcmkVERIFY_OK(_QueryFlush(Event, Event->queues[id].head, &flush));
1682
1683#if gcdINTERRUPT_STATISTIC
1684 gcmkVERIFY_OK(gckOS_AtomIncrement(
1685 Event->os,
1686 Event->interruptCount,
1687 &oldValue
1688 ));
1689#endif
1690
1691#if gcdNULL_DRIVER
1692 /* Notify immediately on infinite hardware. */
1693 gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
1694
1695 gcmkONERROR(gckEVENT_Notify(Event, 0));
1696#else
1697 /* Get the size of the hardware event. */
1698 gcmkONERROR(gckHARDWARE_Event(
1699 hardware,
1700 gcvNULL,
1701 id,
1702 Event->queues[id].source,
1703 &bytes
1704 ));
1705
1706 /* Get the size of flush command. */
1707 gcmkONERROR(gckHARDWARE_Flush(
1708 hardware,
1709 flush,
1710 gcvNULL,
1711 &flushBytes
1712 ));
1713
1714 bytes += flushBytes;
1715
1716
1717 /* Total bytes need to execute. */
1718 executeBytes = bytes;
1719
1720 /* Reserve space in the command queue. */
1721 gcmkONERROR(gckCOMMAND_Reserve(command, bytes, &buffer, &bytes));
1722
1723
1724 /* Set the flush in the command queue. */
1725 gcmkONERROR(gckHARDWARE_Flush(
1726 hardware,
1727 flush,
1728 buffer,
1729 &flushBytes
1730 ));
1731
1732 /* Advance to next command. */
1733 buffer = (gctUINT8_PTR)buffer + flushBytes;
1734
1735 /* Set the hardware event in the command queue. */
1736 gcmkONERROR(gckHARDWARE_Event(
1737 hardware,
1738 buffer,
1739 id,
1740 Event->queues[id].source,
1741 &bytes
1742 ));
1743
1744 /* Advance to next command. */
1745 buffer = (gctUINT8_PTR)buffer + bytes;
1746
1747
1748 /* Execute the hardware event. */
1749 gcmkONERROR(gckCOMMAND_Execute(command, executeBytes));
1750#endif
1751 }
1752
1753 /* Release the command queue. */
1754 gcmkONERROR(gckCOMMAND_ExitCommit(command, FromPower));
1755
1756#if !gcdNULL_DRIVER
1757 gcmkVERIFY_OK(_TryToIdleGPU(Event));
1758#endif
1759 }
1760
1761 /* Success. */
1762 gcmkFOOTER_NO();
1763 return gcvSTATUS_OK;
1764
1765OnError:
1766 if (acquired)
1767 {
1768 /* Need to unroll the mutex acquire. */
1769 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
1770 }
1771
1772 if (commitEntered)
1773 {
1774 /* Release the command queue mutex. */
1775 gcmkVERIFY_OK(gckCOMMAND_ExitCommit(command, FromPower));
1776 }
1777
1778 if (id != 0xFF)
1779 {
1780 /* Need to unroll the event allocation. */
1781 Event->queues[id].head = gcvNULL;
1782 }
1783
1784 if (status == gcvSTATUS_GPU_NOT_RESPONDING)
1785 {
1786 /* Broadcast GPU stuck. */
1787 status = gckOS_Broadcast(Event->os,
1788 Event->kernel->hardware,
1789 gcvBROADCAST_GPU_STUCK);
1790 }
1791
1792 /* Return the status. */
1793 gcmkFOOTER();
1794 return status;
1795}
1796
1797/*******************************************************************************
1798**
1799** gckEVENT_Commit
1800**
1801** Commit an event queue from the user.
1802**
1803** INPUT:
1804**
1805** gckEVENT Event
1806** Pointer to an gckEVENT object.
1807**
1808** gcsQUEUE_PTR Queue
1809** User event queue.
1810**
1811** OUTPUT:
1812**
1813** Nothing.
1814*/
1815gceSTATUS
1816gckEVENT_Commit(
1817 IN gckEVENT Event,
1818 IN gcsQUEUE_PTR Queue
1819 )
1820{
1821 gceSTATUS status;
1822 gcsQUEUE_PTR record = gcvNULL, next;
1823 gctUINT32 processID;
1824 gctBOOL needCopy = gcvFALSE;
1825
1826 gcmkHEADER_ARG("Event=0x%x Queue=0x%x", Event, Queue);
1827
1828 /* Verify the arguments. */
1829 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1830
1831 /* Get the current process ID. */
1832 gcmkONERROR(gckOS_GetProcessID(&processID));
1833
1834 /* Query if we need to copy the client data. */
1835 gcmkONERROR(gckOS_QueryNeedCopy(Event->os, processID, &needCopy));
1836
1837 /* Loop while there are records in the queue. */
1838 while (Queue != gcvNULL)
1839 {
1840 gcsQUEUE queue;
1841
1842 if (needCopy)
1843 {
1844 /* Point to stack record. */
1845 record = &queue;
1846
1847 /* Copy the data from the client. */
1848 gcmkONERROR(gckOS_CopyFromUserData(Event->os,
1849 record,
1850 Queue,
1851 gcmSIZEOF(gcsQUEUE)));
1852 }
1853 else
1854 {
1855 gctPOINTER pointer = gcvNULL;
1856
1857 /* Map record into kernel memory. */
1858 gcmkONERROR(gckOS_MapUserPointer(Event->os,
1859 Queue,
1860 gcmSIZEOF(gcsQUEUE),
1861 &pointer));
1862
1863 record = pointer;
1864 }
1865
1866 /* Append event record to event queue. */
1867 gcmkONERROR(
1868 gckEVENT_AddList(Event, &record->iface, gcvKERNEL_PIXEL, gcvTRUE, gcvFALSE));
1869
1870 /* Next record in the queue. */
1871 next = gcmUINT64_TO_PTR(record->next);
1872
1873 if (!needCopy)
1874 {
1875 /* Unmap record from kernel memory. */
1876 gcmkONERROR(
1877 gckOS_UnmapUserPointer(Event->os,
1878 Queue,
1879 gcmSIZEOF(gcsQUEUE),
1880 (gctPOINTER *) record));
1881 record = gcvNULL;
1882 }
1883
1884 Queue = next;
1885 }
1886
1887 /* Submit the event list. */
1888 gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
1889
1890 /* Success */
1891 gcmkFOOTER_NO();
1892 return gcvSTATUS_OK;
1893
1894OnError:
1895 if ((record != gcvNULL) && !needCopy)
1896 {
1897 /* Roll back. */
1898 gcmkVERIFY_OK(gckOS_UnmapUserPointer(Event->os,
1899 Queue,
1900 gcmSIZEOF(gcsQUEUE),
1901 (gctPOINTER *) record));
1902 }
1903
1904 /* Return the status. */
1905 gcmkFOOTER();
1906 return status;
1907}
1908
1909/*******************************************************************************
1910**
1911** gckEVENT_Compose
1912**
1913** Schedule a composition event and start a composition.
1914**
1915** INPUT:
1916**
1917** gckEVENT Event
1918** Pointer to an gckEVENT object.
1919**
1920** gcsHAL_COMPOSE_PTR Info
1921** Pointer to the composition structure.
1922**
1923** OUTPUT:
1924**
1925** Nothing.
1926*/
1927gceSTATUS
1928gckEVENT_Compose(
1929 IN gckEVENT Event,
1930 IN gcsHAL_COMPOSE_PTR Info
1931 )
1932{
1933 gceSTATUS status;
1934 gcsEVENT_PTR headRecord;
1935 gcsEVENT_PTR tailRecord;
1936 gcsEVENT_PTR tempRecord;
1937 gctUINT8 id = 0xFF;
1938 gctUINT32 processID;
1939
1940 gcmkHEADER_ARG("Event=0x%x Info=0x%x", Event, Info);
1941
1942 /* Verify the arguments. */
1943 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
1944 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
1945
1946 /* Allocate an event ID. */
1947 gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
1948
1949 /* Get process ID. */
1950 gcmkONERROR(gckOS_GetProcessID(&processID));
1951
1952 /* Allocate a record. */
1953 gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
1954 headRecord = tailRecord = tempRecord;
1955
1956 /* Initialize the record. */
1957 tempRecord->info.command = gcvHAL_SIGNAL;
1958 tempRecord->info.u.Signal.process = Info->process;
1959#ifdef __QNXNTO__
1960 tempRecord->info.u.Signal.coid = Info->coid;
1961 tempRecord->info.u.Signal.rcvid = Info->rcvid;
1962#endif
1963 tempRecord->info.u.Signal.signal = Info->signal;
1964 tempRecord->info.u.Signal.auxSignal = 0;
1965 tempRecord->next = gcvNULL;
1966 tempRecord->processID = processID;
1967
1968 /* Allocate another record for user signal #1. */
1969 if (gcmUINT64_TO_PTR(Info->userSignal1) != gcvNULL)
1970 {
1971 /* Allocate a record. */
1972 gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
1973 tailRecord->next = tempRecord;
1974 tailRecord = tempRecord;
1975
1976 /* Initialize the record. */
1977 tempRecord->info.command = gcvHAL_SIGNAL;
1978 tempRecord->info.u.Signal.process = Info->userProcess;
1979#ifdef __QNXNTO__
1980 tempRecord->info.u.Signal.coid = Info->coid;
1981 tempRecord->info.u.Signal.rcvid = Info->rcvid;
1982#endif
1983 tempRecord->info.u.Signal.signal = Info->userSignal1;
1984 tempRecord->info.u.Signal.auxSignal = 0;
1985 tempRecord->next = gcvNULL;
1986 tempRecord->processID = processID;
1987 }
1988
1989 /* Allocate another record for user signal #2. */
1990 if (gcmUINT64_TO_PTR(Info->userSignal2) != gcvNULL)
1991 {
1992 /* Allocate a record. */
1993 gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &tempRecord));
1994 tailRecord->next = tempRecord;
1995
1996 /* Initialize the record. */
1997 tempRecord->info.command = gcvHAL_SIGNAL;
1998 tempRecord->info.u.Signal.process = Info->userProcess;
1999#ifdef __QNXNTO__
2000 tempRecord->info.u.Signal.coid = Info->coid;
2001 tempRecord->info.u.Signal.rcvid = Info->rcvid;
2002#endif
2003 tempRecord->info.u.Signal.signal = Info->userSignal2;
2004 tempRecord->info.u.Signal.auxSignal = 0;
2005 tempRecord->next = gcvNULL;
2006 tempRecord->processID = processID;
2007 }
2008
2009 /* Set the event list. */
2010 Event->queues[id].head = headRecord;
2011
2012 /* Start composition. */
2013 gcmkONERROR(gckHARDWARE_Compose(
2014 Event->kernel->hardware, processID,
2015 gcmUINT64_TO_PTR(Info->physical), gcmUINT64_TO_PTR(Info->logical), Info->offset, Info->size, id
2016 ));
2017
2018 /* Success. */
2019 gcmkFOOTER_NO();
2020 return gcvSTATUS_OK;
2021
2022OnError:
2023 /* Return the status. */
2024 gcmkFOOTER();
2025 return status;
2026}
2027
2028/*******************************************************************************
2029**
2030** gckEVENT_Interrupt
2031**
2032** Called by the interrupt service routine to store the triggered interrupt
2033** mask to be later processed by gckEVENT_Notify.
2034**
2035** INPUT:
2036**
2037** gckEVENT Event
2038** Pointer to an gckEVENT object.
2039**
2040** gctUINT32 Data
2041** Mask for the 32 interrupts.
2042**
2043** OUTPUT:
2044**
2045** Nothing.
2046*/
2047gceSTATUS
2048gckEVENT_Interrupt(
2049 IN gckEVENT Event,
2050 IN gctUINT32 Data
2051 )
2052{
2053 gcmkHEADER_ARG("Event=0x%x Data=0x%x", Event, Data);
2054
2055 /* Verify the arguments. */
2056 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
2057
2058 if (Data & 0x20000000)
2059 {
2060 gckENTRYDATA data;
2061 gctUINT32 idle;
2062 Data &= ~0x20000000;
2063
2064 {
2065 /* Get first entry information. */
2066 gcmkVERIFY_OK(
2067 gckENTRYQUEUE_Dequeue(&Event->kernel->command->queue, &data));
2068
2069 /* Make sure FE is idle. */
2070 do
2071 {
2072 gcmkVERIFY_OK(gckOS_ReadRegisterEx(
2073 Event->os,
2074 Event->kernel->core,
2075 0x4,
2076 &idle));
2077 }
2078 while (idle != 0x7FFFFFFF);
2079
2080
2081 /* Start Command Parser. */
2082 gcmkVERIFY_OK(gckHARDWARE_Execute(
2083 Event->kernel->hardware,
2084 data->physical,
2085 data->bytes
2086 ));
2087 }
2088 }
2089
2090 /* Combine current interrupt status with pending flags. */
2091#if gcdSMP
2092 {
2093 gckOS_AtomSetMask(Event->pending, Data);
2094 }
2095#elif defined(__QNXNTO__)
2096 {
2097 atomic_set(&Event->pending, Data);
2098 }
2099#else
2100 {
2101 Event->pending |= Data;
2102 }
2103#endif
2104
2105#if gcdINTERRUPT_STATISTIC
2106 {
2107 gctINT j = 0;
2108 gctINT32 oldValue;
2109
2110 for (j = 0; j < gcmCOUNTOF(Event->queues); j++)
2111 {
2112 if ((Data & (1 << j)))
2113 {
2114 gcmkVERIFY_OK(gckOS_AtomDecrement(Event->os,
2115 Event->interruptCount,
2116 &oldValue));
2117 }
2118 }
2119 }
2120#endif
2121
2122 /* Success. */
2123 gcmkFOOTER_NO();
2124 return gcvSTATUS_OK;
2125}
2126
2127/*******************************************************************************
2128**
2129** gckEVENT_Notify
2130**
2131** Process all triggered interrupts.
2132**
2133** INPUT:
2134**
2135** gckEVENT Event
2136** Pointer to an gckEVENT object.
2137**
2138** OUTPUT:
2139**
2140** Nothing.
2141*/
2142gceSTATUS
2143gckEVENT_Notify(
2144 IN gckEVENT Event,
2145 IN gctUINT32 IDs
2146 )
2147{
2148 gceSTATUS status = gcvSTATUS_OK;
2149 gctINT i;
2150 gcsEVENT_QUEUE * queue;
2151 gctUINT mask = 0;
2152 gctBOOL acquired = gcvFALSE;
2153 gctPOINTER info;
2154 gctSIGNAL signal;
2155 gctUINT pending = 0;
2156 gckKERNEL kernel = Event->kernel;
2157#if !gcdSMP
2158 gctBOOL suspended = gcvFALSE;
2159#endif
2160#if gcmIS_DEBUG(gcdDEBUG_TRACE)
2161 gctINT eventNumber = 0;
2162#endif
2163 gctINT32 free;
2164#if gcdSECURE_USER
2165 gcskSECURE_CACHE_PTR cache;
2166#endif
2167 gckVIDMEM_NODE nodeObject;
2168 gcuVIDMEM_NODE_PTR node;
2169
2170 gcmkHEADER_ARG("Event=0x%x IDs=0x%x", Event, IDs);
2171
2172 /* Verify the arguments. */
2173 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
2174
2175 gcmDEBUG_ONLY(
2176 if (IDs != 0)
2177 {
2178 for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
2179 {
2180 if (Event->queues[i].head != gcvNULL)
2181 {
2182 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2183 "Queue(%d): stamp=%llu source=%d",
2184 i,
2185 Event->queues[i].stamp,
2186 Event->queues[i].source);
2187 }
2188 }
2189 }
2190 );
2191
2192
2193 for (;;)
2194 {
2195 gcsEVENT_PTR record;
2196
2197 /* Grab the mutex queue. */
2198 gcmkONERROR(gckOS_AcquireMutex(Event->os,
2199 Event->eventQueueMutex,
2200 gcvINFINITE));
2201 acquired = gcvTRUE;
2202
2203#if gcdSMP
2204 {
2205 gckOS_AtomGet(Event->os, Event->pending, (gctINT32_PTR)&pending);
2206 }
2207#else
2208 /* Suspend interrupts. */
2209 gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
2210 suspended = gcvTRUE;
2211
2212 {
2213 pending = Event->pending;
2214 }
2215
2216 /* Resume interrupts. */
2217 gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
2218 suspended = gcvFALSE;
2219#endif
2220
2221
2222 if (pending == 0)
2223 {
2224 /* Release the mutex queue. */
2225 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
2226 acquired = gcvFALSE;
2227
2228 /* No more pending interrupts - done. */
2229 break;
2230 }
2231
2232 if (pending & 0x80000000)
2233 {
2234 gcmkPRINT("[galcore]: AXI BUS ERROR");
2235 gckHARDWARE_DumpGPUState(Event->kernel->hardware);
2236 pending &= 0x7FFFFFFF;
2237 }
2238
2239 if (pending & 0x40000000)
2240 {
2241 gckHARDWARE_DumpMMUException(Event->kernel->hardware);
2242
2243 gckHARDWARE_DumpGPUState(Event->kernel->hardware);
2244
2245 pending &= 0xBFFFFFFF;
2246 }
2247
2248 gcmkTRACE_ZONE_N(
2249 gcvLEVEL_INFO, gcvZONE_EVENT,
2250 gcmSIZEOF(pending),
2251 "Pending interrupts 0x%x",
2252 pending
2253 );
2254
2255 queue = gcvNULL;
2256
2257 gcmDEBUG_ONLY(
2258 if (IDs == 0)
2259 {
2260 for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
2261 {
2262 if (Event->queues[i].head != gcvNULL)
2263 {
2264 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2265 "Queue(%d): stamp=%llu source=%d",
2266 i,
2267 Event->queues[i].stamp,
2268 Event->queues[i].source);
2269 }
2270 }
2271 }
2272 );
2273
2274 /* Find the oldest pending interrupt. */
2275 for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
2276 {
2277 if ((Event->queues[i].head != gcvNULL)
2278 && (pending & (1 << i))
2279 )
2280 {
2281 if ((queue == gcvNULL)
2282 || (Event->queues[i].stamp < queue->stamp)
2283 )
2284 {
2285 queue = &Event->queues[i];
2286 mask = 1 << i;
2287#if gcmIS_DEBUG(gcdDEBUG_TRACE)
2288 eventNumber = i;
2289#endif
2290 }
2291 }
2292 }
2293
2294 if (queue == gcvNULL)
2295 {
2296 gcmkTRACE_ZONE_N(
2297 gcvLEVEL_ERROR, gcvZONE_EVENT,
2298 gcmSIZEOF(pending),
2299 "Interrupts 0x%x are not pending.",
2300 pending
2301 );
2302
2303#if gcdSMP
2304 {
2305 gckOS_AtomClearMask(Event->pending, pending);
2306 }
2307
2308#elif defined(__QNXNTO__)
2309 {
2310 atomic_clr((gctUINT32_PTR)&Event->pending, pending);
2311 }
2312#else
2313 /* Suspend interrupts. */
2314 gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
2315 suspended = gcvTRUE;
2316
2317 {
2318 Event->pending &= ~pending;
2319 }
2320
2321 /* Resume interrupts. */
2322 gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
2323 suspended = gcvFALSE;
2324#endif
2325
2326 /* Release the mutex queue. */
2327 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
2328 acquired = gcvFALSE;
2329 break;
2330 }
2331
2332 /* Check whether there is a missed interrupt. */
2333 for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
2334 {
2335 if ((Event->queues[i].head != gcvNULL)
2336 && (Event->queues[i].stamp < queue->stamp)
2337 && (Event->queues[i].source <= queue->source)
2338 )
2339 {
2340 gcmkTRACE_N(
2341 gcvLEVEL_ERROR,
2342 gcmSIZEOF(i) + gcmSIZEOF(Event->queues[i].stamp),
2343 "Event %d lost (stamp %llu)",
2344 i, Event->queues[i].stamp
2345 );
2346
2347 /* Use this event instead. */
2348 queue = &Event->queues[i];
2349 mask = 0;
2350 }
2351 }
2352
2353 if (mask != 0)
2354 {
2355#if gcmIS_DEBUG(gcdDEBUG_TRACE)
2356 gcmkTRACE_ZONE_N(
2357 gcvLEVEL_INFO, gcvZONE_EVENT,
2358 gcmSIZEOF(eventNumber),
2359 "Processing interrupt %d",
2360 eventNumber
2361 );
2362#endif
2363 }
2364
2365#if gcdSMP
2366 {
2367 gckOS_AtomClearMask(Event->pending, mask);
2368 }
2369
2370#elif defined(__QNXNTO__)
2371 {
2372 atomic_clr(&Event->pending, mask);
2373 }
2374#else
2375 /* Suspend interrupts. */
2376 gcmkONERROR(gckOS_SuspendInterruptEx(Event->os, Event->kernel->core));
2377 suspended = gcvTRUE;
2378
2379 {
2380 Event->pending &= ~mask;
2381 }
2382
2383 /* Resume interrupts. */
2384 gcmkONERROR(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
2385 suspended = gcvFALSE;
2386#endif
2387 /* Write out commit stamp.*/
2388 *(gctUINT64 *)(Event->kernel->command->fence->logical) = queue->commitStamp;
2389
2390 /* Grab the event head. */
2391 record = queue->head;
2392
2393 /* Now quickly clear its event list. */
2394 queue->head = gcvNULL;
2395
2396 /* Release the mutex queue. */
2397 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
2398 acquired = gcvFALSE;
2399
2400 /* Increase the number of free events. */
2401 gcmkONERROR(gckOS_AtomIncrement(Event->os, Event->freeAtom, &free));
2402
2403 /* Walk all events for this interrupt. */
2404 while (record != gcvNULL)
2405 {
2406 gcsEVENT_PTR recordNext;
2407#ifndef __QNXNTO__
2408 gctPOINTER logical;
2409#endif
2410#if gcdSECURE_USER
2411 gctSIZE_T bytes;
2412#endif
2413
2414 /* Grab next record. */
2415 recordNext = record->next;
2416
2417#ifdef __QNXNTO__
2418 /* Assign record->processID as the pid for this galcore thread.
2419 * Used in OS calls like gckOS_UnlockMemory() which do not take a pid.
2420 */
2421 drv_thread_specific_key_assign(record->processID, 0, Event->kernel->core);
2422#endif
2423
2424#if gcdSECURE_USER
2425 /* Get the cache that belongs to this process. */
2426 gcmkONERROR(gckKERNEL_GetProcessDBCache(Event->kernel,
2427 record->processID,
2428 &cache));
2429#endif
2430
2431 gcmkTRACE_ZONE_N(
2432 gcvLEVEL_INFO, gcvZONE_EVENT,
2433 gcmSIZEOF(record->info.command),
2434 "Processing event type: %d",
2435 record->info.command
2436 );
2437
2438 switch (record->info.command)
2439 {
2440 case gcvHAL_FREE_NON_PAGED_MEMORY:
2441 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2442 "gcvHAL_FREE_NON_PAGED_MEMORY: 0x%x",
2443 gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical));
2444
2445 /* Free non-paged memory. */
2446 status = gckOS_FreeNonPagedMemory(
2447 Event->os,
2448 (gctSIZE_T) record->info.u.FreeNonPagedMemory.bytes,
2449 gcmNAME_TO_PTR(record->info.u.FreeNonPagedMemory.physical),
2450 gcmUINT64_TO_PTR(record->info.u.FreeNonPagedMemory.logical));
2451
2452 if (gcmIS_SUCCESS(status))
2453 {
2454#if gcdSECURE_USER
2455 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
2456 Event->kernel,
2457 cache,
2458 gcmUINT64_TO_PTR(record->record.u.FreeNonPagedMemory.logical),
2459 (gctSIZE_T) record->record.u.FreeNonPagedMemory.bytes));
2460#endif
2461 }
2462 gcmRELEASE_NAME(record->info.u.FreeNonPagedMemory.physical);
2463 break;
2464
2465 case gcvHAL_FREE_CONTIGUOUS_MEMORY:
2466 gcmkTRACE_ZONE(
2467 gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2468 "gcvHAL_FREE_CONTIGUOUS_MEMORY: 0x%x",
2469 gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical));
2470
2471 /* Unmap the user memory. */
2472 status = gckOS_FreeContiguous(
2473 Event->os,
2474 gcmNAME_TO_PTR(record->info.u.FreeContiguousMemory.physical),
2475 gcmUINT64_TO_PTR(record->info.u.FreeContiguousMemory.logical),
2476 (gctSIZE_T) record->info.u.FreeContiguousMemory.bytes);
2477
2478 if (gcmIS_SUCCESS(status))
2479 {
2480#if gcdSECURE_USER
2481 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
2482 Event->kernel,
2483 cache,
2484 gcmUINT64_TO_PTR(event->event.u.FreeContiguousMemory.logical),
2485 (gctSIZE_T) event->event.u.FreeContiguousMemory.bytes));
2486#endif
2487 }
2488 gcmRELEASE_NAME(record->info.u.FreeContiguousMemory.physical);
2489 break;
2490
2491 case gcvHAL_WRITE_DATA:
2492#ifndef __QNXNTO__
2493 /* Convert physical into logical address. */
2494 gcmkERR_BREAK(
2495 gckOS_MapPhysical(Event->os,
2496 record->info.u.WriteData.address,
2497 gcmSIZEOF(gctUINT32),
2498 &logical));
2499
2500 /* Write data. */
2501 gcmkERR_BREAK(
2502 gckOS_WriteMemory(Event->os,
2503 logical,
2504 record->info.u.WriteData.data));
2505
2506 /* Unmap the physical memory. */
2507 gcmkERR_BREAK(
2508 gckOS_UnmapPhysical(Event->os,
2509 logical,
2510 gcmSIZEOF(gctUINT32)));
2511#else
2512 /* Write data. */
2513 gcmkERR_BREAK(
2514 gckOS_WriteMemory(Event->os,
2515 (gctPOINTER)
2516 record->info.u.WriteData.address,
2517 record->info.u.WriteData.data));
2518#endif
2519 break;
2520
2521 case gcvHAL_UNLOCK_VIDEO_MEMORY:
2522 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2523 "gcvHAL_UNLOCK_VIDEO_MEMORY: 0x%x",
2524 record->info.u.UnlockVideoMemory.node);
2525
2526 nodeObject = gcmUINT64_TO_PTR(record->info.u.UnlockVideoMemory.node);
2527
2528 node = nodeObject->node;
2529
2530 /* Save node information before it disappears. */
2531#if gcdSECURE_USER
2532 node = event->event.u.UnlockVideoMemory.node;
2533 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
2534 {
2535 logical = gcvNULL;
2536 bytes = 0;
2537 }
2538 else
2539 {
2540 logical = node->Virtual.logical;
2541 bytes = node->Virtual.bytes;
2542 }
2543#endif
2544
2545 /* Unlock. */
2546 status = gckVIDMEM_Unlock(
2547 Event->kernel,
2548 nodeObject,
2549 record->info.u.UnlockVideoMemory.type,
2550 gcvNULL);
2551
2552#if gcdSECURE_USER
2553 if (gcmIS_SUCCESS(status) && (logical != gcvNULL))
2554 {
2555 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
2556 Event->kernel,
2557 cache,
2558 logical,
2559 bytes));
2560 }
2561#endif
2562
2563#if gcdPROCESS_ADDRESS_SPACE
2564 gcmkVERIFY_OK(gckVIDMEM_NODE_Unlock(
2565 Event->kernel,
2566 nodeObject,
2567 record->processID
2568 ));
2569#endif
2570
2571 status = gckVIDMEM_NODE_Dereference(Event->kernel, nodeObject);
2572 break;
2573
2574 case gcvHAL_SIGNAL:
2575 signal = gcmUINT64_TO_PTR(record->info.u.Signal.signal);
2576 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2577 "gcvHAL_SIGNAL: 0x%x",
2578 signal);
2579
2580#ifdef __QNXNTO__
2581 if ((record->info.u.Signal.coid == 0)
2582 && (record->info.u.Signal.rcvid == 0)
2583 )
2584 {
2585 /* Kernel signal. */
2586 gcmkERR_BREAK(
2587 gckOS_SignalPulse(Event->os,
2588 signal));
2589 }
2590 else
2591 {
2592 /* User signal. */
2593 gcmkERR_BREAK(
2594 gckOS_UserSignal(Event->os,
2595 signal,
2596 record->info.u.Signal.rcvid,
2597 record->info.u.Signal.coid));
2598 }
2599#else
2600 /* Set signal. */
2601 if (gcmUINT64_TO_PTR(record->info.u.Signal.process) == gcvNULL)
2602 {
2603 /* Kernel signal. */
2604 gcmkERR_BREAK(
2605 gckOS_Signal(Event->os,
2606 signal,
2607 gcvTRUE));
2608 }
2609 else
2610 {
2611 /* User signal. */
2612 gcmkERR_BREAK(
2613 gckOS_UserSignal(Event->os,
2614 signal,
2615 gcmUINT64_TO_PTR(record->info.u.Signal.process)));
2616 }
2617
2618 gcmkASSERT(record->info.u.Signal.auxSignal == 0);
2619#endif
2620 break;
2621
2622 case gcvHAL_UNMAP_USER_MEMORY:
2623 info = gcmNAME_TO_PTR(record->info.u.UnmapUserMemory.info);
2624 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2625 "gcvHAL_UNMAP_USER_MEMORY: 0x%x",
2626 info);
2627
2628 /* Unmap the user memory. */
2629 status = gckOS_UnmapUserMemory(
2630 Event->os,
2631 Event->kernel->core,
2632 gcmUINT64_TO_PTR(record->info.u.UnmapUserMemory.memory),
2633 (gctSIZE_T) record->info.u.UnmapUserMemory.size,
2634 info,
2635 record->info.u.UnmapUserMemory.address);
2636
2637#if gcdSECURE_USER
2638 if (gcmIS_SUCCESS(status))
2639 {
2640 gcmkVERIFY_OK(gckKERNEL_FlushTranslationCache(
2641 Event->kernel,
2642 cache,
2643 gcmUINT64_TO_PTR(record->info.u.UnmapUserMemory.memory),
2644 (gctSIZE_T) record->info.u.UnmapUserMemory.size));
2645 }
2646#endif
2647 gcmRELEASE_NAME(record->info.u.UnmapUserMemory.info);
2648 break;
2649
2650 case gcvHAL_TIMESTAMP:
2651 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2652 "gcvHAL_TIMESTAMP: %d %d",
2653 record->info.u.TimeStamp.timer,
2654 record->info.u.TimeStamp.request);
2655
2656 /* Process the timestamp. */
2657 switch (record->info.u.TimeStamp.request)
2658 {
2659 case 0:
2660 status = gckOS_GetTime(&Event->kernel->timers[
2661 record->info.u.TimeStamp.timer].
2662 stopTime);
2663 break;
2664
2665 case 1:
2666 status = gckOS_GetTime(&Event->kernel->timers[
2667 record->info.u.TimeStamp.timer].
2668 startTime);
2669 break;
2670
2671 default:
2672 gcmkTRACE_ZONE_N(
2673 gcvLEVEL_ERROR, gcvZONE_EVENT,
2674 gcmSIZEOF(record->info.u.TimeStamp.request),
2675 "Invalid timestamp request: %d",
2676 record->info.u.TimeStamp.request
2677 );
2678
2679 status = gcvSTATUS_INVALID_ARGUMENT;
2680 break;
2681 }
2682 break;
2683
2684 case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
2685 gcmkVERIFY_OK(
2686 gckKERNEL_DestroyVirtualCommandBuffer(Event->kernel,
2687 (gctSIZE_T) record->info.u.FreeVirtualCommandBuffer.bytes,
2688 gcmNAME_TO_PTR(record->info.u.FreeVirtualCommandBuffer.physical),
2689 gcmUINT64_TO_PTR(record->info.u.FreeVirtualCommandBuffer.logical)
2690 ));
2691 gcmRELEASE_NAME(record->info.u.FreeVirtualCommandBuffer.physical);
2692 break;
2693
2694#if gcdANDROID_NATIVE_FENCE_SYNC
2695 case gcvHAL_SYNC_POINT:
2696 {
2697 gctSYNC_POINT syncPoint;
2698
2699 syncPoint = gcmUINT64_TO_PTR(record->info.u.SyncPoint.syncPoint);
2700 status = gckOS_SignalSyncPoint(Event->os, syncPoint);
2701 }
2702 break;
2703#endif
2704
2705#if gcdPROCESS_ADDRESS_SPACE
2706 case gcvHAL_DESTROY_MMU:
2707 status = gckMMU_Destroy(gcmUINT64_TO_PTR(record->info.u.DestroyMmu.mmu));
2708 break;
2709#endif
2710
2711 case gcvHAL_COMMIT_DONE:
2712 break;
2713
2714 default:
2715 /* Invalid argument. */
2716 gcmkTRACE_ZONE_N(
2717 gcvLEVEL_ERROR, gcvZONE_EVENT,
2718 gcmSIZEOF(record->info.command),
2719 "Unknown event type: %d",
2720 record->info.command
2721 );
2722
2723 status = gcvSTATUS_INVALID_ARGUMENT;
2724 break;
2725 }
2726
2727 /* Make sure there are no errors generated. */
2728 if (gcmIS_ERROR(status))
2729 {
2730 gcmkTRACE_ZONE_N(
2731 gcvLEVEL_WARNING, gcvZONE_EVENT,
2732 gcmSIZEOF(status),
2733 "Event produced status: %d(%s)",
2734 status, gckOS_DebugStatus2Name(status));
2735 }
2736
2737 /* Free the event. */
2738 gcmkVERIFY_OK(gckEVENT_FreeRecord(Event, record));
2739
2740 /* Advance to next record. */
2741 record = recordNext;
2742 }
2743
2744 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_EVENT,
2745 "Handled interrupt 0x%x", mask);
2746 }
2747
2748
2749 if (IDs == 0)
2750 {
2751 gcmkONERROR(_TryToIdleGPU(Event));
2752 }
2753
2754 /* Success. */
2755 gcmkFOOTER_NO();
2756 return gcvSTATUS_OK;
2757
2758OnError:
2759 if (acquired)
2760 {
2761 /* Release mutex. */
2762 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
2763 }
2764
2765#if !gcdSMP
2766 if (suspended)
2767 {
2768 /* Resume interrupts. */
2769 gcmkVERIFY_OK(gckOS_ResumeInterruptEx(Event->os, Event->kernel->core));
2770 }
2771#endif
2772
2773 /* Return the status. */
2774 gcmkFOOTER();
2775 return status;
2776}
2777
2778/*******************************************************************************
2779** gckEVENT_FreeProcess
2780**
2781** Free all events owned by a particular process ID.
2782**
2783** INPUT:
2784**
2785** gckEVENT Event
2786** Pointer to an gckEVENT object.
2787**
2788** gctUINT32 ProcessID
2789** Process ID of the process to be freed up.
2790**
2791** OUTPUT:
2792**
2793** Nothing.
2794*/
2795gceSTATUS
2796gckEVENT_FreeProcess(
2797 IN gckEVENT Event,
2798 IN gctUINT32 ProcessID
2799 )
2800{
2801 gctSIZE_T i;
2802 gctBOOL acquired = gcvFALSE;
2803 gcsEVENT_PTR record, next;
2804 gceSTATUS status;
2805 gcsEVENT_PTR deleteHead, deleteTail;
2806
2807 gcmkHEADER_ARG("Event=0x%x ProcessID=%d", Event, ProcessID);
2808
2809 /* Verify the arguments. */
2810 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
2811
2812 /* Walk through all queues. */
2813 for (i = 0; i < gcmCOUNTOF(Event->queues); ++i)
2814 {
2815 if (Event->queues[i].head != gcvNULL)
2816 {
2817 /* Grab the event queue mutex. */
2818 gcmkONERROR(gckOS_AcquireMutex(Event->os,
2819 Event->eventQueueMutex,
2820 gcvINFINITE));
2821 acquired = gcvTRUE;
2822
2823 /* Grab the mutex head. */
2824 record = Event->queues[i].head;
2825 Event->queues[i].head = gcvNULL;
2826 Event->queues[i].tail = gcvNULL;
2827 deleteHead = gcvNULL;
2828 deleteTail = gcvNULL;
2829
2830 while (record != gcvNULL)
2831 {
2832 next = record->next;
2833 if (record->processID == ProcessID)
2834 {
2835 if (deleteHead == gcvNULL)
2836 {
2837 deleteHead = record;
2838 }
2839 else
2840 {
2841 deleteTail->next = record;
2842 }
2843
2844 deleteTail = record;
2845 }
2846 else
2847 {
2848 if (Event->queues[i].head == gcvNULL)
2849 {
2850 Event->queues[i].head = record;
2851 }
2852 else
2853 {
2854 Event->queues[i].tail->next = record;
2855 }
2856
2857 Event->queues[i].tail = record;
2858 }
2859
2860 record->next = gcvNULL;
2861 record = next;
2862 }
2863
2864 /* Release the mutex queue. */
2865 gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
2866 acquired = gcvFALSE;
2867
2868 /* Loop through the entire list of events. */
2869 for (record = deleteHead; record != gcvNULL; record = next)
2870 {
2871 /* Get the next event record. */
2872 next = record->next;
2873
2874 /* Free the event record. */
2875 gcmkONERROR(gckEVENT_FreeRecord(Event, record));
2876 }
2877 }
2878 }
2879
2880 gcmkONERROR(_TryToIdleGPU(Event));
2881
2882 /* Success. */
2883 gcmkFOOTER_NO();
2884 return gcvSTATUS_OK;
2885
2886OnError:
2887 /* Release the event queue mutex. */
2888 if (acquired)
2889 {
2890 gcmkVERIFY_OK(gckOS_ReleaseMutex(Event->os, Event->eventQueueMutex));
2891 }
2892
2893 /* Return the status. */
2894 gcmkFOOTER();
2895 return status;
2896}
2897
2898/*******************************************************************************
2899** gckEVENT_Stop
2900**
2901** Stop the hardware using the End event mechanism.
2902**
2903** INPUT:
2904**
2905** gckEVENT Event
2906** Pointer to an gckEVENT object.
2907**
2908** gctUINT32 ProcessID
2909** Process ID Logical belongs.
2910**
2911** gctPHYS_ADDR Handle
2912** Physical address handle. If gcvNULL it is video memory.
2913**
2914** gctPOINTER Logical
2915** Logical address to flush.
2916**
2917** gctSIGNAL Signal
2918** Pointer to the signal to trigger.
2919**
2920** OUTPUT:
2921**
2922** Nothing.
2923*/
2924gceSTATUS
2925gckEVENT_Stop(
2926 IN gckEVENT Event,
2927 IN gctUINT32 ProcessID,
2928 IN gctUINT32 Handle,
2929 IN gctPOINTER Logical,
2930 IN gctSIGNAL Signal,
2931 IN OUT gctUINT32 * waitSize
2932 )
2933{
2934 gceSTATUS status;
2935 /* gctSIZE_T waitSize;*/
2936 gcsEVENT_PTR record;
2937 gctUINT8 id = 0xFF;
2938
2939 gcmkHEADER_ARG("Event=0x%x ProcessID=%u Handle=0x%x Logical=0x%x "
2940 "Signal=0x%x",
2941 Event, ProcessID, Handle, Logical, Signal);
2942
2943 /* Verify the arguments. */
2944 gcmkVERIFY_OBJECT(Event, gcvOBJ_EVENT);
2945
2946 /* Submit the current event queue. */
2947 gcmkONERROR(gckEVENT_Submit(Event, gcvTRUE, gcvFALSE));
2948 gcmkONERROR(gckEVENT_GetEvent(Event, gcvTRUE, &id, gcvKERNEL_PIXEL));
2949
2950 /* Allocate a record. */
2951 gcmkONERROR(gckEVENT_AllocateRecord(Event, gcvTRUE, &record));
2952
2953 /* Initialize the record. */
2954 record->next = gcvNULL;
2955 record->processID = ProcessID;
2956 record->info.command = gcvHAL_SIGNAL;
2957 record->info.u.Signal.signal = gcmPTR_TO_UINT64(Signal);
2958#ifdef __QNXNTO__
2959 record->info.u.Signal.coid = 0;
2960 record->info.u.Signal.rcvid = 0;
2961#endif
2962 record->info.u.Signal.auxSignal = 0;
2963 record->info.u.Signal.process = 0;
2964
2965 /* Append the record. */
2966 Event->queues[id].head = record;
2967
2968 /* Replace last WAIT with END. */
2969 gcmkONERROR(gckHARDWARE_End(
2970 Event->kernel->hardware, Logical, waitSize
2971 ));
2972
2973#if gcdNONPAGED_MEMORY_CACHEABLE
2974 /* Flush the cache for the END. */
2975 gcmkONERROR(gckOS_CacheClean(
2976 Event->os,
2977 ProcessID,
2978 gcvNULL,
2979 (gctUINT32)Handle,
2980 Logical,
2981 *waitSize
2982 ));
2983#endif
2984
2985 /* Wait for the signal. */
2986 gcmkONERROR(gckOS_WaitSignal(Event->os, Signal, gcvINFINITE));
2987
2988 /* Success. */
2989 gcmkFOOTER_NO();
2990 return gcvSTATUS_OK;
2991
2992OnError:
2993
2994 /* Return the status. */
2995 gcmkFOOTER();
2996 return status;
2997}
2998
2999static void
3000_PrintRecord(
3001 gcsEVENT_PTR record
3002 )
3003{
3004 switch (record->info.command)
3005 {
3006 case gcvHAL_FREE_NON_PAGED_MEMORY:
3007 gcmkPRINT(" gcvHAL_FREE_NON_PAGED_MEMORY");
3008 break;
3009
3010 case gcvHAL_FREE_CONTIGUOUS_MEMORY:
3011 gcmkPRINT(" gcvHAL_FREE_CONTIGUOUS_MEMORY");
3012 break;
3013
3014 case gcvHAL_WRITE_DATA:
3015 gcmkPRINT(" gcvHAL_WRITE_DATA");
3016 break;
3017
3018 case gcvHAL_UNLOCK_VIDEO_MEMORY:
3019 gcmkPRINT(" gcvHAL_UNLOCK_VIDEO_MEMORY");
3020 break;
3021
3022 case gcvHAL_SIGNAL:
3023 gcmkPRINT(" gcvHAL_SIGNAL process=%d signal=0x%x",
3024 record->info.u.Signal.process,
3025 record->info.u.Signal.signal);
3026 break;
3027
3028 case gcvHAL_UNMAP_USER_MEMORY:
3029 gcmkPRINT(" gcvHAL_UNMAP_USER_MEMORY");
3030 break;
3031
3032 case gcvHAL_TIMESTAMP:
3033 gcmkPRINT(" gcvHAL_TIMESTAMP");
3034 break;
3035
3036 case gcvHAL_COMMIT_DONE:
3037 gcmkPRINT(" gcvHAL_COMMIT_DONE");
3038 break;
3039
3040 case gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER:
3041 gcmkPRINT(" gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER logical=0x%08x",
3042 record->info.u.FreeVirtualCommandBuffer.logical);
3043 break;
3044
3045 case gcvHAL_SYNC_POINT:
3046 gcmkPRINT(" gcvHAL_SYNC_POINT syncPoint=0x%08x",
3047 gcmUINT64_TO_PTR(record->info.u.SyncPoint.syncPoint));
3048
3049 break;
3050
3051 case gcvHAL_DESTROY_MMU:
3052 gcmkPRINT(" gcvHAL_DESTORY_MMU mmu=0x%08x",
3053 gcmUINT64_TO_PTR(record->info.u.DestroyMmu.mmu));
3054
3055 break;
3056 default:
3057 gcmkPRINT(" Illegal Event %d", record->info.command);
3058 break;
3059 }
3060}
3061
3062/*******************************************************************************
3063** gckEVENT_Dump
3064**
3065** Dump record in event queue when stuck happens.
3066** No protection for the event queue.
3067**/
3068gceSTATUS
3069gckEVENT_Dump(
3070 IN gckEVENT Event
3071 )
3072{
3073 gcsEVENT_QUEUE_PTR queueHead = Event->queueHead;
3074 gcsEVENT_QUEUE_PTR queue;
3075 gcsEVENT_PTR record = gcvNULL;
3076 gctINT i;
3077#if gcdINTERRUPT_STATISTIC
3078 gctINT32 pendingInterrupt;
3079 gctUINT32 intrAcknowledge;
3080#endif
3081
3082 gcmkHEADER_ARG("Event=0x%x", Event);
3083
3084 gcmkPRINT("**************************\n");
3085 gcmkPRINT("*** EVENT STATE DUMP ***\n");
3086 gcmkPRINT("**************************\n");
3087
3088 gcmkPRINT(" Unsumbitted Event:");
3089 while(queueHead)
3090 {
3091 queue = queueHead;
3092 record = queueHead->head;
3093
3094 gcmkPRINT(" [%x]:", queue);
3095 while(record)
3096 {
3097 _PrintRecord(record);
3098 record = record->next;
3099 }
3100
3101 if (queueHead == Event->queueTail)
3102 {
3103 queueHead = gcvNULL;
3104 }
3105 else
3106 {
3107 queueHead = queueHead->next;
3108 }
3109 }
3110
3111 gcmkPRINT(" Untriggered Event:");
3112 for (i = 0; i < gcmCOUNTOF(Event->queues); i++)
3113 {
3114 queue = &Event->queues[i];
3115 record = queue->head;
3116
3117 gcmkPRINT(" [%d]:", i);
3118 while(record)
3119 {
3120 _PrintRecord(record);
3121 record = record->next;
3122 }
3123 }
3124
3125#if gcdINTERRUPT_STATISTIC
3126 gckOS_AtomGet(Event->os, Event->interruptCount, &pendingInterrupt);
3127 gcmkPRINT(" Number of Pending Interrupt: %d", pendingInterrupt);
3128
3129 if (Event->kernel->recovery == 0)
3130 {
3131 gckOS_ReadRegisterEx(
3132 Event->os,
3133 Event->kernel->core,
3134 0x10,
3135 &intrAcknowledge
3136 );
3137
3138 gcmkPRINT(" INTR_ACKNOWLEDGE=0x%x", intrAcknowledge);
3139 }
3140#endif
3141
3142 gcmkFOOTER_NO();
3143 return gcvSTATUS_OK;
3144}
3145
diff --git a/src/hal/kernel/gc_hal_kernel_heap.c b/src/hal/kernel/gc_hal_kernel_heap.c
new file mode 100755
index 0000000..3d7da98
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_heap.c
@@ -0,0 +1,892 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56/**
57** @file
58** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
59** based memory allocation. An arena-based memory heap allocates data quickly
60** from specified arenas and reduces memory fragmentation.
61**
62*/
63#include "gc_hal_kernel_precomp.h"
64
65#define _GC_OBJ_ZONE gcvZONE_HEAP
66
67/*******************************************************************************
68***** Structures ***************************************************************
69*******************************************************************************/
70#define gcdIN_USE ((gcskNODE_PTR)gcvMAXUINTPTR_T)
71
72typedef struct _gcskNODE * gcskNODE_PTR;
73typedef struct _gcskNODE
74{
75 /* Number of byets in node. */
76 gctSIZE_T bytes;
77
78 /* Pointer to next free node, or gcvNULL to mark the node as freed, or
79 ** gcdIN_USE to mark the node as used. */
80 gcskNODE_PTR next;
81
82#if gcmIS_DEBUG(gcdDEBUG_CODE)
83 /* Time stamp of allocation. */
84 gctUINT64 timeStamp;
85#endif
86}
87gcskNODE;
88
89typedef struct _gcskHEAP * gcskHEAP_PTR;
90typedef struct _gcskHEAP
91{
92 /* Linked list. */
93 gcskHEAP_PTR next;
94 gcskHEAP_PTR prev;
95
96 /* Heap size. */
97 gctSIZE_T size;
98
99 /* Free list. */
100 gcskNODE_PTR freeList;
101}
102gcskHEAP;
103
104struct _gckHEAP
105{
106 /* Object. */
107 gcsOBJECT object;
108
109 /* Pointer to a gckOS object. */
110 gckOS os;
111
112 /* Locking mutex. */
113 gctPOINTER mutex;
114
115 /* Allocation parameters. */
116 gctSIZE_T allocationSize;
117
118 /* Heap list. */
119 gcskHEAP_PTR heap;
120#if gcmIS_DEBUG(gcdDEBUG_CODE)
121 gctUINT64 timeStamp;
122#endif
123
124#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
125 /* Profile information. */
126 gctUINT32 allocCount;
127 gctUINT64 allocBytes;
128 gctUINT64 allocBytesMax;
129 gctUINT64 allocBytesTotal;
130 gctUINT32 heapCount;
131 gctUINT32 heapCountMax;
132 gctUINT64 heapMemory;
133 gctUINT64 heapMemoryMax;
134#endif
135};
136
137/*******************************************************************************
138***** Static Support Functions *************************************************
139*******************************************************************************/
140
141#if gcmIS_DEBUG(gcdDEBUG_CODE)
142static gctSIZE_T
143_DumpHeap(
144 IN gcskHEAP_PTR Heap
145 )
146{
147 gctPOINTER p;
148 gctSIZE_T leaked = 0;
149
150 /* Start at first node. */
151 for (p = Heap + 1;;)
152 {
153 /* Convert the pointer. */
154 gcskNODE_PTR node = (gcskNODE_PTR) p;
155
156 /* Check if this is a used node. */
157 if (node->next == gcdIN_USE)
158 {
159 /* Print the leaking node. */
160 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
161 "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
162 "(%08X %c%c%c%c)",
163 node, node->bytes, node->timeStamp,
164 ((gctUINT32_PTR) (node + 1))[0],
165 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
166 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
167 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
168 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
169
170 /* Add leaking byte count. */
171 leaked += node->bytes;
172 }
173
174 /* Test for end of heap. */
175 if (node->bytes == 0)
176 {
177 break;
178 }
179
180 else
181 {
182 /* Move to next node. */
183 p = (gctUINT8_PTR) node + node->bytes;
184 }
185 }
186
187 /* Return the number of leaked bytes. */
188 return leaked;
189}
190#endif
191
192static gceSTATUS
193_CompactKernelHeap(
194 IN gckHEAP Heap
195 )
196{
197 gcskHEAP_PTR heap, next;
198 gctPOINTER p;
199 gcskHEAP_PTR freeList = gcvNULL;
200
201 gcmkHEADER_ARG("Heap=0x%x", Heap);
202
203 /* Walk all the heaps. */
204 for (heap = Heap->heap; heap != gcvNULL; heap = next)
205 {
206 gcskNODE_PTR lastFree = gcvNULL;
207
208 /* Zero out the free list. */
209 heap->freeList = gcvNULL;
210
211 /* Start at the first node. */
212 for (p = (gctUINT8_PTR) (heap + 1);;)
213 {
214 /* Convert the pointer. */
215 gcskNODE_PTR node = (gcskNODE_PTR) p;
216
217 gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
218
219 /* Test if this node not used. */
220 if (node->next != gcdIN_USE)
221 {
222 /* Test if this is the end of the heap. */
223 if (node->bytes == 0)
224 {
225 break;
226 }
227
228 /* Test of this is the first free node. */
229 else if (lastFree == gcvNULL)
230 {
231 /* Initialzie the free list. */
232 heap->freeList = node;
233 lastFree = node;
234 }
235
236 else
237 {
238 /* Test if this free node is contiguous with the previous
239 ** free node. */
240 if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
241 {
242 /* Just increase the size of the previous free node. */
243 lastFree->bytes += node->bytes;
244 }
245 else
246 {
247 /* Add to linked list. */
248 lastFree->next = node;
249 lastFree = node;
250 }
251 }
252 }
253
254 /* Move to next node. */
255 p = (gctUINT8_PTR) node + node->bytes;
256 }
257
258 /* Mark the end of the chain. */
259 if (lastFree != gcvNULL)
260 {
261 lastFree->next = gcvNULL;
262 }
263
264 /* Get next heap. */
265 next = heap->next;
266
267 /* Check if the entire heap is free. */
268 if ((heap->freeList != gcvNULL)
269 && (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
270 )
271 {
272 /* Remove the heap from the linked list. */
273 if (heap->prev == gcvNULL)
274 {
275 Heap->heap = next;
276 }
277 else
278 {
279 heap->prev->next = next;
280 }
281
282 if (heap->next != gcvNULL)
283 {
284 heap->next->prev = heap->prev;
285 }
286
287#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
288 /* Update profiling. */
289 Heap->heapCount -= 1;
290 Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
291#endif
292
293 /* Add this heap to the list of heaps that need to be freed. */
294 heap->next = freeList;
295 freeList = heap;
296 }
297 }
298
299 if (freeList != gcvNULL)
300 {
301 /* Release the mutex, remove any chance for a dead lock. */
302 gcmkVERIFY_OK(
303 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
304
305 /* Free all heaps in the free list. */
306 for (heap = freeList; heap != gcvNULL; heap = next)
307 {
308 /* Get pointer to the next heap. */
309 next = heap->next;
310
311 /* Free the heap. */
312 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
313 "Freeing heap 0x%x (%lu bytes)",
314 heap, heap->size + gcmSIZEOF(gcskHEAP));
315 gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
316 }
317
318 /* Acquire the mutex again. */
319 gcmkVERIFY_OK(
320 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
321 }
322
323 /* Success. */
324 gcmkFOOTER_NO();
325 return gcvSTATUS_OK;
326}
327
328/*******************************************************************************
329***** gckHEAP API Code *********************************************************
330*******************************************************************************/
331
332/*******************************************************************************
333**
334** gckHEAP_Construct
335**
336** Construct a new gckHEAP object.
337**
338** INPUT:
339**
340** gckOS Os
341** Pointer to a gckOS object.
342**
343** gctSIZE_T AllocationSize
344** Minimum size per arena.
345**
346** OUTPUT:
347**
348** gckHEAP * Heap
349** Pointer to a variable that will hold the pointer to the gckHEAP
350** object.
351*/
352gceSTATUS
353gckHEAP_Construct(
354 IN gckOS Os,
355 IN gctSIZE_T AllocationSize,
356 OUT gckHEAP * Heap
357 )
358{
359 gceSTATUS status;
360 gckHEAP heap = gcvNULL;
361 gctPOINTER pointer = gcvNULL;
362
363 gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
364
365 /* Verify the arguments. */
366 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
367 gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
368
369 /* Allocate the gckHEAP object. */
370 gcmkONERROR(gckOS_AllocateMemory(Os,
371 gcmSIZEOF(struct _gckHEAP),
372 &pointer));
373
374 heap = pointer;
375
376 /* Initialize the gckHEAP object. */
377 heap->object.type = gcvOBJ_HEAP;
378 heap->os = Os;
379 heap->allocationSize = AllocationSize;
380 heap->heap = gcvNULL;
381#if gcmIS_DEBUG(gcdDEBUG_CODE)
382 heap->timeStamp = 0;
383#endif
384
385#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
386 /* Zero the counters. */
387 heap->allocCount = 0;
388 heap->allocBytes = 0;
389 heap->allocBytesMax = 0;
390 heap->allocBytesTotal = 0;
391 heap->heapCount = 0;
392 heap->heapCountMax = 0;
393 heap->heapMemory = 0;
394 heap->heapMemoryMax = 0;
395#endif
396
397 /* Create the mutex. */
398 gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
399
400 /* Return the pointer to the gckHEAP object. */
401 *Heap = heap;
402
403 /* Success. */
404 gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
405 return gcvSTATUS_OK;
406
407OnError:
408 /* Roll back. */
409 if (heap != gcvNULL)
410 {
411 /* Free the heap structure. */
412 gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
413 }
414
415 /* Return the status. */
416 gcmkFOOTER();
417 return status;
418}
419
420/*******************************************************************************
421**
422** gckHEAP_Destroy
423**
424** Destroy a gckHEAP object.
425**
426** INPUT:
427**
428** gckHEAP Heap
429** Pointer to a gckHEAP object to destroy.
430**
431** OUTPUT:
432**
433** Nothing.
434*/
435gceSTATUS
436gckHEAP_Destroy(
437 IN gckHEAP Heap
438 )
439{
440 gcskHEAP_PTR heap;
441#if gcmIS_DEBUG(gcdDEBUG_CODE)
442 gctSIZE_T leaked = 0;
443#endif
444
445 gcmkHEADER_ARG("Heap=0x%x", Heap);
446
447 for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
448 {
449 /* Unlink heap from linked list. */
450 Heap->heap = heap->next;
451
452#if gcmIS_DEBUG(gcdDEBUG_CODE)
453 /* Check for leaked memory. */
454 leaked += _DumpHeap(heap);
455#endif
456
457 /* Free the heap. */
458 gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
459 }
460
461 /* Free the mutex. */
462 gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
463
464 /* Free the heap structure. */
465 gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
466
467 /* Success. */
468#if gcmIS_DEBUG(gcdDEBUG_CODE)
469 gcmkFOOTER_ARG("leaked=%lu", leaked);
470#else
471 gcmkFOOTER_NO();
472#endif
473 return gcvSTATUS_OK;
474}
475
476/*******************************************************************************
477**
478** gckHEAP_Allocate
479**
480** Allocate data from the heap.
481**
482** INPUT:
483**
484** gckHEAP Heap
485** Pointer to a gckHEAP object.
486**
487** IN gctSIZE_T Bytes
488** Number of byte to allocate.
489**
490** OUTPUT:
491**
492** gctPOINTER * Memory
493** Pointer to a variable that will hold the address of the allocated
494** memory.
495*/
496gceSTATUS
497gckHEAP_Allocate(
498 IN gckHEAP Heap,
499 IN gctSIZE_T Bytes,
500 OUT gctPOINTER * Memory
501 )
502{
503 gctBOOL acquired = gcvFALSE;
504 gcskHEAP_PTR heap;
505 gceSTATUS status;
506 gctSIZE_T bytes;
507 gcskNODE_PTR node, used, prevFree = gcvNULL;
508 gctPOINTER memory = gcvNULL;
509
510 gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
511
512 /* Verify the arguments. */
513 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
514 gcmkVERIFY_ARGUMENT(Bytes > 0);
515 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
516
517 /* Determine number of bytes required for a node. */
518 bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
519
520 /* Acquire the mutex. */
521 gcmkONERROR(
522 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
523
524 acquired = gcvTRUE;
525
526 /* Check if this allocation is bigger than the default allocation size. */
527 if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
528 {
529 /* Adjust allocation size. */
530 Heap->allocationSize = bytes * 2;
531 }
532
533 else if (Heap->heap != gcvNULL)
534 {
535 gctINT i;
536
537 /* 2 retries, since we might need to compact. */
538 for (i = 0; i < 2; ++i)
539 {
540 /* Walk all the heaps. */
541 for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
542 {
543 /* Check if this heap has enough bytes to hold the request. */
544 if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
545 {
546 prevFree = gcvNULL;
547
548 /* Walk the chain of free nodes. */
549 for (node = heap->freeList;
550 node != gcvNULL;
551 node = node->next
552 )
553 {
554 gcmkASSERT(node->next != gcdIN_USE);
555
556 /* Check if this free node has enough bytes. */
557 if (node->bytes >= bytes)
558 {
559 /* Use the node. */
560 goto UseNode;
561 }
562
563 /* Save current free node for linked list management. */
564 prevFree = node;
565 }
566 }
567 }
568
569 if (i == 0)
570 {
571 /* Compact the heap. */
572 gcmkVERIFY_OK(_CompactKernelHeap(Heap));
573
574#if gcmIS_DEBUG(gcdDEBUG_CODE)
575 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
576 "===== KERNEL HEAP =====");
577 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
578 "Number of allocations : %12u",
579 Heap->allocCount);
580 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
581 "Number of bytes allocated : %12llu",
582 Heap->allocBytes);
583 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
584 "Maximum allocation size : %12llu",
585 Heap->allocBytesMax);
586 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
587 "Total number of bytes allocated : %12llu",
588 Heap->allocBytesTotal);
589 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
590 "Number of heaps : %12u",
591 Heap->heapCount);
592 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
593 "Heap memory in bytes : %12llu",
594 Heap->heapMemory);
595 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
596 "Maximum number of heaps : %12u",
597 Heap->heapCountMax);
598 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
599 "Maximum heap memory in bytes : %12llu",
600 Heap->heapMemoryMax);
601#endif
602 }
603 }
604 }
605
606 /* Release the mutex. */
607 gcmkONERROR(
608 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
609
610 acquired = gcvFALSE;
611
612 /* Allocate a new heap. */
613 gcmkONERROR(
614 gckOS_AllocateMemory(Heap->os,
615 Heap->allocationSize,
616 &memory));
617
618 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
619 "Allocated heap 0x%x (%lu bytes)",
620 memory, Heap->allocationSize);
621
622 /* Acquire the mutex. */
623 gcmkONERROR(
624 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
625
626 acquired = gcvTRUE;
627
628 /* Use the allocated memory as the heap. */
629 heap = (gcskHEAP_PTR) memory;
630
631 /* Insert this heap to the head of the chain. */
632 heap->next = Heap->heap;
633 heap->prev = gcvNULL;
634 heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
635
636 if (heap->next != gcvNULL)
637 {
638 heap->next->prev = heap;
639 }
640 Heap->heap = heap;
641
642 /* Mark the end of the heap. */
643 node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
644 + Heap->allocationSize
645 - gcmSIZEOF(gcskNODE)
646 );
647 node->bytes = 0;
648 node->next = gcvNULL;
649
650 /* Create a free list. */
651 node = (gcskNODE_PTR) (heap + 1);
652 heap->freeList = node;
653
654 /* Initialize the free list. */
655 node->bytes = heap->size - gcmSIZEOF(gcskNODE);
656 node->next = gcvNULL;
657
658 /* No previous free. */
659 prevFree = gcvNULL;
660
661#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
662 /* Update profiling. */
663 Heap->heapCount += 1;
664 Heap->heapMemory += Heap->allocationSize;
665
666 if (Heap->heapCount > Heap->heapCountMax)
667 {
668 Heap->heapCountMax = Heap->heapCount;
669 }
670 if (Heap->heapMemory > Heap->heapMemoryMax)
671 {
672 Heap->heapMemoryMax = Heap->heapMemory;
673 }
674#endif
675
676UseNode:
677 /* Verify some stuff. */
678 gcmkASSERT(heap != gcvNULL);
679 gcmkASSERT(node != gcvNULL);
680 gcmkASSERT(node->bytes >= bytes);
681
682 if (heap->prev != gcvNULL)
683 {
684 /* Unlink the heap from the linked list. */
685 heap->prev->next = heap->next;
686 if (heap->next != gcvNULL)
687 {
688 heap->next->prev = heap->prev;
689 }
690
691 /* Move the heap to the front of the list. */
692 heap->next = Heap->heap;
693 heap->prev = gcvNULL;
694 Heap->heap = heap;
695 heap->next->prev = heap;
696 }
697
698 /* Check if there is enough free space left after usage for another free
699 ** node. */
700 if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
701 {
702 /* Allocated used space from the back of the free list. */
703 used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
704
705 /* Adjust the number of free bytes. */
706 node->bytes -= bytes;
707 gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
708 }
709 else
710 {
711 /* Remove this free list from the chain. */
712 if (prevFree == gcvNULL)
713 {
714 heap->freeList = node->next;
715 }
716 else
717 {
718 prevFree->next = node->next;
719 }
720
721 /* Consume the entire free node. */
722 used = (gcskNODE_PTR) node;
723 bytes = node->bytes;
724 }
725
726 /* Mark node as used. */
727 used->bytes = bytes;
728 used->next = gcdIN_USE;
729#if gcmIS_DEBUG(gcdDEBUG_CODE)
730 used->timeStamp = ++Heap->timeStamp;
731#endif
732
733#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
734 /* Update profile counters. */
735 Heap->allocCount += 1;
736 Heap->allocBytes += bytes;
737 Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
738 Heap->allocBytesTotal += bytes;
739#endif
740
741 /* Release the mutex. */
742 gcmkVERIFY_OK(
743 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
744
745 /* Return pointer to memory. */
746 *Memory = used + 1;
747
748 /* Success. */
749 gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
750 return gcvSTATUS_OK;
751
752OnError:
753 if (acquired)
754 {
755 /* Release the mutex. */
756 gcmkVERIFY_OK(
757 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
758 }
759
760 if (memory != gcvNULL)
761 {
762 /* Free the heap memory. */
763 gckOS_FreeMemory(Heap->os, memory);
764 }
765
766 /* Return the status. */
767 gcmkFOOTER();
768 return status;
769}
770
771/*******************************************************************************
772**
773** gckHEAP_Free
774**
775** Free allocated memory from the heap.
776**
777** INPUT:
778**
779** gckHEAP Heap
780** Pointer to a gckHEAP object.
781**
782** IN gctPOINTER Memory
783** Pointer to memory to free.
784**
785** OUTPUT:
786**
787** NOTHING.
788*/
789gceSTATUS
790gckHEAP_Free(
791 IN gckHEAP Heap,
792 IN gctPOINTER Memory
793 )
794{
795 gcskNODE_PTR node;
796 gceSTATUS status;
797
798 gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
799
800 /* Verify the arguments. */
801 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
802 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
803
804 /* Acquire the mutex. */
805 gcmkONERROR(
806 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
807
808 /* Pointer to structure. */
809 node = (gcskNODE_PTR) Memory - 1;
810
811 /* Mark the node as freed. */
812 node->next = gcvNULL;
813
814#if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
815 /* Update profile counters. */
816 Heap->allocBytes -= node->bytes;
817#endif
818
819 /* Release the mutex. */
820 gcmkVERIFY_OK(
821 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
822
823 /* Success. */
824 gcmkFOOTER_NO();
825 return gcvSTATUS_OK;
826
827OnError:
828 /* Return the status. */
829 gcmkFOOTER();
830 return status;
831}
832
833#if VIVANTE_PROFILER
834gceSTATUS
835gckHEAP_ProfileStart(
836 IN gckHEAP Heap
837 )
838{
839 gcmkHEADER_ARG("Heap=0x%x", Heap);
840
841 /* Verify the arguments. */
842 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
843
844 /* Zero the counters. */
845 Heap->allocCount = 0;
846 Heap->allocBytes = 0;
847 Heap->allocBytesMax = 0;
848 Heap->allocBytesTotal = 0;
849 Heap->heapCount = 0;
850 Heap->heapCountMax = 0;
851 Heap->heapMemory = 0;
852 Heap->heapMemoryMax = 0;
853
854 /* Success. */
855 gcmkFOOTER_NO();
856 return gcvSTATUS_OK;
857}
858
859gceSTATUS
860gckHEAP_ProfileEnd(
861 IN gckHEAP Heap,
862 IN gctCONST_STRING Title
863 )
864{
865 gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
866
867 /* Verify the arguments. */
868 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
869 gcmkVERIFY_ARGUMENT(Title != gcvNULL);
870
871 gcmkPRINT("");
872 gcmkPRINT("=====[ HEAP - %s ]=====", Title);
873 gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
874 gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
875 gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
876 gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
877 gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
878 gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
879 gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
880 gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
881 gcmkPRINT("==============================================");
882
883 /* Success. */
884 gcmkFOOTER_NO();
885 return gcvSTATUS_OK;
886}
887#endif /* VIVANTE_PROFILER */
888
889/*******************************************************************************
890***** Test Code ****************************************************************
891*******************************************************************************/
892
diff --git a/src/hal/kernel/gc_hal_kernel_mmu.c b/src/hal/kernel/gc_hal_kernel_mmu.c
new file mode 100755
index 0000000..b6baf0a
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_mmu.c
@@ -0,0 +1,2315 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57
58#define _GC_OBJ_ZONE gcvZONE_MMU
59
60typedef enum _gceMMU_TYPE
61{
62 gcvMMU_USED = (0 << 4),
63 gcvMMU_SINGLE = (1 << 4),
64 gcvMMU_FREE = (2 << 4),
65}
66gceMMU_TYPE;
67
68#define gcmENTRY_TYPE(x) (x & 0xF0)
69
70#define gcdMMU_TABLE_DUMP 0
71
72#define gcdUSE_MMU_EXCEPTION 0
73
74/*
75 gcdMMU_CLEAR_VALUE
76
77 The clear value for the entry of the old MMU.
78*/
79#ifndef gcdMMU_CLEAR_VALUE
80# define gcdMMU_CLEAR_VALUE 0x00000ABC
81#endif
82
83#define gcdVERTEX_START (128 << 10)
84
85typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
86
87typedef struct _gcsMMU_STLB
88{
89 gctPHYS_ADDR physical;
90 gctUINT32_PTR logical;
91 gctSIZE_T size;
92 gctUINT32 physBase;
93 gctSIZE_T pageCount;
94 gctUINT32 mtlbIndex;
95 gctUINT32 mtlbEntryNum;
96 gcsMMU_STLB_PTR next;
97} gcsMMU_STLB;
98
99#if gcdSHARED_PAGETABLE
100typedef struct _gcsSharedPageTable * gcsSharedPageTable_PTR;
101typedef struct _gcsSharedPageTable
102{
103 /* Shared gckMMU object. */
104 gckMMU mmu;
105
106 /* Hardwares which use this shared pagetable. */
107 gckHARDWARE hardwares[gcdMAX_GPU_COUNT];
108
109 /* Number of cores use this shared pagetable. */
110 gctUINT32 reference;
111}
112gcsSharedPageTable;
113
114static gcsSharedPageTable_PTR sharedPageTable = gcvNULL;
115#endif
116
117#if gcdMIRROR_PAGETABLE
118typedef struct _gcsMirrorPageTable * gcsMirrorPageTable_PTR;
119typedef struct _gcsMirrorPageTable
120{
121 /* gckMMU objects. */
122 gckMMU mmus[gcdMAX_GPU_COUNT];
123
124 /* Hardwares which use this shared pagetable. */
125 gckHARDWARE hardwares[gcdMAX_GPU_COUNT];
126
127 /* Number of cores use this shared pagetable. */
128 gctUINT32 reference;
129}
130gcsMirrorPageTable;
131
132static gcsMirrorPageTable_PTR mirrorPageTable = gcvNULL;
133static gctPOINTER mirrorPageTableMutex = gcvNULL;
134#endif
135
136typedef struct _gcsDynamicSpaceNode * gcsDynamicSpaceNode_PTR;
137typedef struct _gcsDynamicSpaceNode
138{
139 gctUINT32 start;
140 gctINT32 entries;
141}
142gcsDynamicSpaceNode;
143
144static void
145_WritePageEntry(
146 IN gctUINT32_PTR PageEntry,
147 IN gctUINT32 EntryValue
148 )
149{
150 static gctUINT16 data = 0xff00;
151
152 if (*(gctUINT8 *)&data == 0xff)
153 {
154 *PageEntry = gcmSWAB32(EntryValue);
155 }
156 else
157 {
158 *PageEntry = EntryValue;
159 }
160}
161
162static gctUINT32
163_ReadPageEntry(
164 IN gctUINT32_PTR PageEntry
165 )
166{
167 static gctUINT16 data = 0xff00;
168 gctUINT32 entryValue;
169
170 if (*(gctUINT8 *)&data == 0xff)
171 {
172 entryValue = *PageEntry;
173 return gcmSWAB32(entryValue);
174 }
175 else
176 {
177 return *PageEntry;
178 }
179}
180
181static gceSTATUS
182_FillPageTable(
183 IN gctUINT32_PTR PageTable,
184 IN gctUINT32 PageCount,
185 IN gctUINT32 EntryValue
186)
187{
188 gctUINT i;
189
190 for (i = 0; i < PageCount; i++)
191 {
192 _WritePageEntry(PageTable + i, EntryValue);
193 }
194
195 return gcvSTATUS_OK;
196}
197
198static gceSTATUS
199_Link(
200 IN gckMMU Mmu,
201 IN gctUINT32 Index,
202 IN gctUINT32 Next
203 )
204{
205 if (Index >= Mmu->pageTableEntries)
206 {
207 /* Just move heap pointer. */
208 Mmu->heapList = Next;
209 }
210 else
211 {
212 /* Address page table. */
213 gctUINT32_PTR map = Mmu->mapLogical;
214
215 /* Dispatch on node type. */
216 switch (gcmENTRY_TYPE(_ReadPageEntry(&map[Index])))
217 {
218 case gcvMMU_SINGLE:
219 /* Set single index. */
220 _WritePageEntry(&map[Index], (Next << 8) | gcvMMU_SINGLE);
221 break;
222
223 case gcvMMU_FREE:
224 /* Set index. */
225 _WritePageEntry(&map[Index + 1], Next);
226 break;
227
228 default:
229 gcmkFATAL("MMU table correcupted at index %u!", Index);
230 return gcvSTATUS_HEAP_CORRUPTED;
231 }
232 }
233
234 /* Success. */
235 return gcvSTATUS_OK;
236}
237
238static gceSTATUS
239_AddFree(
240 IN gckMMU Mmu,
241 IN gctUINT32 Index,
242 IN gctUINT32 Node,
243 IN gctUINT32 Count
244 )
245{
246 gctUINT32_PTR map = Mmu->mapLogical;
247
248 if (Count == 1)
249 {
250 /* Initialize a single page node. */
251 _WritePageEntry(map + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
252 }
253 else
254 {
255 /* Initialize the node. */
256 _WritePageEntry(map + Node + 0, (Count << 8) | gcvMMU_FREE);
257 _WritePageEntry(map + Node + 1, ~0U);
258 }
259
260 /* Append the node. */
261 return _Link(Mmu, Index, Node);
262}
263
264static gceSTATUS
265_Collect(
266 IN gckMMU Mmu
267 )
268{
269 gctUINT32_PTR map = Mmu->mapLogical;
270 gceSTATUS status;
271 gctUINT32 i, previous, start = 0, count = 0;
272
273 previous = Mmu->heapList = ~0U;
274 Mmu->freeNodes = gcvFALSE;
275
276 /* Walk the entire page table. */
277 for (i = 0; i < Mmu->pageTableEntries; ++i)
278 {
279 /* Dispatch based on type of page. */
280 switch (gcmENTRY_TYPE(_ReadPageEntry(&map[i])))
281 {
282 case gcvMMU_USED:
283 /* Used page, so close any open node. */
284 if (count > 0)
285 {
286 /* Add the node. */
287 gcmkONERROR(_AddFree(Mmu, previous, start, count));
288
289 /* Reset the node. */
290 previous = start;
291 count = 0;
292 }
293 break;
294
295 case gcvMMU_SINGLE:
296 /* Single free node. */
297 if (count++ == 0)
298 {
299 /* Start a new node. */
300 start = i;
301 }
302 break;
303
304 case gcvMMU_FREE:
305 /* A free node. */
306 if (count == 0)
307 {
308 /* Start a new node. */
309 start = i;
310 }
311
312 /* Advance the count. */
313 count += _ReadPageEntry(&map[i]) >> 8;
314
315 /* Advance the index into the page table. */
316 i += (_ReadPageEntry(&map[i]) >> 8) - 1;
317 break;
318
319 default:
320 gcmkFATAL("MMU page table correcupted at index %u!", i);
321 return gcvSTATUS_HEAP_CORRUPTED;
322 }
323 }
324
325 /* See if we have an open node left. */
326 if (count > 0)
327 {
328 /* Add the node to the list. */
329 gcmkONERROR(_AddFree(Mmu, previous, start, count));
330 }
331
332 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_MMU,
333 "Performed a garbage collection of the MMU heap.");
334
335 /* Success. */
336 return gcvSTATUS_OK;
337
338OnError:
339 /* Return the staus. */
340 return status;
341}
342
343static gctUINT32
344_SetPage(gctUINT32 PageAddress, gctUINT32 PageAddressExt)
345{
346 return PageAddress
347 /* AddressExt */
348 | (PageAddressExt << 4)
349 /* writable */
350 | (1 << 2)
351 /* Ignore exception */
352 | (0 << 1)
353 /* Present */
354 | (1 << 0);
355}
356
357#if gcdPROCESS_ADDRESS_SPACE
358gctUINT32
359_AddressToIndex(
360 IN gckMMU Mmu,
361 IN gctUINT32 Address
362 )
363{
364 gctUINT32 mtlbOffset = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
365 gctUINT32 stlbOffset = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
366
367 return (mtlbOffset - Mmu->dynamicMappingStart) * gcdMMU_STLB_4K_ENTRY_NUM + stlbOffset;
368}
369
370gctUINT32
371_MtlbOffset(
372 gctUINT32 Address
373 )
374{
375 return (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
376}
377
378gctUINT32
379_StlbOffset(
380 gctUINT32 Address
381 )
382{
383 return (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
384}
385
386static gceSTATUS
387_AllocateStlb(
388 IN gckOS Os,
389 OUT gcsMMU_STLB_PTR *Stlb
390 )
391{
392 gceSTATUS status;
393 gcsMMU_STLB_PTR stlb;
394 gctPOINTER pointer;
395
396 /* Allocate slave TLB record. */
397 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsMMU_STLB), &pointer));
398 stlb = pointer;
399
400 stlb->size = gcdMMU_STLB_4K_SIZE;
401
402 /* Allocate slave TLB entries. */
403 gcmkONERROR(gckOS_AllocateContiguous(
404 Os,
405 gcvFALSE,
406 &stlb->size,
407 &stlb->physical,
408 (gctPOINTER)&stlb->logical
409 ));
410
411 gcmkONERROR(gckOS_GetPhysicalAddress(Os, stlb->logical, &stlb->physBase));
412
413#if gcdUSE_MMU_EXCEPTION
414 _FillPageTable(stlb->logical, stlb->size / 4, gcdMMU_STLB_EXCEPTION);
415#else
416 gckOS_ZeroMemory(stlb->logical, stlb->size);
417#endif
418
419 *Stlb = stlb;
420
421 return gcvSTATUS_OK;
422
423OnError:
424 return status;
425}
426
427gceSTATUS
428_SetupProcessAddressSpace(
429 IN gckMMU Mmu
430 )
431{
432 gceSTATUS status;
433 gctINT numEntries = 0;
434 gctUINT32_PTR map;
435
436 numEntries = gcdPROCESS_ADDRESS_SPACE_SIZE
437 /* Address space mapped by one MTLB entry. */
438 / (1 << gcdMMU_MTLB_SHIFT);
439
440 Mmu->dynamicMappingStart = 0;
441
442 Mmu->pageTableSize = numEntries * 4096;
443
444 Mmu->pageTableEntries = Mmu->pageTableSize / gcmSIZEOF(gctUINT32);
445
446 gcmkONERROR(gckOS_Allocate(Mmu->os,
447 Mmu->pageTableSize,
448 (void **)&Mmu->mapLogical));
449
450 /* Initilization. */
451 map = Mmu->mapLogical;
452 _WritePageEntry(map, (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
453 _WritePageEntry(map + 1, ~0U);
454 Mmu->heapList = 0;
455 Mmu->freeNodes = gcvFALSE;
456
457 return gcvSTATUS_OK;
458
459OnError:
460 return status;
461}
462#else
463static gceSTATUS
464_FillFlatMapping(
465 IN gckMMU Mmu,
466 IN gctUINT32 PhysBase,
467 OUT gctSIZE_T Size
468 )
469{
470 gceSTATUS status;
471 gctBOOL mutex = gcvFALSE;
472 gcsMMU_STLB_PTR head = gcvNULL, pre = gcvNULL;
473 gctUINT32 start = PhysBase & (~gcdMMU_PAGE_64K_MASK);
474 gctUINT32 end = (PhysBase + Size - 1) & (~gcdMMU_PAGE_64K_MASK);
475 gctUINT32 mStart = start >> gcdMMU_MTLB_SHIFT;
476 gctUINT32 mEnd = end >> gcdMMU_MTLB_SHIFT;
477 gctUINT32 sStart = (start & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
478 gctUINT32 sEnd = (end & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
479 gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
480 gctPHYS_ADDR_T physical;
481
482 /* Grab the mutex. */
483 gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
484 mutex = gcvTRUE;
485
486 while (mStart <= mEnd)
487 {
488 gcmkASSERT(mStart < gcdMMU_MTLB_ENTRY_NUM);
489 if (*(Mmu->mtlbLogical + mStart) == 0)
490 {
491 gcsMMU_STLB_PTR stlb;
492 gctPOINTER pointer = gcvNULL;
493 gctUINT32 last = (mStart == mEnd) ? sEnd : (gcdMMU_STLB_64K_ENTRY_NUM - 1);
494 gctUINT32 mtlbEntry;
495
496 gcmkONERROR(gckOS_Allocate(Mmu->os, sizeof(struct _gcsMMU_STLB), &pointer));
497 stlb = pointer;
498
499 stlb->mtlbEntryNum = 0;
500 stlb->next = gcvNULL;
501 stlb->physical = gcvNULL;
502 stlb->logical = gcvNULL;
503 stlb->size = gcdMMU_STLB_64K_SIZE;
504 stlb->pageCount = 0;
505
506 if (pre == gcvNULL)
507 {
508 pre = head = stlb;
509 }
510 else
511 {
512 gcmkASSERT(pre->next == gcvNULL);
513 pre->next = stlb;
514 pre = stlb;
515 }
516
517 gcmkONERROR(
518 gckOS_AllocateContiguous(Mmu->os,
519 gcvFALSE,
520 &stlb->size,
521 &stlb->physical,
522 (gctPOINTER)&stlb->logical));
523
524 gcmkONERROR(gckOS_ZeroMemory(stlb->logical, stlb->size));
525
526 gcmkONERROR(gckOS_GetPhysicalAddress(
527 Mmu->os,
528 stlb->logical,
529 &physical));
530
531 gcmkSAFECASTPHYSADDRT(stlb->physBase, physical);
532
533 if (stlb->physBase & (gcdMMU_STLB_64K_SIZE - 1))
534 {
535 gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
536 }
537
538 mtlbEntry = stlb->physBase
539 /* 64KB page size */
540 | (1 << 2)
541 /* Ignore exception */
542 | (0 << 1)
543 /* Present */
544 | (1 << 0);
545
546 if (ace)
547 {
548 mtlbEntry = mtlbEntry
549 /* Secure */
550 | (1 << 4);
551 }
552
553 _WritePageEntry(Mmu->mtlbLogical + mStart, mtlbEntry);
554
555#if gcdMMU_TABLE_DUMP
556 gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
557 __FUNCTION__, __LINE__,
558 mStart,
559 _ReadPageEntry(Mmu->mtlbLogical + mStart));
560#endif
561
562 stlb->mtlbIndex = mStart;
563 stlb->mtlbEntryNum = 1;
564#if gcdMMU_TABLE_DUMP
565 gckOS_Print("%s(%d): STLB: logical:%08x -> physical:%08x\n",
566 __FUNCTION__, __LINE__,
567 stlb->logical,
568 stlb->physBase);
569#endif
570
571 while (sStart <= last)
572 {
573 gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
574 _WritePageEntry(stlb->logical + sStart, _SetPage(start, 0));
575#if gcdMMU_TABLE_DUMP
576 gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
577 __FUNCTION__, __LINE__,
578 sStart,
579 _ReadPageEntry(stlb->logical + sStart));
580#endif
581 /* next page. */
582 start += gcdMMU_PAGE_64K_SIZE;
583 sStart++;
584 stlb->pageCount++;
585 }
586
587 sStart = 0;
588 ++mStart;
589 }
590 else
591 {
592 gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
593 }
594 }
595
596 /* Insert the stlb into staticSTLB. */
597 if (Mmu->staticSTLB == gcvNULL)
598 {
599 Mmu->staticSTLB = head;
600 }
601 else
602 {
603 gcmkASSERT(pre == gcvNULL);
604 gcmkASSERT(pre->next == gcvNULL);
605 pre->next = Mmu->staticSTLB;
606 Mmu->staticSTLB = head;
607 }
608
609 /* Release the mutex. */
610 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
611
612 return gcvSTATUS_OK;
613
614OnError:
615
616 /* Roll back. */
617 while (head != gcvNULL)
618 {
619 pre = head;
620 head = head->next;
621
622 if (pre->physical != gcvNULL)
623 {
624 gcmkVERIFY_OK(
625 gckOS_FreeContiguous(Mmu->os,
626 pre->physical,
627 pre->logical,
628 pre->size));
629 }
630
631 if (pre->mtlbEntryNum != 0)
632 {
633 gcmkASSERT(pre->mtlbEntryNum == 1);
634 _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
635 }
636
637 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
638 }
639
640 if (mutex)
641 {
642 /* Release the mutex. */
643 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
644 }
645
646 return status;
647}
648
649static gceSTATUS
650_FindDynamicSpace(
651 IN gckMMU Mmu,
652 OUT gcsDynamicSpaceNode_PTR *Array,
653 OUT gctINT * Size
654 )
655{
656 gceSTATUS status = gcvSTATUS_OK;
657 gctPOINTER pointer = gcvNULL;
658 gcsDynamicSpaceNode_PTR array = gcvNULL;
659 gctINT size = 0;
660 gctINT i = 0, nodeStart = -1, nodeEntries = 0;
661
662 /* Allocate memory for the array. */
663 gcmkONERROR(gckOS_Allocate(Mmu->os,
664 gcmSIZEOF(*array) * (gcdMMU_MTLB_ENTRY_NUM / 2),
665 &pointer));
666
667 array = (gcsDynamicSpaceNode_PTR)pointer;
668
669 /* Loop all the entries. */
670 while (i < gcdMMU_MTLB_ENTRY_NUM)
671 {
672 if (!Mmu->mtlbLogical[i])
673 {
674 if (nodeStart < 0)
675 {
676 /* This is the first entry of the dynamic space. */
677 nodeStart = i;
678 nodeEntries = 1;
679 }
680 else
681 {
682 /* Other entries of the dynamic space. */
683 nodeEntries++;
684 }
685 }
686 else if (nodeStart >= 0)
687 {
688 /* Save the previous node. */
689 array[size].start = nodeStart;
690 array[size].entries = nodeEntries;
691 size++;
692
693 /* Reset the start. */
694 nodeStart = -1;
695 nodeEntries = 0;
696 }
697
698 i++;
699 }
700
701 /* Save the previous node. */
702 if (nodeStart >= 0)
703 {
704 array[size].start = nodeStart;
705 array[size].entries = nodeEntries;
706 size++;
707 }
708
709#if gcdMMU_TABLE_DUMP
710 for (i = 0; i < size; i++)
711 {
712 gckOS_Print("%s(%d): [%d]: start=%d, entries=%d.\n",
713 __FUNCTION__, __LINE__,
714 i,
715 array[i].start,
716 array[i].entries);
717 }
718#endif
719
720 *Array = array;
721 *Size = size;
722
723 return gcvSTATUS_OK;
724
725OnError:
726 if (pointer != gcvNULL)
727 {
728 gckOS_Free(Mmu->os, pointer);
729 }
730
731 return status;
732}
733
734static gceSTATUS
735_SetupDynamicSpace(
736 IN gckMMU Mmu
737 )
738{
739 gceSTATUS status;
740 gcsDynamicSpaceNode_PTR nodeArray = gcvNULL;
741 gctINT i, nodeArraySize = 0;
742 gctPHYS_ADDR_T physical;
743 gctUINT32 address;
744 gctINT numEntries = 0;
745 gctUINT32_PTR map;
746 gctBOOL acquired = gcvFALSE;
747 gctUINT32 mtlbEntry;
748 gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
749
750 /* Find all the dynamic address space. */
751 gcmkONERROR(_FindDynamicSpace(Mmu, &nodeArray, &nodeArraySize));
752
753 /* TODO: We only use the largest one for now. */
754 for (i = 0; i < nodeArraySize; i++)
755 {
756 if (nodeArray[i].entries > numEntries)
757 {
758 Mmu->dynamicMappingStart = nodeArray[i].start;
759 numEntries = nodeArray[i].entries;
760 }
761 }
762
763 gckOS_Free(Mmu->os, (gctPOINTER)nodeArray);
764
765 Mmu->pageTableSize = numEntries * 4096;
766
767 gcmkSAFECASTSIZET(Mmu->pageTableEntries, Mmu->pageTableSize / gcmSIZEOF(gctUINT32));
768
769 gcmkONERROR(gckOS_Allocate(Mmu->os,
770 Mmu->pageTableSize,
771 (void **)&Mmu->mapLogical));
772
773 /* Construct Slave TLB. */
774 gcmkONERROR(gckOS_AllocateContiguous(Mmu->os,
775 gcvFALSE,
776 &Mmu->pageTableSize,
777 &Mmu->pageTablePhysical,
778 (gctPOINTER)&Mmu->pageTableLogical));
779
780#if gcdUSE_MMU_EXCEPTION
781 gcmkONERROR(_FillPageTable(Mmu->pageTableLogical,
782 Mmu->pageTableEntries,
783 /* Enable exception */
784 1 << 1));
785#else
786 /* Invalidate all entries. */
787 gcmkONERROR(gckOS_ZeroMemory(Mmu->pageTableLogical,
788 Mmu->pageTableSize));
789#endif
790
791 /* Initilization. */
792 map = Mmu->mapLogical;
793 _WritePageEntry(map, (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
794 _WritePageEntry(map + 1, ~0U);
795 Mmu->heapList = 0;
796 Mmu->freeNodes = gcvFALSE;
797
798 gcmkONERROR(gckOS_GetPhysicalAddress(Mmu->os,
799 Mmu->pageTableLogical,
800 &physical));
801
802 gcmkSAFECASTPHYSADDRT(address, physical);
803
804 /* Grab the mutex. */
805 gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
806 acquired = gcvTRUE;
807
808 /* Map to Master TLB. */
809 for (i = (gctINT)Mmu->dynamicMappingStart;
810 i < (gctINT)Mmu->dynamicMappingStart + numEntries;
811 i++)
812 {
813 mtlbEntry = address
814 /* 4KB page size */
815 | (0 << 2)
816 /* Ignore exception */
817 | (0 << 1)
818 /* Present */
819 | (1 << 0);
820
821 if (ace)
822 {
823 mtlbEntry = mtlbEntry
824 /* Secure */
825 | (1 << 4);
826 }
827
828 _WritePageEntry(Mmu->mtlbLogical + i, mtlbEntry);
829
830#if gcdMMU_TABLE_DUMP
831 gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
832 __FUNCTION__, __LINE__,
833 i,
834 _ReadPageEntry(Mmu->mtlbLogical + i));
835#endif
836 address += gcdMMU_STLB_4K_SIZE;
837 }
838
839 /* Release the mutex. */
840 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
841
842 return gcvSTATUS_OK;
843
844OnError:
845 if (Mmu->mapLogical)
846 {
847 gcmkVERIFY_OK(
848 gckOS_Free(Mmu->os, (gctPOINTER) Mmu->mapLogical));
849
850
851 gcmkVERIFY_OK(
852 gckOS_FreeContiguous(Mmu->os,
853 Mmu->pageTablePhysical,
854 (gctPOINTER) Mmu->pageTableLogical,
855 Mmu->pageTableSize));
856 }
857
858 if (acquired)
859 {
860 /* Release the mutex. */
861 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
862 }
863
864 return status;
865}
866#endif
867
868/*******************************************************************************
869**
870** _Construct
871**
872** Construct a new gckMMU object.
873**
874** INPUT:
875**
876** gckKERNEL Kernel
877** Pointer to an gckKERNEL object.
878**
879** gctSIZE_T MmuSize
880** Number of bytes for the page table.
881**
882** OUTPUT:
883**
884** gckMMU * Mmu
885** Pointer to a variable that receives the gckMMU object pointer.
886*/
887gceSTATUS
888_Construct(
889 IN gckKERNEL Kernel,
890 IN gctSIZE_T MmuSize,
891 OUT gckMMU * Mmu
892 )
893{
894 gckOS os;
895 gckHARDWARE hardware;
896 gceSTATUS status;
897 gckMMU mmu = gcvNULL;
898 gctUINT32_PTR map;
899 gctPOINTER pointer = gcvNULL;
900#if gcdPROCESS_ADDRESS_SPACE
901 gctUINT32 i;
902 gctUINT32 physical;
903#endif
904 gctUINT32 physBase;
905 gctUINT32 physSize;
906 gctUINT32 gpuAddress;
907 gctPHYS_ADDR_T gpuPhysical;
908
909 gcmkHEADER_ARG("Kernel=0x%x MmuSize=%lu", Kernel, MmuSize);
910
911 /* Verify the arguments. */
912 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
913 gcmkVERIFY_ARGUMENT(MmuSize > 0);
914 gcmkVERIFY_ARGUMENT(Mmu != gcvNULL);
915
916 /* Extract the gckOS object pointer. */
917 os = Kernel->os;
918 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
919
920 /* Extract the gckHARDWARE object pointer. */
921 hardware = Kernel->hardware;
922 gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
923
924 /* Allocate memory for the gckMMU object. */
925 gcmkONERROR(gckOS_Allocate(os, sizeof(struct _gckMMU), &pointer));
926
927 mmu = pointer;
928
929 /* Initialize the gckMMU object. */
930 mmu->object.type = gcvOBJ_MMU;
931 mmu->os = os;
932 mmu->hardware = hardware;
933 mmu->pageTableMutex = gcvNULL;
934 mmu->pageTableLogical = gcvNULL;
935 mmu->mtlbLogical = gcvNULL;
936 mmu->staticSTLB = gcvNULL;
937 mmu->enabled = gcvFALSE;
938 mmu->mapLogical = gcvNULL;
939
940 /* Create the page table mutex. */
941 gcmkONERROR(gckOS_CreateMutex(os, &mmu->pageTableMutex));
942
943 if (hardware->mmuVersion == 0)
944 {
945 mmu->pageTableSize = MmuSize;
946
947 /* Construct address space management table. */
948 gcmkONERROR(gckOS_Allocate(mmu->os,
949 mmu->pageTableSize,
950 &pointer));
951
952 mmu->mapLogical = pointer;
953
954 /* Construct page table read by GPU. */
955 gcmkONERROR(gckOS_AllocateContiguous(mmu->os,
956 gcvFALSE,
957 &mmu->pageTableSize,
958 &mmu->pageTablePhysical,
959 (gctPOINTER)&mmu->pageTableLogical));
960
961
962 /* Compute number of entries in page table. */
963 gcmkSAFECASTSIZET(mmu->pageTableEntries, mmu->pageTableSize / sizeof(gctUINT32));
964
965 /* Mark all pages as free. */
966 map = mmu->mapLogical;
967
968#if gcdMMU_CLEAR_VALUE
969 _FillPageTable(mmu->pageTableLogical, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
970#endif
971
972 _WritePageEntry(map, (mmu->pageTableEntries << 8) | gcvMMU_FREE);
973 _WritePageEntry(map + 1, ~0U);
974 mmu->heapList = 0;
975 mmu->freeNodes = gcvFALSE;
976 }
977 else
978 {
979 /* Allocate the 4K mode MTLB table. */
980 mmu->mtlbSize = gcdMMU_MTLB_SIZE + 64;
981
982 gcmkONERROR(
983 gckOS_AllocateContiguous(os,
984 gcvFALSE,
985 &mmu->mtlbSize,
986 &mmu->mtlbPhysical,
987 &pointer));
988
989 mmu->mtlbLogical = pointer;
990
991#if gcdPROCESS_ADDRESS_SPACE
992 _FillPageTable(pointer, mmu->mtlbSize / 4, gcdMMU_MTLB_EXCEPTION);
993
994 /* Allocate a array to store stlbs. */
995 gcmkONERROR(gckOS_Allocate(os, mmu->mtlbSize, &mmu->stlbs));
996
997 gckOS_ZeroMemory(mmu->stlbs, mmu->mtlbSize);
998
999 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1000 {
1001 gcmkONERROR(gckOS_AtomConstruct(os, &mmu->pageTableDirty[i]));
1002 }
1003
1004 _SetupProcessAddressSpace(mmu);
1005
1006 /* Map kernel command buffer in MMU. */
1007 for (i = 0; i < gcdCOMMAND_QUEUES; i++)
1008 {
1009 gcmkONERROR(gckOS_GetPhysicalAddress(
1010 mmu->os,
1011 Kernel->command->queues[i].logical,
1012 &physical
1013 ));
1014
1015 gcmkONERROR(gckMMU_FlatMapping(mmu, physical));
1016 }
1017#else
1018 /* Invalid all the entries. */
1019 gcmkONERROR(
1020 gckOS_ZeroMemory(pointer, mmu->mtlbSize));
1021
1022 gcmkONERROR(
1023 gckOS_QueryOption(mmu->os, "physBase", &physBase));
1024
1025 gcmkONERROR(
1026 gckOS_QueryOption(mmu->os, "physSize", &physSize));
1027
1028 gcmkONERROR(
1029 gckOS_CPUPhysicalToGPUPhysical(mmu->os, physBase, &gpuPhysical));
1030
1031 gcmkSAFECASTPHYSADDRT(gpuAddress, gpuPhysical);
1032
1033 /* Setup [physBase - physSize) flat mapping. */
1034 gcmkONERROR(_FillFlatMapping(
1035 mmu,
1036 gpuAddress,
1037 physSize
1038 ));
1039
1040 gcmkONERROR(_SetupDynamicSpace(mmu));
1041#endif
1042 }
1043
1044 /* Return the gckMMU object pointer. */
1045 *Mmu = mmu;
1046
1047 /* Success. */
1048 gcmkFOOTER_ARG("*Mmu=0x%x", *Mmu);
1049 return gcvSTATUS_OK;
1050
1051OnError:
1052 /* Roll back. */
1053 if (mmu != gcvNULL)
1054 {
1055 if (mmu->mapLogical != gcvNULL)
1056 {
1057 gcmkVERIFY_OK(
1058 gckOS_Free(os, (gctPOINTER) mmu->mapLogical));
1059
1060
1061 gcmkVERIFY_OK(
1062 gckOS_FreeContiguous(os,
1063 mmu->pageTablePhysical,
1064 (gctPOINTER) mmu->pageTableLogical,
1065 mmu->pageTableSize));
1066 }
1067
1068 if (mmu->mtlbLogical != gcvNULL)
1069 {
1070 gcmkVERIFY_OK(
1071 gckOS_FreeContiguous(os,
1072 mmu->mtlbPhysical,
1073 (gctPOINTER) mmu->mtlbLogical,
1074 mmu->mtlbSize));
1075 }
1076
1077 if (mmu->pageTableMutex != gcvNULL)
1078 {
1079 /* Delete the mutex. */
1080 gcmkVERIFY_OK(
1081 gckOS_DeleteMutex(os, mmu->pageTableMutex));
1082 }
1083
1084 /* Mark the gckMMU object as unknown. */
1085 mmu->object.type = gcvOBJ_UNKNOWN;
1086
1087 /* Free the allocates memory. */
1088 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, mmu));
1089 }
1090
1091 /* Return the status. */
1092 gcmkFOOTER();
1093 return status;
1094}
1095
1096/*******************************************************************************
1097**
1098** _Destroy
1099**
1100** Destroy a gckMMU object.
1101**
1102** INPUT:
1103**
1104** gckMMU Mmu
1105** Pointer to an gckMMU object.
1106**
1107** OUTPUT:
1108**
1109** Nothing.
1110*/
1111gceSTATUS
1112_Destroy(
1113 IN gckMMU Mmu
1114 )
1115{
1116#if gcdPROCESS_ADDRESS_SPACE
1117 gctUINT32 i;
1118#endif
1119 gcmkHEADER_ARG("Mmu=0x%x", Mmu);
1120
1121 /* Verify the arguments. */
1122 gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
1123
1124 while (Mmu->staticSTLB != gcvNULL)
1125 {
1126 gcsMMU_STLB_PTR pre = Mmu->staticSTLB;
1127 Mmu->staticSTLB = pre->next;
1128
1129 if (pre->physical != gcvNULL)
1130 {
1131 gcmkVERIFY_OK(
1132 gckOS_FreeContiguous(Mmu->os,
1133 pre->physical,
1134 pre->logical,
1135 pre->size));
1136 }
1137
1138 if (pre->mtlbEntryNum != 0)
1139 {
1140 gcmkASSERT(pre->mtlbEntryNum == 1);
1141 _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
1142#if gcdMMU_TABLE_DUMP
1143 gckOS_Print("%s(%d): clean MTLB[%d]\n",
1144 __FUNCTION__, __LINE__,
1145 pre->mtlbIndex);
1146#endif
1147 }
1148
1149 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
1150 }
1151
1152 if (Mmu->hardware->mmuVersion != 0)
1153 {
1154 gcmkVERIFY_OK(
1155 gckOS_FreeContiguous(Mmu->os,
1156 Mmu->mtlbPhysical,
1157 (gctPOINTER) Mmu->mtlbLogical,
1158 Mmu->mtlbSize));
1159 }
1160
1161 /* Free address space management table. */
1162 if (Mmu->mapLogical != gcvNULL)
1163 {
1164 gcmkVERIFY_OK(
1165 gckOS_Free(Mmu->os, (gctPOINTER) Mmu->mapLogical));
1166 }
1167
1168 if (Mmu->pageTableLogical != gcvNULL)
1169 {
1170 /* Free page table. */
1171 gcmkVERIFY_OK(
1172 gckOS_FreeContiguous(Mmu->os,
1173 Mmu->pageTablePhysical,
1174 (gctPOINTER) Mmu->pageTableLogical,
1175 Mmu->pageTableSize));
1176 }
1177
1178 /* Delete the page table mutex. */
1179 gcmkVERIFY_OK(gckOS_DeleteMutex(Mmu->os, Mmu->pageTableMutex));
1180
1181#if gcdPROCESS_ADDRESS_SPACE
1182 for (i = 0; i < Mmu->mtlbSize / 4; i++)
1183 {
1184 struct _gcsMMU_STLB *stlb = ((struct _gcsMMU_STLB **)Mmu->stlbs)[i];
1185
1186 if (stlb)
1187 {
1188 gcmkVERIFY_OK(gckOS_FreeContiguous(
1189 Mmu->os,
1190 stlb->physical,
1191 stlb->logical,
1192 stlb->size));
1193
1194 gcmkOS_SAFE_FREE(Mmu->os, stlb);
1195 }
1196 }
1197
1198 gcmkOS_SAFE_FREE(Mmu->os, Mmu->stlbs);
1199#endif
1200
1201 /* Mark the gckMMU object as unknown. */
1202 Mmu->object.type = gcvOBJ_UNKNOWN;
1203
1204 /* Free the gckMMU object. */
1205 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, Mmu));
1206
1207 /* Success. */
1208 gcmkFOOTER_NO();
1209 return gcvSTATUS_OK;
1210}
1211
1212/*******************************************************************************
1213** _AdjstIndex
1214**
1215** Adjust the index from which we search for a usable node to make sure
1216** index allocated is greater than Start.
1217*/
1218gceSTATUS
1219_AdjustIndex(
1220 IN gckMMU Mmu,
1221 IN gctUINT32 Index,
1222 IN gctUINT32 PageCount,
1223 IN gctUINT32 Start,
1224 OUT gctUINT32 * IndexAdjusted
1225 )
1226{
1227 gceSTATUS status;
1228 gctUINT32 index = Index;
1229 gctUINT32_PTR map = Mmu->mapLogical;
1230
1231 gcmkHEADER();
1232
1233 for (; index < Mmu->pageTableEntries;)
1234 {
1235 gctUINT32 result = 0;
1236 gctUINT32 nodeSize = 0;
1237
1238 if (index >= Start)
1239 {
1240 break;
1241 }
1242
1243 switch (gcmENTRY_TYPE(map[index]))
1244 {
1245 case gcvMMU_SINGLE:
1246 nodeSize = 1;
1247 break;
1248
1249 case gcvMMU_FREE:
1250 nodeSize = map[index] >> 8;
1251 break;
1252
1253 default:
1254 gcmkFATAL("MMU table correcupted at index %u!", index);
1255 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1256 }
1257
1258 if (nodeSize > PageCount)
1259 {
1260 result = index + (nodeSize - PageCount);
1261
1262 if (result >= Start)
1263 {
1264 break;
1265 }
1266 }
1267
1268 switch (gcmENTRY_TYPE(map[index]))
1269 {
1270 case gcvMMU_SINGLE:
1271 index = map[index] >> 8;
1272 break;
1273
1274 case gcvMMU_FREE:
1275 index = map[index + 1];
1276 break;
1277
1278 default:
1279 gcmkFATAL("MMU table correcupted at index %u!", index);
1280 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1281 }
1282 }
1283
1284 *IndexAdjusted = index;
1285
1286 gcmkFOOTER_NO();
1287 return gcvSTATUS_OK;
1288
1289OnError:
1290 gcmkFOOTER();
1291 return status;
1292}
1293
1294gceSTATUS
1295gckMMU_Construct(
1296 IN gckKERNEL Kernel,
1297 IN gctSIZE_T MmuSize,
1298 OUT gckMMU * Mmu
1299 )
1300{
1301#if gcdSHARED_PAGETABLE
1302 gceSTATUS status;
1303 gctPOINTER pointer;
1304
1305 gcmkHEADER_ARG("Kernel=0x%08x", Kernel);
1306
1307 if (sharedPageTable == gcvNULL)
1308 {
1309 gcmkONERROR(
1310 gckOS_Allocate(Kernel->os,
1311 sizeof(struct _gcsSharedPageTable),
1312 &pointer));
1313 sharedPageTable = pointer;
1314
1315 gcmkONERROR(
1316 gckOS_ZeroMemory(sharedPageTable,
1317 sizeof(struct _gcsSharedPageTable)));
1318
1319 gcmkONERROR(_Construct(Kernel, MmuSize, &sharedPageTable->mmu));
1320 }
1321
1322 *Mmu = sharedPageTable->mmu;
1323
1324 sharedPageTable->hardwares[sharedPageTable->reference] = Kernel->hardware;
1325
1326 sharedPageTable->reference++;
1327
1328 gcmkFOOTER_ARG("sharedPageTable->reference=%lu", sharedPageTable->reference);
1329 return gcvSTATUS_OK;
1330
1331OnError:
1332 if (sharedPageTable)
1333 {
1334 if (sharedPageTable->mmu)
1335 {
1336 gcmkVERIFY_OK(gckMMU_Destroy(sharedPageTable->mmu));
1337 }
1338
1339 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, sharedPageTable));
1340 }
1341
1342 gcmkFOOTER();
1343 return status;
1344#elif gcdMIRROR_PAGETABLE
1345 gceSTATUS status;
1346 gctPOINTER pointer;
1347
1348 gcmkHEADER_ARG("Kernel=0x%08x", Kernel);
1349
1350 if (mirrorPageTable == gcvNULL)
1351 {
1352 gcmkONERROR(
1353 gckOS_Allocate(Kernel->os,
1354 sizeof(struct _gcsMirrorPageTable),
1355 &pointer));
1356 mirrorPageTable = pointer;
1357
1358 gcmkONERROR(
1359 gckOS_ZeroMemory(mirrorPageTable,
1360 sizeof(struct _gcsMirrorPageTable)));
1361
1362 gcmkONERROR(
1363 gckOS_CreateMutex(Kernel->os, &mirrorPageTableMutex));
1364 }
1365
1366 gcmkONERROR(_Construct(Kernel, MmuSize, Mmu));
1367
1368 mirrorPageTable->mmus[mirrorPageTable->reference] = *Mmu;
1369
1370 mirrorPageTable->hardwares[mirrorPageTable->reference] = Kernel->hardware;
1371
1372 mirrorPageTable->reference++;
1373
1374 gcmkFOOTER_ARG("mirrorPageTable->reference=%lu", mirrorPageTable->reference);
1375 return gcvSTATUS_OK;
1376
1377OnError:
1378 if (mirrorPageTable && mirrorPageTable->reference == 0)
1379 {
1380 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, mirrorPageTable));
1381 }
1382
1383 gcmkFOOTER();
1384 return status;
1385#else
1386 return _Construct(Kernel, MmuSize, Mmu);
1387#endif
1388}
1389
1390gceSTATUS
1391gckMMU_Destroy(
1392 IN gckMMU Mmu
1393 )
1394{
1395#if gcdSHARED_PAGETABLE
1396 gckOS os = Mmu->os;
1397
1398 sharedPageTable->reference--;
1399
1400 if (sharedPageTable->reference == 0)
1401 {
1402 if (sharedPageTable->mmu)
1403 {
1404 gcmkVERIFY_OK(_Destroy(Mmu));
1405 }
1406
1407 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, sharedPageTable));
1408 }
1409
1410 return gcvSTATUS_OK;
1411#elif gcdMIRROR_PAGETABLE
1412 mirrorPageTable->reference--;
1413
1414 if (mirrorPageTable->reference == 0)
1415 {
1416 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, mirrorPageTable));
1417 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, mirrorPageTableMutex));
1418 }
1419
1420 return _Destroy(Mmu);
1421#else
1422 return _Destroy(Mmu);
1423#endif
1424}
1425
1426/*******************************************************************************
1427**
1428** gckMMU_AllocatePages
1429**
1430** Allocate pages inside the page table.
1431**
1432** INPUT:
1433**
1434** gckMMU Mmu
1435** Pointer to an gckMMU object.
1436**
1437** gctSIZE_T PageCount
1438** Number of pages to allocate.
1439**
1440** OUTPUT:
1441**
1442** gctPOINTER * PageTable
1443** Pointer to a variable that receives the base address of the page
1444** table.
1445**
1446** gctUINT32 * Address
1447** Pointer to a variable that receives the hardware specific address.
1448*/
1449gceSTATUS
1450_AllocatePages(
1451 IN gckMMU Mmu,
1452 IN gctSIZE_T PageCount,
1453 IN gceSURF_TYPE Type,
1454 OUT gctPOINTER * PageTable,
1455 OUT gctUINT32 * Address
1456 )
1457{
1458 gceSTATUS status;
1459 gctBOOL mutex = gcvFALSE;
1460 gctUINT32 index = 0, previous = ~0U, left;
1461 gctUINT32_PTR map;
1462 gctBOOL gotIt;
1463 gctUINT32 address;
1464 gctUINT32 pageCount;
1465
1466 gcmkHEADER_ARG("Mmu=0x%x PageCount=%lu", Mmu, PageCount);
1467
1468 /* Verify the arguments. */
1469 gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
1470 gcmkVERIFY_ARGUMENT(PageCount > 0);
1471 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
1472
1473 if (PageCount > Mmu->pageTableEntries)
1474 {
1475 /* Not enough pages avaiable. */
1476 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1477 }
1478
1479 gcmkSAFECASTSIZET(pageCount, PageCount);
1480
1481 /* Grab the mutex. */
1482 gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
1483 mutex = gcvTRUE;
1484
1485 /* Cast pointer to page table. */
1486 for (map = Mmu->mapLogical, gotIt = gcvFALSE; !gotIt;)
1487 {
1488 index = Mmu->heapList;
1489
1490 if ((Mmu->hardware->mmuVersion == 0) && (Type == gcvSURF_VERTEX))
1491 {
1492 gcmkONERROR(_AdjustIndex(
1493 Mmu,
1494 index,
1495 pageCount,
1496 gcdVERTEX_START / gcmSIZEOF(gctUINT32),
1497 &index
1498 ));
1499 }
1500
1501 /* Walk the heap list. */
1502 for (; !gotIt && (index < Mmu->pageTableEntries);)
1503 {
1504 /* Check the node type. */
1505 switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
1506 {
1507 case gcvMMU_SINGLE:
1508 /* Single odes are valid if we only need 1 page. */
1509 if (pageCount == 1)
1510 {
1511 gotIt = gcvTRUE;
1512 }
1513 else
1514 {
1515 /* Move to next node. */
1516 previous = index;
1517 index = _ReadPageEntry(&map[index]) >> 8;
1518 }
1519 break;
1520
1521 case gcvMMU_FREE:
1522 /* Test if the node has enough space. */
1523 if (pageCount <= (_ReadPageEntry(&map[index]) >> 8))
1524 {
1525 gotIt = gcvTRUE;
1526 }
1527 else
1528 {
1529 /* Move to next node. */
1530 previous = index;
1531 index = _ReadPageEntry(&map[index + 1]);
1532 }
1533 break;
1534
1535 default:
1536 gcmkFATAL("MMU table correcupted at index %u!", index);
1537 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1538 }
1539 }
1540
1541 /* Test if we are out of memory. */
1542 if (index >= Mmu->pageTableEntries)
1543 {
1544 if (Mmu->freeNodes)
1545 {
1546 /* Time to move out the trash! */
1547 gcmkONERROR(_Collect(Mmu));
1548
1549 /* We are going to search from start, so reset previous to start. */
1550 previous = ~0U;
1551 }
1552 else
1553 {
1554 /* Out of resources. */
1555 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1556 }
1557 }
1558 }
1559
1560 switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
1561 {
1562 case gcvMMU_SINGLE:
1563 /* Unlink single node from free list. */
1564 gcmkONERROR(
1565 _Link(Mmu, previous, _ReadPageEntry(&map[index]) >> 8));
1566 break;
1567
1568 case gcvMMU_FREE:
1569 /* Check how many pages will be left. */
1570 left = (_ReadPageEntry(&map[index]) >> 8) - pageCount;
1571 switch (left)
1572 {
1573 case 0:
1574 /* The entire node is consumed, just unlink it. */
1575 gcmkONERROR(
1576 _Link(Mmu, previous, _ReadPageEntry(&map[index + 1])));
1577 break;
1578
1579 case 1:
1580 /* One page will remain. Convert the node to a single node and
1581 ** advance the index. */
1582 _WritePageEntry(&map[index], (_ReadPageEntry(&map[index + 1]) << 8) | gcvMMU_SINGLE);
1583 index ++;
1584 break;
1585
1586 default:
1587 /* Enough pages remain for a new node. However, we will just adjust
1588 ** the size of the current node and advance the index. */
1589 _WritePageEntry(&map[index], (left << 8) | gcvMMU_FREE);
1590 index += left;
1591 break;
1592 }
1593 break;
1594 }
1595
1596 /* Mark node as used. */
1597 gcmkONERROR(_FillPageTable(&map[index], pageCount, gcvMMU_USED));
1598
1599 /* Return pointer to page table. */
1600 *PageTable = &Mmu->pageTableLogical[index];
1601
1602 /* Build virtual address. */
1603 if (Mmu->hardware->mmuVersion == 0)
1604 {
1605 gcmkONERROR(
1606 gckHARDWARE_BuildVirtualAddress(Mmu->hardware, index, 0, &address));
1607 }
1608 else
1609 {
1610 gctUINT32 masterOffset = index / gcdMMU_STLB_4K_ENTRY_NUM
1611 + Mmu->dynamicMappingStart;
1612 gctUINT32 slaveOffset = index % gcdMMU_STLB_4K_ENTRY_NUM;
1613
1614 address = (masterOffset << gcdMMU_MTLB_SHIFT)
1615 | (slaveOffset << gcdMMU_STLB_4K_SHIFT);
1616 }
1617
1618 if (Address != gcvNULL)
1619 {
1620 *Address = address;
1621 }
1622
1623 /* Release the mutex. */
1624 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
1625
1626 /* Success. */
1627 gcmkFOOTER_ARG("*PageTable=0x%x *Address=%08x",
1628 *PageTable, gcmOPT_VALUE(Address));
1629 return gcvSTATUS_OK;
1630
1631OnError:
1632
1633 if (mutex)
1634 {
1635 /* Release the mutex. */
1636 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
1637 }
1638
1639 /* Return the status. */
1640 gcmkFOOTER();
1641 return status;
1642}
1643
1644/*******************************************************************************
1645**
1646** gckMMU_FreePages
1647**
1648** Free pages inside the page table.
1649**
1650** INPUT:
1651**
1652** gckMMU Mmu
1653** Pointer to an gckMMU object.
1654**
1655** gctPOINTER PageTable
1656** Base address of the page table to free.
1657**
1658** gctSIZE_T PageCount
1659** Number of pages to free.
1660**
1661** OUTPUT:
1662**
1663** Nothing.
1664*/
1665gceSTATUS
1666_FreePages(
1667 IN gckMMU Mmu,
1668 IN gctPOINTER PageTable,
1669 IN gctSIZE_T PageCount
1670 )
1671{
1672 gctUINT32_PTR node;
1673 gceSTATUS status;
1674 gctBOOL acquired = gcvFALSE;
1675 gctUINT32 pageCount;
1676
1677 gcmkHEADER_ARG("Mmu=0x%x PageTable=0x%x PageCount=%lu",
1678 Mmu, PageTable, PageCount);
1679
1680 /* Verify the arguments. */
1681 gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
1682 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
1683 gcmkVERIFY_ARGUMENT(PageCount > 0);
1684
1685 gcmkSAFECASTSIZET(pageCount, PageCount);
1686
1687 /* Get the node by index. */
1688 node = Mmu->mapLogical + ((gctUINT32_PTR)PageTable - Mmu->pageTableLogical);
1689
1690 gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
1691 acquired = gcvTRUE;
1692
1693#if gcdMMU_CLEAR_VALUE
1694 if (Mmu->hardware->mmuVersion == 0)
1695 {
1696 _FillPageTable(PageTable, pageCount, gcdMMU_CLEAR_VALUE);
1697 }
1698#endif
1699
1700 if (PageCount == 1)
1701 {
1702 /* Single page node. */
1703 _WritePageEntry(node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
1704#if gcdUSE_MMU_EXCEPTION
1705 /* Enable exception */
1706 _WritePageEntry(PageTable, (1 << 1));
1707#endif
1708 }
1709 else
1710 {
1711 /* Mark the node as free. */
1712 _WritePageEntry(node, (pageCount << 8) | gcvMMU_FREE);
1713 _WritePageEntry(node + 1, ~0U);
1714
1715#if gcdUSE_MMU_EXCEPTION
1716 /* Enable exception */
1717 gcmkVERIFY_OK(_FillPageTable(PageTable, pageCount, 1 << 1));
1718#endif
1719 }
1720
1721 /* We have free nodes. */
1722 Mmu->freeNodes = gcvTRUE;
1723
1724 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
1725 acquired = gcvFALSE;
1726
1727 /* Success. */
1728 gcmkFOOTER_NO();
1729 return gcvSTATUS_OK;
1730
1731OnError:
1732 if (acquired)
1733 {
1734 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
1735 }
1736
1737 gcmkFOOTER();
1738 return status;
1739}
1740
1741gceSTATUS
1742gckMMU_AllocatePages(
1743 IN gckMMU Mmu,
1744 IN gctSIZE_T PageCount,
1745 OUT gctPOINTER * PageTable,
1746 OUT gctUINT32 * Address
1747 )
1748{
1749 return gckMMU_AllocatePagesEx(
1750 Mmu, PageCount, gcvSURF_TYPE_UNKNOWN, PageTable, Address);
1751}
1752
1753gceSTATUS
1754gckMMU_AllocatePagesEx(
1755 IN gckMMU Mmu,
1756 IN gctSIZE_T PageCount,
1757 IN gceSURF_TYPE Type,
1758 OUT gctPOINTER * PageTable,
1759 OUT gctUINT32 * Address
1760 )
1761{
1762#if gcdMIRROR_PAGETABLE
1763 gceSTATUS status;
1764 gctPOINTER pageTable;
1765 gctUINT32 address;
1766 gctINT i;
1767 gckMMU mmu;
1768 gctBOOL acquired = gcvFALSE;
1769 gctBOOL allocated = gcvFALSE;
1770
1771 gckOS_AcquireMutex(Mmu->os, mirrorPageTableMutex, gcvINFINITE);
1772 acquired = gcvTRUE;
1773
1774 /* Allocate page table for current MMU. */
1775 for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
1776 {
1777 if (Mmu == mirrorPageTable->mmus[i])
1778 {
1779 gcmkONERROR(_AllocatePages(Mmu, PageCount, Type, PageTable, Address));
1780 allocated = gcvTRUE;
1781 }
1782 }
1783
1784 /* Allocate page table for other MMUs. */
1785 for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
1786 {
1787 mmu = mirrorPageTable->mmus[i];
1788
1789 if (Mmu != mmu)
1790 {
1791 gcmkONERROR(_AllocatePages(mmu, PageCount, Type, &pageTable, &address));
1792 gcmkASSERT(address == *Address);
1793 }
1794 }
1795
1796 gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
1797 acquired = gcvFALSE;
1798
1799 return gcvSTATUS_OK;
1800OnError:
1801
1802 if (allocated)
1803 {
1804 /* Page tables for multiple GPU always keep the same. So it is impossible
1805 * the fist one allocates successfully but others fail.
1806 */
1807 gcmkASSERT(0);
1808 }
1809
1810 if (acquired)
1811 {
1812 gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
1813 }
1814
1815 return status;
1816#else
1817 return _AllocatePages(Mmu, PageCount, Type, PageTable, Address);
1818#endif
1819}
1820
1821gceSTATUS
1822gckMMU_FreePages(
1823 IN gckMMU Mmu,
1824 IN gctPOINTER PageTable,
1825 IN gctSIZE_T PageCount
1826 )
1827{
1828#if gcdMIRROR_PAGETABLE
1829 gctINT i;
1830 gctUINT32 offset;
1831 gckMMU mmu;
1832
1833 gckOS_AcquireMutex(Mmu->os, mirrorPageTableMutex, gcvINFINITE);
1834
1835 gcmkVERIFY_OK(_FreePages(Mmu, PageTable, PageCount));
1836
1837 offset = (gctUINT32)PageTable - (gctUINT32)Mmu->pageTableLogical;
1838
1839 for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
1840 {
1841 mmu = mirrorPageTable->mmus[i];
1842
1843 if (mmu != Mmu)
1844 {
1845 gcmkVERIFY_OK(_FreePages(mmu, mmu->pageTableLogical + offset/4, PageCount));
1846 }
1847 }
1848
1849 gckOS_ReleaseMutex(Mmu->os, mirrorPageTableMutex);
1850
1851 return gcvSTATUS_OK;
1852#else
1853 return _FreePages(Mmu, PageTable, PageCount);
1854#endif
1855}
1856
1857gceSTATUS
1858gckMMU_SetPage(
1859 IN gckMMU Mmu,
1860 IN gctPHYS_ADDR_T PageAddress,
1861 IN gctUINT32 *PageEntry
1862 )
1863{
1864#if gcdMIRROR_PAGETABLE
1865 gctUINT32_PTR pageEntry;
1866 gctINT i;
1867 gckMMU mmu;
1868 gctUINT32 offset = (gctUINT32)PageEntry - (gctUINT32)Mmu->pageTableLogical;
1869#endif
1870 gctUINT32 addressExt;
1871 gctUINT32 address;
1872
1873 gcmkHEADER_ARG("Mmu=0x%x", Mmu);
1874
1875 /* Verify the arguments. */
1876 gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
1877 gcmkVERIFY_ARGUMENT(PageEntry != gcvNULL);
1878 gcmkVERIFY_ARGUMENT(!(PageAddress & 0xFFF));
1879
1880 /* [31:0]. */
1881 address = (gctUINT32)(PageAddress & 0xFFFFFFFF);
1882 /* [39:32]. */
1883 addressExt = (gctUINT32)((PageAddress >> 32) & 0xFF);
1884
1885 if (Mmu->hardware->mmuVersion == 0)
1886 {
1887 _WritePageEntry(PageEntry, address);
1888 }
1889 else
1890 {
1891 _WritePageEntry(PageEntry, _SetPage(address, addressExt));
1892 }
1893
1894#if gcdMIRROR_PAGETABLE
1895 for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
1896 {
1897 mmu = mirrorPageTable->mmus[i];
1898
1899 if (mmu != Mmu)
1900 {
1901 pageEntry = mmu->pageTableLogical + offset / 4;
1902
1903 if (mmu->hardware->mmuVersion == 0)
1904 {
1905 _WritePageEntry(pageEntry, address);
1906 }
1907 else
1908 {
1909 _WritePageEntry(pageEntry, _SetPage(address, addressExt));
1910 }
1911 }
1912
1913 }
1914#endif
1915
1916 /* Success. */
1917 gcmkFOOTER_NO();
1918 return gcvSTATUS_OK;
1919}
1920
1921#if gcdPROCESS_ADDRESS_SPACE
1922gceSTATUS
1923gckMMU_GetPageEntry(
1924 IN gckMMU Mmu,
1925 IN gctUINT32 Address,
1926 IN gctUINT32_PTR *PageTable
1927 )
1928{
1929 gceSTATUS status;
1930 struct _gcsMMU_STLB *stlb;
1931 struct _gcsMMU_STLB **stlbs = Mmu->stlbs;
1932 gctUINT32 offset = _MtlbOffset(Address);
1933 gctUINT32 mtlbEntry;
1934 gctBOOL ace = gckHARDWARE_IsFeatureAvailable(Mmu->hardware, gcvFEATURE_ACE);
1935
1936 gcmkHEADER_ARG("Mmu=0x%x", Mmu);
1937
1938 /* Verify the arguments. */
1939 gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
1940 gcmkVERIFY_ARGUMENT((Address & 0xFFF) == 0);
1941
1942 stlb = stlbs[offset];
1943
1944 if (stlb == gcvNULL)
1945 {
1946 gcmkONERROR(_AllocateStlb(Mmu->os, &stlb));
1947
1948 mtlbEntry = stlb->physBase
1949 | gcdMMU_MTLB_4K_PAGE
1950 | gcdMMU_MTLB_PRESENT
1951 ;
1952
1953 if (ace)
1954 {
1955 mtlbEntry = mtlbEntry
1956 /* Secure */
1957 | (1 << 4);
1958 }
1959
1960 /* Insert Slave TLB address to Master TLB entry.*/
1961 _WritePageEntry(Mmu->mtlbLogical + offset, mtlbEntry);
1962
1963 /* Record stlb. */
1964 stlbs[offset] = stlb;
1965 }
1966
1967 *PageTable = &stlb->logical[_StlbOffset(Address)];
1968
1969 /* Success. */
1970 gcmkFOOTER_NO();
1971 return gcvSTATUS_OK;
1972
1973OnError:
1974 gcmkFOOTER();
1975 return status;
1976}
1977
1978gceSTATUS
1979_CheckMap(
1980 IN gckMMU Mmu
1981 )
1982{
1983 gceSTATUS status;
1984 gctUINT32_PTR map = Mmu->mapLogical;
1985 gctUINT32 index;
1986
1987 for (index = Mmu->heapList; index < Mmu->pageTableEntries;)
1988 {
1989 /* Check the node type. */
1990 switch (gcmENTRY_TYPE(_ReadPageEntry(&map[index])))
1991 {
1992 case gcvMMU_SINGLE:
1993 /* Move to next node. */
1994 index = _ReadPageEntry(&map[index]) >> 8;
1995 break;
1996
1997 case gcvMMU_FREE:
1998 /* Move to next node. */
1999 index = _ReadPageEntry(&map[index + 1]);
2000 break;
2001
2002 default:
2003 gcmkFATAL("MMU table correcupted at index [%u] = %x!", index, map[index]);
2004 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2005 }
2006 }
2007
2008 return gcvSTATUS_OK;
2009
2010OnError:
2011 return status;
2012}
2013
2014gceSTATUS
2015gckMMU_FlatMapping(
2016 IN gckMMU Mmu,
2017 IN gctUINT32 Physical
2018 )
2019{
2020 gceSTATUS status;
2021 gctUINT32 index = _AddressToIndex(Mmu, Physical);
2022 gctUINT32 i;
2023 gctBOOL gotIt = gcvFALSE;
2024 gctUINT32_PTR map = Mmu->mapLogical;
2025 gctUINT32 previous = ~0U;
2026 gctUINT32_PTR pageTable;
2027
2028 gckMMU_GetPageEntry(Mmu, Physical, &pageTable);
2029
2030 _WritePageEntry(pageTable, _SetPage(Physical));
2031
2032 if (map)
2033 {
2034 /* Find node which contains index. */
2035 for (i = 0; !gotIt && (i < Mmu->pageTableEntries);)
2036 {
2037 gctUINT32 numPages;
2038
2039 switch (gcmENTRY_TYPE(_ReadPageEntry(&map[i])))
2040 {
2041 case gcvMMU_SINGLE:
2042 if (i == index)
2043 {
2044 gotIt = gcvTRUE;
2045 }
2046 else
2047 {
2048 previous = i;
2049 i = _ReadPageEntry(&map[i]) >> 8;
2050 }
2051 break;
2052
2053 case gcvMMU_FREE:
2054 numPages = _ReadPageEntry(&map[i]) >> 8;
2055 if (index >= i && index < i + numPages)
2056 {
2057 gotIt = gcvTRUE;
2058 }
2059 else
2060 {
2061 previous = i;
2062 i = _ReadPageEntry(&map[i + 1]);
2063 }
2064 break;
2065
2066 default:
2067 gcmkFATAL("MMU table correcupted at index %u!", index);
2068 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2069 }
2070 }
2071
2072 switch (gcmENTRY_TYPE(_ReadPageEntry(&map[i])))
2073 {
2074 case gcvMMU_SINGLE:
2075 /* Unlink single node from free list. */
2076 gcmkONERROR(
2077 _Link(Mmu, previous, _ReadPageEntry(&map[i]) >> 8));
2078 break;
2079
2080 case gcvMMU_FREE:
2081 /* Split the node. */
2082 {
2083 gctUINT32 start;
2084 gctUINT32 next = _ReadPageEntry(&map[i+1]);
2085 gctUINT32 total = _ReadPageEntry(&map[i]) >> 8;
2086 gctUINT32 countLeft = index - i;
2087 gctUINT32 countRight = total - countLeft - 1;
2088
2089 if (countLeft)
2090 {
2091 start = i;
2092 _AddFree(Mmu, previous, start, countLeft);
2093 previous = start;
2094 }
2095
2096 if (countRight)
2097 {
2098 start = index + 1;
2099 _AddFree(Mmu, previous, start, countRight);
2100 previous = start;
2101 }
2102
2103 _Link(Mmu, previous, next);
2104 }
2105 break;
2106 }
2107 }
2108
2109 return gcvSTATUS_OK;
2110
2111OnError:
2112
2113 /* Roll back. */
2114 return status;
2115}
2116
2117
2118
2119gceSTATUS
2120gckMMU_FreePagesEx(
2121 IN gckMMU Mmu,
2122 IN gctUINT32 Address,
2123 IN gctSIZE_T PageCount
2124 )
2125{
2126 gctUINT32_PTR node;
2127 gceSTATUS status;
2128
2129#if gcdUSE_MMU_EXCEPTION
2130 gctUINT32 i;
2131 struct _gcsMMU_STLB *stlb;
2132 struct _gcsMMU_STLB **stlbs = Mmu->stlbs;
2133#endif
2134
2135 gcmkHEADER_ARG("Mmu=0x%x Address=0x%x PageCount=%lu",
2136 Mmu, Address, PageCount);
2137
2138 /* Verify the arguments. */
2139 gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
2140 gcmkVERIFY_ARGUMENT(PageCount > 0);
2141
2142 /* Get the node by index. */
2143 node = Mmu->mapLogical + _AddressToIndex(Mmu, Address);
2144
2145 gcmkONERROR(gckOS_AcquireMutex(Mmu->os, Mmu->pageTableMutex, gcvINFINITE));
2146
2147 if (PageCount == 1)
2148 {
2149 /* Single page node. */
2150 _WritePageEntry(node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
2151 }
2152 else
2153 {
2154 /* Mark the node as free. */
2155 _WritePageEntry(node, (PageCount << 8) | gcvMMU_FREE);
2156 _WritePageEntry(node + 1, ~0U);
2157 }
2158
2159 /* We have free nodes. */
2160 Mmu->freeNodes = gcvTRUE;
2161
2162#if gcdUSE_MMU_EXCEPTION
2163 for (i = 0; i < PageCount; i++)
2164 {
2165 /* Get */
2166 stlb = stlbs[_MtlbOffset(Address)];
2167
2168 /* Enable exception */
2169 stlb->logical[_StlbOffset(Address)] = gcdMMU_STLB_EXCEPTION;
2170 }
2171#endif
2172
2173 gcmkVERIFY_OK(gckOS_ReleaseMutex(Mmu->os, Mmu->pageTableMutex));
2174
2175
2176 /* Success. */
2177 gcmkFOOTER_NO();
2178 return gcvSTATUS_OK;
2179
2180OnError:
2181 gcmkFOOTER();
2182 return status;
2183}
2184#endif
2185
2186gceSTATUS
2187gckMMU_Flush(
2188 IN gckMMU Mmu,
2189 IN gceSURF_TYPE Type
2190 )
2191{
2192 gckHARDWARE hardware;
2193 gctUINT32 mask;
2194 gctINT i;
2195
2196 if (Type == gcvSURF_VERTEX || Type == gcvSURF_INDEX)
2197 {
2198 mask = gcvPAGE_TABLE_DIRTY_BIT_FE;
2199 }
2200 else
2201 {
2202 mask = gcvPAGE_TABLE_DIRTY_BIT_OTHER;
2203 }
2204
2205#if gcdPROCESS_ADDRESS_SPACE
2206 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
2207 {
2208 gcmkVERIFY_OK(
2209 gckOS_AtomSetMask(Mmu->pageTableDirty[i], mask));
2210 }
2211#else
2212#if gcdSHARED_PAGETABLE
2213 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
2214 {
2215 hardware = sharedPageTable->hardwares[i];
2216 if (hardware)
2217 {
2218 gcmkVERIFY_OK(gckOS_AtomSetMask(hardware->pageTableDirty, mask));
2219 }
2220 }
2221#elif gcdMIRROR_PAGETABLE
2222 for (i = 0; i < (gctINT)mirrorPageTable->reference; i++)
2223 {
2224 hardware = mirrorPageTable->hardwares[i];
2225
2226 /* Notify cores who use this page table. */
2227 gcmkVERIFY_OK(
2228 gckOS_AtomSetMask(hardware->pageTableDirty, mask));
2229 }
2230#else
2231 hardware = Mmu->hardware;
2232 gcmkVERIFY_OK(
2233 gckOS_AtomSetMask(hardware->pageTableDirty, mask));
2234#endif
2235#endif
2236
2237 return gcvSTATUS_OK;
2238}
2239
2240gceSTATUS
2241gckMMU_DumpPageTableEntry(
2242 IN gckMMU Mmu,
2243 IN gctUINT32 Address
2244 )
2245{
2246#if gcdPROCESS_ADDRESS_SPACE
2247 gcsMMU_STLB_PTR *stlbs = Mmu->stlbs;
2248 gcsMMU_STLB_PTR stlbDesc = stlbs[_MtlbOffset(Address)];
2249#else
2250 gctUINT32_PTR pageTable;
2251 gctUINT32 index;
2252 gctUINT32 mtlb, stlb;
2253#endif
2254
2255 gcmkHEADER_ARG("Mmu=0x%08X Address=0x%08X", Mmu, Address);
2256 gcmkVERIFY_OBJECT(Mmu, gcvOBJ_MMU);
2257
2258 gcmkASSERT(Mmu->hardware->mmuVersion > 0);
2259
2260#if gcdPROCESS_ADDRESS_SPACE
2261 if (stlbDesc)
2262 {
2263 gcmkPRINT(" STLB entry = 0x%08X",
2264 _ReadPageEntry(&stlbDesc->logical[_StlbOffset(Address)]));
2265 }
2266 else
2267 {
2268 gcmkPRINT(" MTLB entry is empty.");
2269 }
2270#else
2271 mtlb = (Address & gcdMMU_MTLB_MASK) >> gcdMMU_MTLB_SHIFT;
2272
2273 if (mtlb >= Mmu->dynamicMappingStart)
2274 {
2275 stlb = (Address & gcdMMU_STLB_4K_MASK) >> gcdMMU_STLB_4K_SHIFT;
2276
2277 pageTable = Mmu->pageTableLogical;
2278
2279 index = (mtlb - Mmu->dynamicMappingStart)
2280 * gcdMMU_STLB_4K_ENTRY_NUM
2281 + stlb;
2282
2283 gcmkPRINT(" Page table entry = 0x%08X", _ReadPageEntry(pageTable + index));
2284 }
2285 else
2286 {
2287 gcsMMU_STLB_PTR stlbObj = Mmu->staticSTLB;
2288 gctUINT32 entry = Mmu->mtlbLogical[mtlb];
2289
2290 stlb = (Address & gcdMMU_STLB_64K_MASK) >> gcdMMU_STLB_64K_SHIFT;
2291
2292 entry &= 0xFFFFFFF0;
2293
2294 while (stlbObj)
2295 {
2296
2297 if (entry == stlbObj->physBase)
2298 {
2299 gcmkPRINT(" Page table entry = 0x%08X", stlbObj->logical[stlb]);
2300 break;
2301 }
2302
2303 stlbObj = stlbObj->next;
2304 }
2305 }
2306#endif
2307
2308 gcmkFOOTER_NO();
2309 return gcvSTATUS_OK;
2310}
2311
2312/******************************************************************************
2313****************************** T E S T C O D E ******************************
2314******************************************************************************/
2315
diff --git a/src/hal/kernel/gc_hal_kernel_power.c b/src/hal/kernel/gc_hal_kernel_power.c
new file mode 100755
index 0000000..5246cfc
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_power.c
@@ -0,0 +1,381 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57
58#define _GC_OBJ_ZONE gcvZONE_POWER
59
60/******************************************************************************\
61************************ Dynamic Voltage Frequency Setting *********************
62\******************************************************************************/
63#if gcdDVFS
64static gctUINT32
65_GetLoadHistory(
66 IN gckDVFS Dvfs,
67 IN gctUINT32 Select,
68 IN gctUINT32 Index
69)
70{
71 return Dvfs->loads[Index];
72}
73
74static void
75_IncreaseScale(
76 IN gckDVFS Dvfs,
77 IN gctUINT32 Load,
78 OUT gctUINT8 *Scale
79 )
80{
81 if (Dvfs->currentScale < 32)
82 {
83 *Scale = Dvfs->currentScale + 8;
84 }
85 else
86 {
87 *Scale = Dvfs->currentScale + 8;
88 *Scale = gcmMIN(64, *Scale);
89 }
90}
91
92static void
93_RecordFrequencyHistory(
94 gckDVFS Dvfs,
95 gctUINT32 Frequency
96 )
97{
98 gctUINT32 i = 0;
99
100 struct _FrequencyHistory *history = Dvfs->frequencyHistory;
101
102 for (i = 0; i < 16; i++)
103 {
104 if (history->frequency == Frequency)
105 {
106 break;
107 }
108
109 if (history->frequency == 0)
110 {
111 history->frequency = Frequency;
112 break;
113 }
114
115 history++;
116 }
117
118 if (i < 16)
119 {
120 history->count++;
121 }
122}
123
124static gctUINT32
125_GetFrequencyHistory(
126 gckDVFS Dvfs,
127 gctUINT32 Frequency
128 )
129{
130 gctUINT32 i = 0;
131
132 struct _FrequencyHistory * history = Dvfs->frequencyHistory;
133
134 for (i = 0; i < 16; i++)
135 {
136 if (history->frequency == Frequency)
137 {
138 break;
139 }
140
141 history++;
142 }
143
144 if (i < 16)
145 {
146 return history->count;
147 }
148
149 return 0;
150}
151
152static void
153_Policy(
154 IN gckDVFS Dvfs,
155 IN gctUINT32 Load,
156 OUT gctUINT8 *Scale
157 )
158{
159 gctUINT8 load[4], nextLoad;
160 gctUINT8 scale;
161
162 /* Last 4 history. */
163 load[0] = (Load & 0xFF);
164 load[1] = (Load & 0xFF00) >> 8;
165 load[2] = (Load & 0xFF0000) >> 16;
166 load[3] = (Load & 0xFF000000) >> 24;
167
168 /* Determine target scale. */
169 if (load[0] > 54)
170 {
171 _IncreaseScale(Dvfs, Load, &scale);
172 }
173 else
174 {
175 nextLoad = (load[0] + load[1] + load[2] + load[3])/4;
176
177 scale = Dvfs->currentScale * (nextLoad) / 54;
178
179 scale = gcmMAX(1, scale);
180 scale = gcmMIN(64, scale);
181 }
182
183 Dvfs->totalConfig++;
184
185 Dvfs->loads[(load[0]-1)/8]++;
186
187 *Scale = scale;
188
189
190 if (Dvfs->totalConfig % 100 == 0)
191 {
192 gcmkPRINT("=======================================================");
193 gcmkPRINT("GPU Load: %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
194 8, 16, 24, 32, 40, 48, 56, 64);
195 gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d %-8d %-8d %-8d",
196 _GetLoadHistory(Dvfs,2, 0),
197 _GetLoadHistory(Dvfs,2, 1),
198 _GetLoadHistory(Dvfs,2, 2),
199 _GetLoadHistory(Dvfs,2, 3),
200 _GetLoadHistory(Dvfs,2, 4),
201 _GetLoadHistory(Dvfs,2, 5),
202 _GetLoadHistory(Dvfs,2, 6),
203 _GetLoadHistory(Dvfs,2, 7)
204 );
205
206 gcmkPRINT("Frequency(MHz) %-8d %-8d %-8d %-8d %-8d",
207 58, 120, 240, 360, 480);
208 gcmkPRINT(" %-8d %-8d %-8d %-8d %-8d",
209 _GetFrequencyHistory(Dvfs, 58),
210 _GetFrequencyHistory(Dvfs,120),
211 _GetFrequencyHistory(Dvfs,240),
212 _GetFrequencyHistory(Dvfs,360),
213 _GetFrequencyHistory(Dvfs,480)
214 );
215 }
216}
217
218static void
219_TimerFunction(
220 gctPOINTER Data
221 )
222{
223 gceSTATUS status;
224 gckDVFS dvfs = (gckDVFS) Data;
225 gckHARDWARE hardware = dvfs->hardware;
226 gctUINT32 value;
227 gctUINT32 frequency;
228 gctUINT8 scale;
229 gctUINT32 t1, t2, consumed;
230
231 gckOS_GetTicks(&t1);
232
233 gcmkONERROR(gckHARDWARE_QueryLoad(hardware, &value));
234
235 /* determine target sacle. */
236 _Policy(dvfs, value, &scale);
237
238 /* Set frequency and voltage. */
239 gcmkONERROR(gckOS_SetGPUFrequency(hardware->os, hardware->core, scale));
240
241 /* Query real frequency. */
242 gcmkONERROR(
243 gckOS_QueryGPUFrequency(hardware->os,
244 hardware->core,
245 &frequency,
246 &dvfs->currentScale));
247
248 _RecordFrequencyHistory(dvfs, frequency);
249
250 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_POWER,
251 "Current frequency = %d",
252 frequency);
253
254 /* Set period. */
255 gcmkONERROR(gckHARDWARE_SetDVFSPeroid(hardware, frequency));
256
257OnError:
258 /* Determine next querying time. */
259 gckOS_GetTicks(&t2);
260
261 consumed = gcmMIN(((long)t2 - (long)t1), 5);
262
263 if (dvfs->stop == gcvFALSE)
264 {
265 gcmkVERIFY_OK(gckOS_StartTimer(hardware->os,
266 dvfs->timer,
267 dvfs->pollingTime - consumed));
268 }
269
270 return;
271}
272
273gceSTATUS
274gckDVFS_Construct(
275 IN gckHARDWARE Hardware,
276 OUT gckDVFS * Dvfs
277 )
278{
279 gceSTATUS status;
280 gctPOINTER pointer;
281 gckDVFS dvfs = gcvNULL;
282 gckOS os = Hardware->os;
283
284 gcmkHEADER_ARG("Hardware=0x%X", Hardware);
285
286 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
287 gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
288
289 /* Allocate a gckDVFS manager. */
290 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(struct _gckDVFS), &pointer));
291
292 gckOS_ZeroMemory(pointer, gcmSIZEOF(struct _gckDVFS));
293
294 dvfs = pointer;
295
296 /* Initialization. */
297 dvfs->hardware = Hardware;
298 dvfs->pollingTime = gcdDVFS_POLLING_TIME;
299 dvfs->os = Hardware->os;
300 dvfs->currentScale = 64;
301
302 /* Create a polling timer. */
303 gcmkONERROR(gckOS_CreateTimer(os, _TimerFunction, pointer, &dvfs->timer));
304
305 /* Initialize frequency and voltage adjustment helper. */
306 gcmkONERROR(gckOS_PrepareGPUFrequency(os, Hardware->core));
307
308 /* Return result. */
309 *Dvfs = dvfs;
310
311 gcmkFOOTER_NO();
312 return gcvSTATUS_OK;
313
314OnError:
315 /* Roll back. */
316 if (dvfs)
317 {
318 if (dvfs->timer)
319 {
320 gcmkVERIFY_OK(gckOS_DestroyTimer(os, dvfs->timer));
321 }
322
323 gcmkOS_SAFE_FREE(os, dvfs);
324 }
325
326 gcmkFOOTER();
327 return status;
328}
329
330gceSTATUS
331gckDVFS_Destroy(
332 IN gckDVFS Dvfs
333 )
334{
335 gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
336 gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
337
338 /* Deinitialize helper fuunction. */
339 gcmkVERIFY_OK(gckOS_FinishGPUFrequency(Dvfs->os, Dvfs->hardware->core));
340
341 /* DestroyTimer. */
342 gcmkVERIFY_OK(gckOS_DestroyTimer(Dvfs->os, Dvfs->timer));
343
344 gcmkOS_SAFE_FREE(Dvfs->os, Dvfs);
345
346 gcmkFOOTER_NO();
347 return gcvSTATUS_OK;
348}
349
350gceSTATUS
351gckDVFS_Start(
352 IN gckDVFS Dvfs
353 )
354{
355 gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
356 gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
357
358 gckHARDWARE_InitDVFS(Dvfs->hardware);
359
360 Dvfs->stop = gcvFALSE;
361
362 gckOS_StartTimer(Dvfs->os, Dvfs->timer, Dvfs->pollingTime);
363
364 gcmkFOOTER_NO();
365 return gcvSTATUS_OK;
366}
367
368gceSTATUS
369gckDVFS_Stop(
370 IN gckDVFS Dvfs
371 )
372{
373 gcmkHEADER_ARG("Dvfs=0x%X", Dvfs);
374 gcmkVERIFY_ARGUMENT(Dvfs != gcvNULL);
375
376 Dvfs->stop = gcvTRUE;
377
378 gcmkFOOTER_NO();
379 return gcvSTATUS_OK;
380}
381#endif
diff --git a/src/hal/kernel/gc_hal_kernel_precomp.h b/src/hal/kernel/gc_hal_kernel_precomp.h
new file mode 100755
index 0000000..a2b5e77
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_precomp.h
@@ -0,0 +1,63 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_precomp_h_
57#define __gc_hal_kernel_precomp_h_
58
59#include "gc_hal.h"
60#include "gc_hal_driver.h"
61#include "gc_hal_kernel.h"
62
63#endif /* __gc_hal_kernel_precomp_h_ */
diff --git a/src/hal/kernel/gc_hal_kernel_security.c b/src/hal/kernel/gc_hal_kernel_security.c
new file mode 100755
index 0000000..41da90d
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_security.c
@@ -0,0 +1,62 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57
58
59
60
61#define _GC_OBJ_ZONE gcvZONE_KERNEL
62
diff --git a/src/hal/kernel/gc_hal_kernel_video_memory.c b/src/hal/kernel/gc_hal_kernel_video_memory.c
new file mode 100755
index 0000000..a9f1f5f
--- /dev/null
+++ b/src/hal/kernel/gc_hal_kernel_video_memory.c
@@ -0,0 +1,2761 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_precomp.h"
57
58#define _GC_OBJ_ZONE gcvZONE_VIDMEM
59
60/******************************************************************************\
61******************************* Private Functions ******************************
62\******************************************************************************/
63
64/*******************************************************************************
65**
66** _Split
67**
68** Split a node on the required byte boundary.
69**
70** INPUT:
71**
72** gckOS Os
73** Pointer to an gckOS object.
74**
75** gcuVIDMEM_NODE_PTR Node
76** Pointer to the node to split.
77**
78** gctSIZE_T Bytes
79** Number of bytes to keep in the node.
80**
81** OUTPUT:
82**
83** Nothing.
84**
85** RETURNS:
86**
87** gctBOOL
88** gcvTRUE if the node was split successfully, or gcvFALSE if there is an
89** error.
90**
91*/
92static gctBOOL
93_Split(
94 IN gckOS Os,
95 IN gcuVIDMEM_NODE_PTR Node,
96 IN gctSIZE_T Bytes
97 )
98{
99 gcuVIDMEM_NODE_PTR node;
100 gctPOINTER pointer = gcvNULL;
101
102 /* Make sure the byte boundary makes sense. */
103 if ((Bytes <= 0) || (Bytes > Node->VidMem.bytes))
104 {
105 return gcvFALSE;
106 }
107
108 /* Allocate a new gcuVIDMEM_NODE object. */
109 if (gcmIS_ERROR(gckOS_Allocate(Os,
110 gcmSIZEOF(gcuVIDMEM_NODE),
111 &pointer)))
112 {
113 /* Error. */
114 return gcvFALSE;
115 }
116
117 node = pointer;
118
119 /* Initialize gcuVIDMEM_NODE structure. */
120 node->VidMem.offset = Node->VidMem.offset + Bytes;
121 node->VidMem.bytes = Node->VidMem.bytes - Bytes;
122 node->VidMem.alignment = 0;
123 node->VidMem.locked = 0;
124 node->VidMem.memory = Node->VidMem.memory;
125 node->VidMem.pool = Node->VidMem.pool;
126 node->VidMem.physical = Node->VidMem.physical;
127#ifdef __QNXNTO__
128 node->VidMem.processID = 0;
129 node->VidMem.logical = gcvNULL;
130#endif
131
132 /* Insert node behind specified node. */
133 node->VidMem.next = Node->VidMem.next;
134 node->VidMem.prev = Node;
135 Node->VidMem.next = node->VidMem.next->VidMem.prev = node;
136
137 /* Insert free node behind specified node. */
138 node->VidMem.nextFree = Node->VidMem.nextFree;
139 node->VidMem.prevFree = Node;
140 Node->VidMem.nextFree = node->VidMem.nextFree->VidMem.prevFree = node;
141
142 /* Adjust size of specified node. */
143 Node->VidMem.bytes = Bytes;
144
145 /* Success. */
146 return gcvTRUE;
147}
148
149/*******************************************************************************
150**
151** _Merge
152**
153** Merge two adjacent nodes together.
154**
155** INPUT:
156**
157** gckOS Os
158** Pointer to an gckOS object.
159**
160** gcuVIDMEM_NODE_PTR Node
161** Pointer to the first of the two nodes to merge.
162**
163** OUTPUT:
164**
165** Nothing.
166**
167*/
168static gceSTATUS
169_Merge(
170 IN gckOS Os,
171 IN gcuVIDMEM_NODE_PTR Node
172 )
173{
174 gcuVIDMEM_NODE_PTR node;
175 gceSTATUS status;
176
177 /* Save pointer to next node. */
178 node = Node->VidMem.next;
179
180 /* This is a good time to make sure the heap is not corrupted. */
181 if (Node->VidMem.offset + Node->VidMem.bytes != node->VidMem.offset)
182 {
183 /* Corrupted heap. */
184 gcmkASSERT(
185 Node->VidMem.offset + Node->VidMem.bytes == node->VidMem.offset);
186 return gcvSTATUS_HEAP_CORRUPTED;
187 }
188
189 /* Adjust byte count. */
190 Node->VidMem.bytes += node->VidMem.bytes;
191
192 /* Unlink next node from linked list. */
193 Node->VidMem.next = node->VidMem.next;
194 Node->VidMem.nextFree = node->VidMem.nextFree;
195
196 Node->VidMem.next->VidMem.prev =
197 Node->VidMem.nextFree->VidMem.prevFree = Node;
198
199 /* Free next node. */
200 status = gcmkOS_SAFE_FREE(Os, node);
201 return status;
202}
203
204/******************************************************************************\
205******************************* gckVIDMEM API Code ******************************
206\******************************************************************************/
207
208/*******************************************************************************
209**
210** gckVIDMEM_ConstructVirtual
211**
212** Construct a new gcuVIDMEM_NODE union for virtual memory.
213**
214** INPUT:
215**
216** gckKERNEL Kernel
217** Pointer to an gckKERNEL object.
218**
219** gctSIZE_T Bytes
220** Number of byte to allocate.
221**
222** OUTPUT:
223**
224** gcuVIDMEM_NODE_PTR * Node
225** Pointer to a variable that receives the gcuVIDMEM_NODE union pointer.
226*/
227gceSTATUS
228gckVIDMEM_ConstructVirtual(
229 IN gckKERNEL Kernel,
230 IN gctUINT32 Flag,
231 IN gctSIZE_T Bytes,
232 OUT gcuVIDMEM_NODE_PTR * Node
233 )
234{
235 gckOS os;
236 gceSTATUS status;
237 gcuVIDMEM_NODE_PTR node = gcvNULL;
238 gctPOINTER pointer = gcvNULL;
239 gctINT i;
240
241 gcmkHEADER_ARG("Kernel=0x%x Flag=%x Bytes=%lu", Kernel, Flag, Bytes);
242
243 /* Verify the arguments. */
244 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
245 gcmkVERIFY_ARGUMENT(Bytes > 0);
246 gcmkVERIFY_ARGUMENT(Node != gcvNULL);
247
248 /* Extract the gckOS object pointer. */
249 os = Kernel->os;
250 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
251
252 /* Allocate an gcuVIDMEM_NODE union. */
253 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
254
255 node = pointer;
256
257 /* Initialize gcuVIDMEM_NODE union for virtual memory. */
258 node->Virtual.kernel = Kernel;
259 node->Virtual.contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
260 node->Virtual.logical = gcvNULL;
261
262 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
263 {
264 node->Virtual.lockeds[i] = 0;
265 node->Virtual.pageTables[i] = gcvNULL;
266 node->Virtual.lockKernels[i] = gcvNULL;
267 }
268
269 gcmkONERROR(gckOS_GetProcessID(&node->Virtual.processID));
270
271 /* Allocate the virtual memory. */
272 gcmkONERROR(
273 gckOS_AllocatePagedMemoryEx(os,
274 Flag,
275 node->Virtual.bytes = Bytes,
276 &node->Virtual.gid,
277 &node->Virtual.physical));
278
279 /* Return pointer to the gcuVIDMEM_NODE union. */
280 *Node = node;
281
282 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
283 "Created virtual node 0x%x for %u bytes @ 0x%x",
284 node, Bytes, node->Virtual.physical);
285
286 /* Success. */
287 gcmkFOOTER_ARG("*Node=0x%x", *Node);
288 return gcvSTATUS_OK;
289
290OnError:
291 /* Roll back. */
292 if (node != gcvNULL)
293 {
294 /* Free the structure. */
295 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
296 }
297
298 /* Return the status. */
299 gcmkFOOTER();
300 return status;
301}
302
303/*******************************************************************************
304**
305** gckVIDMEM_DestroyVirtual
306**
307** Destroy an gcuVIDMEM_NODE union for virtual memory.
308**
309** INPUT:
310**
311** gcuVIDMEM_NODE_PTR Node
312** Pointer to a gcuVIDMEM_NODE union.
313**
314** OUTPUT:
315**
316** Nothing.
317*/
318gceSTATUS
319gckVIDMEM_DestroyVirtual(
320 IN gcuVIDMEM_NODE_PTR Node
321 )
322{
323 gckOS os;
324
325 gcmkHEADER_ARG("Node=0x%x", Node);
326
327 /* Verify the arguments. */
328 gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL);
329
330 /* Extact the gckOS object pointer. */
331 os = Node->Virtual.kernel->os;
332 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
333
334 /* Delete the gcuVIDMEM_NODE union. */
335 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, Node));
336
337 /* Success. */
338 gcmkFOOTER_NO();
339 return gcvSTATUS_OK;
340}
341
342/*******************************************************************************
343**
344** gckVIDMEM_Construct
345**
346** Construct a new gckVIDMEM object.
347**
348** INPUT:
349**
350** gckOS Os
351** Pointer to an gckOS object.
352**
353** gctUINT32 BaseAddress
354** Base address for the video memory heap.
355**
356** gctSIZE_T Bytes
357** Number of bytes in the video memory heap.
358**
359** gctSIZE_T Threshold
360** Minimum number of bytes beyond am allocation before the node is
361** split. Can be used as a minimum alignment requirement.
362**
363** gctSIZE_T BankSize
364** Number of bytes per physical memory bank. Used by bank
365** optimization.
366**
367** OUTPUT:
368**
369** gckVIDMEM * Memory
370** Pointer to a variable that will hold the pointer to the gckVIDMEM
371** object.
372*/
373gceSTATUS
374gckVIDMEM_Construct(
375 IN gckOS Os,
376 IN gctUINT32 BaseAddress,
377 IN gctSIZE_T Bytes,
378 IN gctSIZE_T Threshold,
379 IN gctSIZE_T BankSize,
380 OUT gckVIDMEM * Memory
381 )
382{
383 gckVIDMEM memory = gcvNULL;
384 gceSTATUS status;
385 gcuVIDMEM_NODE_PTR node;
386 gctINT i, banks = 0;
387 gctPOINTER pointer = gcvNULL;
388 gctUINT32 heapBytes;
389 gctUINT32 bankSize;
390
391 gcmkHEADER_ARG("Os=0x%x BaseAddress=%08x Bytes=%lu Threshold=%lu "
392 "BankSize=%lu",
393 Os, BaseAddress, Bytes, Threshold, BankSize);
394
395 /* Verify the arguments. */
396 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
397 gcmkVERIFY_ARGUMENT(Bytes > 0);
398 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
399
400 gcmkSAFECASTSIZET(heapBytes, Bytes);
401 gcmkSAFECASTSIZET(bankSize, BankSize);
402
403 /* Allocate the gckVIDMEM object. */
404 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct _gckVIDMEM), &pointer));
405
406 memory = pointer;
407
408 /* Initialize the gckVIDMEM object. */
409 memory->object.type = gcvOBJ_VIDMEM;
410 memory->os = Os;
411
412 /* Set video memory heap information. */
413 memory->baseAddress = BaseAddress;
414 memory->bytes = heapBytes;
415 memory->freeBytes = heapBytes;
416 memory->threshold = Threshold;
417 memory->mutex = gcvNULL;
418
419 BaseAddress = 0;
420
421 /* Walk all possible banks. */
422 for (i = 0; i < gcmCOUNTOF(memory->sentinel); ++i)
423 {
424 gctUINT32 bytes;
425
426 if (BankSize == 0)
427 {
428 /* Use all bytes for the first bank. */
429 bytes = heapBytes;
430 }
431 else
432 {
433 /* Compute number of bytes for this bank. */
434 bytes = gcmALIGN(BaseAddress + 1, bankSize) - BaseAddress;
435
436 if (bytes > heapBytes)
437 {
438 /* Make sure we don't exceed the total number of bytes. */
439 bytes = heapBytes;
440 }
441 }
442
443 if (bytes == 0)
444 {
445 /* Mark heap is not used. */
446 memory->sentinel[i].VidMem.next =
447 memory->sentinel[i].VidMem.prev =
448 memory->sentinel[i].VidMem.nextFree =
449 memory->sentinel[i].VidMem.prevFree = gcvNULL;
450 continue;
451 }
452
453 /* Allocate one gcuVIDMEM_NODE union. */
454 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
455
456 node = pointer;
457
458 /* Initialize gcuVIDMEM_NODE union. */
459 node->VidMem.memory = memory;
460
461 node->VidMem.next =
462 node->VidMem.prev =
463 node->VidMem.nextFree =
464 node->VidMem.prevFree = &memory->sentinel[i];
465
466 node->VidMem.offset = BaseAddress;
467 node->VidMem.bytes = bytes;
468 node->VidMem.alignment = 0;
469 node->VidMem.physical = 0;
470 node->VidMem.pool = gcvPOOL_UNKNOWN;
471
472 node->VidMem.locked = 0;
473
474#ifdef __QNXNTO__
475 node->VidMem.processID = 0;
476 node->VidMem.logical = gcvNULL;
477#endif
478
479
480 /* Initialize the linked list of nodes. */
481 memory->sentinel[i].VidMem.next =
482 memory->sentinel[i].VidMem.prev =
483 memory->sentinel[i].VidMem.nextFree =
484 memory->sentinel[i].VidMem.prevFree = node;
485
486 /* Mark sentinel. */
487 memory->sentinel[i].VidMem.bytes = 0;
488
489 /* Adjust address for next bank. */
490 BaseAddress += bytes;
491 heapBytes -= bytes;
492 banks ++;
493 }
494
495 /* Assign all the bank mappings. */
496 memory->mapping[gcvSURF_RENDER_TARGET] = banks - 1;
497 memory->mapping[gcvSURF_BITMAP] = banks - 1;
498 if (banks > 1) --banks;
499 memory->mapping[gcvSURF_DEPTH] = banks - 1;
500 memory->mapping[gcvSURF_HIERARCHICAL_DEPTH] = banks - 1;
501 if (banks > 1) --banks;
502 memory->mapping[gcvSURF_TEXTURE] = banks - 1;
503 if (banks > 1) --banks;
504 memory->mapping[gcvSURF_VERTEX] = banks - 1;
505 if (banks > 1) --banks;
506 memory->mapping[gcvSURF_INDEX] = banks - 1;
507 if (banks > 1) --banks;
508 memory->mapping[gcvSURF_TILE_STATUS] = banks - 1;
509 if (banks > 1) --banks;
510 memory->mapping[gcvSURF_TYPE_UNKNOWN] = 0;
511
512
513 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
514 "[GALCORE] INDEX: bank %d",
515 memory->mapping[gcvSURF_INDEX]);
516 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
517 "[GALCORE] VERTEX: bank %d",
518 memory->mapping[gcvSURF_VERTEX]);
519 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
520 "[GALCORE] TEXTURE: bank %d",
521 memory->mapping[gcvSURF_TEXTURE]);
522 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
523 "[GALCORE] RENDER_TARGET: bank %d",
524 memory->mapping[gcvSURF_RENDER_TARGET]);
525 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
526 "[GALCORE] DEPTH: bank %d",
527 memory->mapping[gcvSURF_DEPTH]);
528 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
529 "[GALCORE] TILE_STATUS: bank %d",
530 memory->mapping[gcvSURF_TILE_STATUS]);
531
532 /* Allocate the mutex. */
533 gcmkONERROR(gckOS_CreateMutex(Os, &memory->mutex));
534
535 /* Return pointer to the gckVIDMEM object. */
536 *Memory = memory;
537
538 /* Success. */
539 gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
540 return gcvSTATUS_OK;
541
542OnError:
543 /* Roll back. */
544 if (memory != gcvNULL)
545 {
546 if (memory->mutex != gcvNULL)
547 {
548 /* Delete the mutex. */
549 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, memory->mutex));
550 }
551
552 for (i = 0; i < banks; ++i)
553 {
554 /* Free the heap. */
555 gcmkASSERT(memory->sentinel[i].VidMem.next != gcvNULL);
556 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory->sentinel[i].VidMem.next));
557 }
558
559 /* Free the object. */
560 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, memory));
561 }
562
563 /* Return the status. */
564 gcmkFOOTER();
565 return status;
566}
567
568/*******************************************************************************
569**
570** gckVIDMEM_Destroy
571**
572** Destroy an gckVIDMEM object.
573**
574** INPUT:
575**
576** gckVIDMEM Memory
577** Pointer to an gckVIDMEM object to destroy.
578**
579** OUTPUT:
580**
581** Nothing.
582*/
583gceSTATUS
584gckVIDMEM_Destroy(
585 IN gckVIDMEM Memory
586 )
587{
588 gcuVIDMEM_NODE_PTR node, next;
589 gctINT i;
590
591 gcmkHEADER_ARG("Memory=0x%x", Memory);
592
593 /* Verify the arguments. */
594 gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
595
596 /* Walk all sentinels. */
597 for (i = 0; i < gcmCOUNTOF(Memory->sentinel); ++i)
598 {
599 /* Bail out of the heap is not used. */
600 if (Memory->sentinel[i].VidMem.next == gcvNULL)
601 {
602 break;
603 }
604
605 /* Walk all the nodes until we reach the sentinel. */
606 for (node = Memory->sentinel[i].VidMem.next;
607 node->VidMem.bytes != 0;
608 node = next)
609 {
610 /* Save pointer to the next node. */
611 next = node->VidMem.next;
612
613 /* Free the node. */
614 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, node));
615 }
616 }
617
618 /* Free the mutex. */
619 gcmkVERIFY_OK(gckOS_DeleteMutex(Memory->os, Memory->mutex));
620
621 /* Mark the object as unknown. */
622 Memory->object.type = gcvOBJ_UNKNOWN;
623
624 /* Free the gckVIDMEM object. */
625 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Memory->os, Memory));
626
627 /* Success. */
628 gcmkFOOTER_NO();
629 return gcvSTATUS_OK;
630}
631
632#if gcdENABLE_BANK_ALIGNMENT
633
634#if !gcdBANK_BIT_START
635#error gcdBANK_BIT_START not defined.
636#endif
637
638#if !gcdBANK_BIT_END
639#error gcdBANK_BIT_END not defined.
640#endif
641/*******************************************************************************
642** _GetSurfaceBankAlignment
643**
644** Return the required offset alignment required to the make BaseAddress
645** aligned properly.
646**
647** INPUT:
648**
649** gckOS Os
650** Pointer to gcoOS object.
651**
652** gceSURF_TYPE Type
653** Type of allocation.
654**
655** gctUINT32 BaseAddress
656** Base address of current video memory node.
657**
658** OUTPUT:
659**
660** gctUINT32_PTR AlignmentOffset
661** Pointer to a variable that will hold the number of bytes to skip in
662** the current video memory node in order to make the alignment bank
663** aligned.
664*/
665static gceSTATUS
666_GetSurfaceBankAlignment(
667 IN gckKERNEL Kernel,
668 IN gceSURF_TYPE Type,
669 IN gctUINT32 BaseAddress,
670 OUT gctUINT32_PTR AlignmentOffset
671 )
672{
673 gctUINT32 bank;
674 /* To retrieve the bank. */
675 static const gctUINT32 bankMask = (0xFFFFFFFF << gcdBANK_BIT_START)
676 ^ (0xFFFFFFFF << (gcdBANK_BIT_END + 1));
677
678 /* To retrieve the bank and all the lower bytes. */
679 static const gctUINT32 byteMask = ~(0xFFFFFFFF << (gcdBANK_BIT_END + 1));
680
681 gcmkHEADER_ARG("Type=%d BaseAddress=0x%x ", Type, BaseAddress);
682
683 /* Verify the arguments. */
684 gcmkVERIFY_ARGUMENT(AlignmentOffset != gcvNULL);
685
686 switch (Type)
687 {
688 case gcvSURF_RENDER_TARGET:
689 bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
690
691 /* Align to the first bank. */
692 *AlignmentOffset = (bank == 0) ?
693 0 :
694 ((1 << (gcdBANK_BIT_END + 1)) + 0) - (BaseAddress & byteMask);
695 break;
696
697 case gcvSURF_DEPTH:
698 bank = (BaseAddress & bankMask) >> (gcdBANK_BIT_START);
699
700 /* Align to the third bank. */
701 *AlignmentOffset = (bank == 2) ?
702 0 :
703 ((1 << (gcdBANK_BIT_END + 1)) + (2 << gcdBANK_BIT_START)) - (BaseAddress & byteMask);
704
705 /* Minimum 256 byte alignment needed for fast_msaa. */
706 if ((gcdBANK_CHANNEL_BIT > 7) ||
707 ((gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_FAST_MSAA) != gcvSTATUS_TRUE) &&
708 (gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_SMALL_MSAA) != gcvSTATUS_TRUE)))
709 {
710 /* Add a channel offset at the channel bit. */
711 *AlignmentOffset += (1 << gcdBANK_CHANNEL_BIT);
712 }
713 break;
714
715 default:
716 /* no alignment needed. */
717 *AlignmentOffset = 0;
718 }
719
720 /* Return the status. */
721 gcmkFOOTER_ARG("*AlignmentOffset=%u", *AlignmentOffset);
722 return gcvSTATUS_OK;
723}
724#endif
725
726static gcuVIDMEM_NODE_PTR
727_FindNode(
728 IN gckKERNEL Kernel,
729 IN gckVIDMEM Memory,
730 IN gctINT Bank,
731 IN gctSIZE_T Bytes,
732 IN gceSURF_TYPE Type,
733 IN OUT gctUINT32_PTR Alignment
734 )
735{
736 gcuVIDMEM_NODE_PTR node;
737 gctUINT32 alignment;
738
739#if gcdENABLE_BANK_ALIGNMENT
740 gctUINT32 bankAlignment;
741 gceSTATUS status;
742#endif
743
744 if (Memory->sentinel[Bank].VidMem.nextFree == gcvNULL)
745 {
746 /* No free nodes left. */
747 return gcvNULL;
748 }
749
750#if gcdENABLE_BANK_ALIGNMENT
751 /* Walk all free nodes until we have one that is big enough or we have
752 ** reached the sentinel. */
753 for (node = Memory->sentinel[Bank].VidMem.nextFree;
754 node->VidMem.bytes != 0;
755 node = node->VidMem.nextFree)
756 {
757 if (node->VidMem.bytes < Bytes)
758 {
759 continue;
760 }
761
762 gcmkONERROR(_GetSurfaceBankAlignment(
763 Kernel,
764 Type,
765 node->VidMem.memory->baseAddress + node->VidMem.offset,
766 &bankAlignment));
767
768 bankAlignment = gcmALIGN(bankAlignment, *Alignment);
769
770 /* Compute number of bytes to skip for alignment. */
771 alignment = (*Alignment == 0)
772 ? 0
773 : (*Alignment - (node->VidMem.offset % *Alignment));
774
775 if (alignment == *Alignment)
776 {
777 /* Node is already aligned. */
778 alignment = 0;
779 }
780
781 if (node->VidMem.bytes >= Bytes + alignment + bankAlignment)
782 {
783 /* This node is big enough. */
784 *Alignment = alignment + bankAlignment;
785 return node;
786 }
787 }
788#endif
789
790 /* Walk all free nodes until we have one that is big enough or we have
791 reached the sentinel. */
792 for (node = Memory->sentinel[Bank].VidMem.nextFree;
793 node->VidMem.bytes != 0;
794 node = node->VidMem.nextFree)
795 {
796 gctUINT offset;
797
798 gctINT modulo;
799
800 gcmkSAFECASTSIZET(offset, node->VidMem.offset);
801
802 modulo = gckMATH_ModuloInt(offset, *Alignment);
803
804 /* Compute number of bytes to skip for alignment. */
805 alignment = (*Alignment == 0) ? 0 : (*Alignment - modulo);
806
807 if (alignment == *Alignment)
808 {
809 /* Node is already aligned. */
810 alignment = 0;
811 }
812
813 if (node->VidMem.bytes >= Bytes + alignment)
814 {
815 /* This node is big enough. */
816 *Alignment = alignment;
817 return node;
818 }
819 }
820
821#if gcdENABLE_BANK_ALIGNMENT
822OnError:
823#endif
824 /* Not enough memory. */
825 return gcvNULL;
826}
827
828/*******************************************************************************
829**
830** gckVIDMEM_AllocateLinear
831**
832** Allocate linear memory from the gckVIDMEM object.
833**
834** INPUT:
835**
836** gckVIDMEM Memory
837** Pointer to an gckVIDMEM object.
838**
839** gctSIZE_T Bytes
840** Number of bytes to allocate.
841**
842** gctUINT32 Alignment
843** Byte alignment for allocation.
844**
845** gceSURF_TYPE Type
846** Type of surface to allocate (use by bank optimization).
847**
848** gctBOOL Specified
849** If user must use this pool, it should set Specified to gcvTRUE,
850** otherwise allocator may reserve some memory for other usage, such
851** as small block size allocation request.
852**
853** OUTPUT:
854**
855** gcuVIDMEM_NODE_PTR * Node
856** Pointer to a variable that will hold the allocated memory node.
857*/
858gceSTATUS
859gckVIDMEM_AllocateLinear(
860 IN gckKERNEL Kernel,
861 IN gckVIDMEM Memory,
862 IN gctSIZE_T Bytes,
863 IN gctUINT32 Alignment,
864 IN gceSURF_TYPE Type,
865 IN gctBOOL Specified,
866 OUT gcuVIDMEM_NODE_PTR * Node
867 )
868{
869 gceSTATUS status;
870 gcuVIDMEM_NODE_PTR node;
871 gctUINT32 alignment;
872 gctINT bank, i;
873 gctBOOL acquired = gcvFALSE;
874
875 gcmkHEADER_ARG("Memory=0x%x Bytes=%lu Alignment=%u Type=%d",
876 Memory, Bytes, Alignment, Type);
877
878 /* Verify the arguments. */
879 gcmkVERIFY_OBJECT(Memory, gcvOBJ_VIDMEM);
880 gcmkVERIFY_ARGUMENT(Bytes > 0);
881 gcmkVERIFY_ARGUMENT(Node != gcvNULL);
882 gcmkVERIFY_ARGUMENT(Type < gcvSURF_NUM_TYPES);
883
884 /* Acquire the mutex. */
885 gcmkONERROR(gckOS_AcquireMutex(Memory->os, Memory->mutex, gcvINFINITE));
886
887 acquired = gcvTRUE;
888
889 if (Bytes > Memory->freeBytes)
890 {
891 /* Not enough memory. */
892 status = gcvSTATUS_OUT_OF_MEMORY;
893 goto OnError;
894 }
895
896#if gcdSMALL_BLOCK_SIZE
897 if ((Memory->freeBytes < (Memory->bytes/gcdRATIO_FOR_SMALL_MEMORY))
898 && (Bytes >= gcdSMALL_BLOCK_SIZE)
899 && (Specified == gcvFALSE)
900 )
901 {
902 /* The left memory is for small memory.*/
903 status = gcvSTATUS_OUT_OF_MEMORY;
904 goto OnError;
905 }
906#endif
907
908 /* Find the default bank for this surface type. */
909 gcmkASSERT((gctINT) Type < gcmCOUNTOF(Memory->mapping));
910 bank = Memory->mapping[Type];
911 alignment = Alignment;
912
913 /* Find a free node in the default bank. */
914 node = _FindNode(Kernel, Memory, bank, Bytes, Type, &alignment);
915
916 /* Out of memory? */
917 if (node == gcvNULL)
918 {
919 /* Walk all lower banks. */
920 for (i = bank - 1; i >= 0; --i)
921 {
922 /* Find a free node inside the current bank. */
923 node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
924 if (node != gcvNULL)
925 {
926 break;
927 }
928 }
929 }
930
931 if (node == gcvNULL)
932 {
933 /* Walk all upper banks. */
934 for (i = bank + 1; i < gcmCOUNTOF(Memory->sentinel); ++i)
935 {
936 if (Memory->sentinel[i].VidMem.nextFree == gcvNULL)
937 {
938 /* Abort when we reach unused banks. */
939 break;
940 }
941
942 /* Find a free node inside the current bank. */
943 node = _FindNode(Kernel, Memory, i, Bytes, Type, &alignment);
944 if (node != gcvNULL)
945 {
946 break;
947 }
948 }
949 }
950
951 if (node == gcvNULL)
952 {
953 /* Out of memory. */
954 status = gcvSTATUS_OUT_OF_MEMORY;
955 goto OnError;
956 }
957
958 /* Do we have an alignment? */
959 if (alignment > 0)
960 {
961 /* Split the node so it is aligned. */
962 if (_Split(Memory->os, node, alignment))
963 {
964 /* Successful split, move to aligned node. */
965 node = node->VidMem.next;
966
967 /* Remove alignment. */
968 alignment = 0;
969 }
970 }
971
972 /* Do we have enough memory after the allocation to split it? */
973 if (node->VidMem.bytes - Bytes > Memory->threshold)
974 {
975 /* Adjust the node size. */
976 _Split(Memory->os, node, Bytes);
977 }
978
979 /* Remove the node from the free list. */
980 node->VidMem.prevFree->VidMem.nextFree = node->VidMem.nextFree;
981 node->VidMem.nextFree->VidMem.prevFree = node->VidMem.prevFree;
982 node->VidMem.nextFree =
983 node->VidMem.prevFree = gcvNULL;
984
985 /* Fill in the information. */
986 node->VidMem.alignment = alignment;
987 node->VidMem.memory = Memory;
988#ifdef __QNXNTO__
989 node->VidMem.logical = gcvNULL;
990 gcmkONERROR(gckOS_GetProcessID(&node->VidMem.processID));
991#endif
992
993 /* Adjust the number of free bytes. */
994 Memory->freeBytes -= node->VidMem.bytes;
995
996
997 /* Release the mutex. */
998 gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
999
1000 /* Return the pointer to the node. */
1001 *Node = node;
1002
1003 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
1004 "Allocated %u bytes @ 0x%x [0x%08X]",
1005 node->VidMem.bytes, node, node->VidMem.offset);
1006
1007 /* Success. */
1008 gcmkFOOTER_ARG("*Node=0x%x", *Node);
1009 return gcvSTATUS_OK;
1010
1011OnError:
1012 if (acquired)
1013 {
1014 /* Release the mutex. */
1015 gcmkVERIFY_OK(gckOS_ReleaseMutex(Memory->os, Memory->mutex));
1016 }
1017
1018 /* Return the status. */
1019 gcmkFOOTER();
1020 return status;
1021}
1022
1023/*******************************************************************************
1024**
1025** gckVIDMEM_Free
1026**
1027** Free an allocated video memory node.
1028**
1029** INPUT:
1030**
1031** gckKERNEL Kernel
1032** Pointer to an gckKERNEL object.
1033**
1034** gcuVIDMEM_NODE_PTR Node
1035** Pointer to a gcuVIDMEM_NODE object.
1036**
1037** OUTPUT:
1038**
1039** Nothing.
1040*/
1041gceSTATUS
1042gckVIDMEM_Free(
1043 IN gckKERNEL Kernel,
1044 IN gcuVIDMEM_NODE_PTR Node
1045 )
1046{
1047 gceSTATUS status;
1048 gckKERNEL kernel = gcvNULL;
1049 gckVIDMEM memory = gcvNULL;
1050 gcuVIDMEM_NODE_PTR node;
1051 gctBOOL mutexAcquired = gcvFALSE;
1052
1053 gcmkHEADER_ARG("Node=0x%x", Node);
1054
1055 /* Verify the arguments. */
1056 if ((Node == gcvNULL)
1057 || (Node->VidMem.memory == gcvNULL)
1058 )
1059 {
1060 /* Invalid object. */
1061 gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
1062 }
1063
1064 /**************************** Video Memory ********************************/
1065
1066 if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1067 {
1068 /* Extract pointer to gckVIDMEM object owning the node. */
1069 memory = Node->VidMem.memory;
1070
1071 /* Acquire the mutex. */
1072 gcmkONERROR(
1073 gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
1074
1075 mutexAcquired = gcvTRUE;
1076
1077#ifdef __QNXNTO__
1078 /* Unmap the video memory. */
1079 if (Node->VidMem.logical != gcvNULL)
1080 {
1081 gckKERNEL_UnmapVideoMemory(
1082 Kernel,
1083 Node->VidMem.logical,
1084 Node->VidMem.processID,
1085 Node->VidMem.bytes);
1086 Node->VidMem.logical = gcvNULL;
1087 }
1088
1089 /* Reset. */
1090 Node->VidMem.processID = 0;
1091
1092 /* Don't try to re-free an already freed node. */
1093 if ((Node->VidMem.nextFree == gcvNULL)
1094 && (Node->VidMem.prevFree == gcvNULL)
1095 )
1096#endif
1097 {
1098
1099 /* Check if Node is already freed. */
1100 if (Node->VidMem.nextFree)
1101 {
1102 /* Node is alread freed. */
1103 gcmkONERROR(gcvSTATUS_INVALID_DATA);
1104 }
1105
1106 /* Update the number of free bytes. */
1107 memory->freeBytes += Node->VidMem.bytes;
1108
1109 /* Find the next free node. */
1110 for (node = Node->VidMem.next;
1111 node != gcvNULL && node->VidMem.nextFree == gcvNULL;
1112 node = node->VidMem.next) ;
1113
1114 /* Insert this node in the free list. */
1115 Node->VidMem.nextFree = node;
1116 Node->VidMem.prevFree = node->VidMem.prevFree;
1117
1118 Node->VidMem.prevFree->VidMem.nextFree =
1119 node->VidMem.prevFree = Node;
1120
1121 /* Is the next node a free node and not the sentinel? */
1122 if ((Node->VidMem.next == Node->VidMem.nextFree)
1123 && (Node->VidMem.next->VidMem.bytes != 0)
1124 )
1125 {
1126 /* Merge this node with the next node. */
1127 gcmkONERROR(_Merge(memory->os, node = Node));
1128 gcmkASSERT(node->VidMem.nextFree != node);
1129 gcmkASSERT(node->VidMem.prevFree != node);
1130 }
1131
1132 /* Is the previous node a free node and not the sentinel? */
1133 if ((Node->VidMem.prev == Node->VidMem.prevFree)
1134 && (Node->VidMem.prev->VidMem.bytes != 0)
1135 )
1136 {
1137 /* Merge this node with the previous node. */
1138 gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev));
1139 gcmkASSERT(node->VidMem.nextFree != node);
1140 gcmkASSERT(node->VidMem.prevFree != node);
1141 }
1142 }
1143
1144 /* Release the mutex. */
1145 gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
1146
1147 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
1148 "Node 0x%x is freed.",
1149 Node);
1150
1151 /* Success. */
1152 gcmkFOOTER_NO();
1153 return gcvSTATUS_OK;
1154 }
1155
1156 /*************************** Virtual Memory *******************************/
1157
1158 /* Get gckKERNEL object. */
1159 kernel = Node->Virtual.kernel;
1160
1161 /* Verify the gckKERNEL object pointer. */
1162 gcmkVERIFY_OBJECT(kernel, gcvOBJ_KERNEL);
1163
1164
1165 /* Free the virtual memory. */
1166 gcmkVERIFY_OK(gckOS_FreePagedMemory(kernel->os,
1167 Node->Virtual.physical,
1168 Node->Virtual.bytes));
1169
1170 /* Destroy the gcuVIDMEM_NODE union. */
1171 gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node));
1172
1173 /* Success. */
1174 gcmkFOOTER_NO();
1175 return gcvSTATUS_OK;
1176
1177OnError:
1178 if (mutexAcquired)
1179 {
1180 /* Release the mutex. */
1181 gcmkVERIFY_OK(gckOS_ReleaseMutex(
1182 memory->os, memory->mutex
1183 ));
1184 }
1185
1186 /* Return the status. */
1187 gcmkFOOTER();
1188 return status;
1189}
1190
1191#if !gcdPROCESS_ADDRESS_SPACE
1192/*******************************************************************************
1193**
1194** _NeedVirtualMapping
1195**
1196** Whether setup GPU page table for video node.
1197**
1198** INPUT:
1199** gckKERNEL Kernel
1200** Pointer to an gckKERNEL object.
1201**
1202** gcuVIDMEM_NODE_PTR Node
1203** Pointer to a gcuVIDMEM_NODE union.
1204**
1205** gceCORE Core
1206** Id of current GPU.
1207**
1208** OUTPUT:
1209** gctBOOL * NeedMapping
1210** A pointer hold the result whether Node should be mapping.
1211*/
1212static gceSTATUS
1213_NeedVirtualMapping(
1214 IN gckKERNEL Kernel,
1215 IN gceCORE Core,
1216 IN gcuVIDMEM_NODE_PTR Node,
1217 OUT gctBOOL * NeedMapping
1218)
1219{
1220 gceSTATUS status;
1221 gctPHYS_ADDR_T phys;
1222 gctUINT32 address;
1223 gctUINT32 end;
1224 gcePOOL pool;
1225 gctUINT32 offset;
1226 gctUINT32 baseAddress;
1227 gctUINT32 bytes;
1228
1229 gcmkHEADER_ARG("Node=0x%X", Node);
1230
1231 /* Verify the arguments. */
1232 gcmkVERIFY_ARGUMENT(Kernel != gcvNULL);
1233 gcmkVERIFY_ARGUMENT(Node != gcvNULL);
1234 gcmkVERIFY_ARGUMENT(NeedMapping != gcvNULL);
1235 gcmkVERIFY_ARGUMENT(Core < gcdMAX_GPU_COUNT);
1236
1237 if (Node->Virtual.contiguous)
1238 {
1239 if (!gckHARDWARE_IsFeatureAvailable(Kernel->hardware, gcvFEATURE_MMU))
1240 {
1241 /* Convert logical address into a physical address. */
1242 gcmkONERROR(gckOS_UserLogicalToPhysical(
1243 Kernel->os, Node->Virtual.logical, &phys
1244 ));
1245
1246 gcmkSAFECASTPHYSADDRT(address, phys);
1247
1248 gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
1249
1250 gcmkASSERT(phys >= baseAddress);
1251
1252 /* Subtract baseAddress to get a GPU address used for programming. */
1253 address -= baseAddress;
1254
1255 /* If part of region is belong to gcvPOOL_VIRTUAL,
1256 ** whole region has to be mapped. */
1257 gcmkSAFECASTSIZET(bytes, Node->Virtual.bytes);
1258 end = address + bytes - 1;
1259
1260 gcmkONERROR(gckHARDWARE_SplitMemory(
1261 Kernel->hardware, end, &pool, &offset
1262 ));
1263
1264 *NeedMapping = (pool == gcvPOOL_VIRTUAL);
1265 }
1266 else
1267 {
1268 /* TODO: Check whether physical address in flat mapping. */
1269 *NeedMapping = gcvTRUE;
1270 }
1271 }
1272 else
1273 {
1274 *NeedMapping = gcvTRUE;
1275 }
1276
1277 gcmkFOOTER_ARG("*NeedMapping=%d", *NeedMapping);
1278 return gcvSTATUS_OK;
1279
1280OnError:
1281 gcmkFOOTER();
1282 return status;
1283}
1284#endif
1285
1286#if gcdPROCESS_ADDRESS_SPACE
1287gcsGPU_MAP_PTR
1288_FindGPUMap(
1289 IN gcsGPU_MAP_PTR Head,
1290 IN gctINT ProcessID
1291 )
1292{
1293 gcsGPU_MAP_PTR map = Head;
1294
1295 while (map)
1296 {
1297 if (map->pid == ProcessID)
1298 {
1299 return map;
1300 }
1301
1302 map = map->next;
1303 }
1304
1305 return gcvNULL;
1306}
1307
1308gcsGPU_MAP_PTR
1309_CreateGPUMap(
1310 IN gckOS Os,
1311 IN gcsGPU_MAP_PTR *Head,
1312 IN gcsGPU_MAP_PTR *Tail,
1313 IN gctINT ProcessID
1314 )
1315{
1316 gcsGPU_MAP_PTR gpuMap;
1317 gctPOINTER pointer = gcvNULL;
1318
1319 gckOS_Allocate(Os, sizeof(gcsGPU_MAP), &pointer);
1320
1321 if (pointer == gcvNULL)
1322 {
1323 return gcvNULL;
1324 }
1325
1326 gpuMap = pointer;
1327
1328 gckOS_ZeroMemory(pointer, sizeof(gcsGPU_MAP));
1329
1330 gpuMap->pid = ProcessID;
1331
1332 if (!*Head)
1333 {
1334 *Head = *Tail = gpuMap;
1335 }
1336 else
1337 {
1338 gpuMap->prev = *Tail;
1339 (*Tail)->next = gpuMap;
1340 *Tail = gpuMap;
1341 }
1342
1343 return gpuMap;
1344}
1345
1346void
1347_DestroyGPUMap(
1348 IN gckOS Os,
1349 IN gcsGPU_MAP_PTR *Head,
1350 IN gcsGPU_MAP_PTR *Tail,
1351 IN gcsGPU_MAP_PTR gpuMap
1352 )
1353{
1354
1355 if (gpuMap == *Head)
1356 {
1357 if ((*Head = gpuMap->next) == gcvNULL)
1358 {
1359 *Tail = gcvNULL;
1360 }
1361 }
1362 else
1363 {
1364 gpuMap->prev->next = gpuMap->next;
1365 if (gpuMap == *Tail)
1366 {
1367 *Tail = gpuMap->prev;
1368 }
1369 else
1370 {
1371 gpuMap->next->prev = gpuMap->prev;
1372 }
1373 }
1374
1375 gcmkOS_SAFE_FREE(Os, gpuMap);
1376}
1377#endif
1378
1379/*******************************************************************************
1380**
1381** gckVIDMEM_Lock
1382**
1383** Lock a video memory node and return its hardware specific address.
1384**
1385** INPUT:
1386**
1387** gckKERNEL Kernel
1388** Pointer to an gckKERNEL object.
1389**
1390** gcuVIDMEM_NODE_PTR Node
1391** Pointer to a gcuVIDMEM_NODE union.
1392**
1393** OUTPUT:
1394**
1395** gctUINT32 * Address
1396** Pointer to a variable that will hold the hardware specific address.
1397**
1398** gctUINT32 * PhysicalAddress
1399** Pointer to a variable that will hold the bus address of a contiguous
1400** video node.
1401*/
1402gceSTATUS
1403gckVIDMEM_Lock(
1404 IN gckKERNEL Kernel,
1405 IN gckVIDMEM_NODE Node,
1406 IN gctBOOL Cacheable,
1407 OUT gctUINT32 * Address,
1408 OUT gctUINT32 * Gid,
1409 OUT gctUINT64 * PhysicalAddress
1410 )
1411{
1412 gceSTATUS status;
1413 gctBOOL acquired = gcvFALSE;
1414 gctBOOL locked = gcvFALSE;
1415 gckOS os = gcvNULL;
1416#if !gcdPROCESS_ADDRESS_SPACE
1417 gctBOOL needMapping = gcvFALSE;
1418#endif
1419 gctUINT32 baseAddress;
1420 gctUINT64 physicalAddress;
1421 gcuVIDMEM_NODE_PTR node = Node->node;
1422 gctPHYS_ADDR_T physical;
1423
1424 gcmkHEADER_ARG("Node=0x%x", Node);
1425
1426 /* Verify the arguments. */
1427 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1428 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1429
1430 /* Extract the gckOS object pointer. */
1431 os = Kernel->os;
1432 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
1433
1434 if ((node == gcvNULL)
1435 || (node->VidMem.memory == gcvNULL)
1436 )
1437 {
1438 /* Invalid object. */
1439 gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
1440 }
1441
1442 /* Grab the mutex. */
1443 gcmkONERROR(gckOS_AcquireMutex(os, Node->mutex, gcvINFINITE));
1444 acquired = gcvTRUE;
1445
1446 /**************************** Video Memory ********************************/
1447
1448 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1449 {
1450 gctUINT32 offset;
1451
1452 if (Cacheable == gcvTRUE)
1453 {
1454 gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
1455 }
1456
1457 /* Increment the lock count. */
1458 node->VidMem.locked ++;
1459
1460 /* Return the physical address of the node. */
1461 gcmkSAFECASTSIZET(offset, node->VidMem.offset);
1462
1463 *Address = node->VidMem.memory->baseAddress
1464 + offset
1465 + node->VidMem.alignment;
1466
1467 physicalAddress = *Address;
1468
1469 /* Get hardware specific address. */
1470 {
1471 if (Kernel->hardware->mmuVersion == 0)
1472 {
1473 /* Convert physical to GPU address for old mmu. */
1474 gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &baseAddress));
1475 gcmkASSERT(*Address > baseAddress);
1476 *Address -= baseAddress;
1477 }
1478 }
1479
1480 gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(
1481 Kernel->os,
1482 *Address,
1483 &physical
1484 ));
1485
1486 gcmkSAFECASTSIZET(*Address, physical);
1487
1488 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
1489 "Locked node 0x%x (%d) @ 0x%08X",
1490 node,
1491 node->VidMem.locked,
1492 *Address);
1493 }
1494
1495 /*************************** Virtual Memory *******************************/
1496
1497 else
1498 {
1499
1500 *Gid = node->Virtual.gid;
1501
1502#if gcdPAGED_MEMORY_CACHEABLE
1503 /* Force video memory cacheable. */
1504 Cacheable = gcvTRUE;
1505#endif
1506
1507 gcmkONERROR(
1508 gckOS_LockPages(os,
1509 node->Virtual.physical,
1510 node->Virtual.bytes,
1511 Cacheable,
1512 &node->Virtual.logical,
1513 &node->Virtual.pageCount));
1514
1515 gcmkONERROR(gckOS_UserLogicalToPhysical(
1516 os,
1517 node->Virtual.logical,
1518 &physicalAddress
1519 ));
1520
1521
1522#if !gcdPROCESS_ADDRESS_SPACE
1523 /* Increment the lock count. */
1524 if (node->Virtual.lockeds[Kernel->core] ++ == 0)
1525 {
1526 locked = gcvTRUE;
1527
1528 gcmkONERROR(_NeedVirtualMapping(Kernel, Kernel->core, node, &needMapping));
1529
1530 if (needMapping == gcvFALSE)
1531 {
1532 /* Get hardware specific address. */
1533 {
1534 gcmkONERROR(gckHARDWARE_ConvertLogical(
1535 Kernel->hardware,
1536 node->Virtual.logical,
1537 gcvTRUE,
1538 &node->Virtual.addresses[Kernel->core]));
1539 }
1540 }
1541 else
1542 {
1543 {
1544 /* Allocate pages inside the MMU. */
1545 gcmkONERROR(
1546 gckMMU_AllocatePagesEx(Kernel->mmu,
1547 node->Virtual.pageCount,
1548 node->Virtual.type,
1549 &node->Virtual.pageTables[Kernel->core],
1550 &node->Virtual.addresses[Kernel->core]));
1551 }
1552
1553 node->Virtual.lockKernels[Kernel->core] = Kernel;
1554
1555 /* Map the pages. */
1556 gcmkONERROR(
1557 gckOS_MapPagesEx(os,
1558 Kernel->core,
1559 node->Virtual.physical,
1560 node->Virtual.pageCount,
1561 node->Virtual.addresses[Kernel->core],
1562 node->Virtual.pageTables[Kernel->core]));
1563
1564 {
1565 gcmkONERROR(gckMMU_Flush(Kernel->mmu, node->Virtual.type));
1566 }
1567 }
1568 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
1569 "Mapped virtual node 0x%x to 0x%08X",
1570 node,
1571 node->Virtual.addresses[Kernel->core]);
1572 }
1573
1574 /* Return hardware address. */
1575 *Address = node->Virtual.addresses[Kernel->core];
1576#endif
1577 }
1578
1579 /* Release the mutex. */
1580 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
1581
1582 *PhysicalAddress = (gctUINT64)physicalAddress;
1583
1584 /* Success. */
1585 gcmkFOOTER_ARG("*Address=%08x", *Address);
1586 return gcvSTATUS_OK;
1587
1588OnError:
1589 if (locked)
1590 {
1591 if (node->Virtual.pageTables[Kernel->core] != gcvNULL)
1592 {
1593 {
1594 /* Free the pages from the MMU. */
1595 gcmkVERIFY_OK(
1596 gckMMU_FreePages(Kernel->mmu,
1597 node->Virtual.pageTables[Kernel->core],
1598 node->Virtual.pageCount));
1599 }
1600 node->Virtual.pageTables[Kernel->core] = gcvNULL;
1601 node->Virtual.lockKernels[Kernel->core] = gcvNULL;
1602 }
1603
1604 /* Unlock the pages. */
1605 gcmkVERIFY_OK(
1606 gckOS_UnlockPages(os,
1607 node->Virtual.physical,
1608 node->Virtual.bytes,
1609 node->Virtual.logical
1610 ));
1611
1612 node->Virtual.lockeds[Kernel->core]--;
1613 }
1614
1615 if (acquired)
1616 {
1617 /* Release the mutex. */
1618 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
1619 }
1620
1621 /* Return the status. */
1622 gcmkFOOTER();
1623 return status;
1624}
1625
1626/*******************************************************************************
1627**
1628** gckVIDMEM_Unlock
1629**
1630** Unlock a video memory node.
1631**
1632** INPUT:
1633**
1634** gckKERNEL Kernel
1635** Pointer to an gckKERNEL object.
1636**
1637** gcuVIDMEM_NODE_PTR Node
1638** Pointer to a locked gcuVIDMEM_NODE union.
1639**
1640** gceSURF_TYPE Type
1641** Type of surface to unlock.
1642**
1643** gctBOOL * Asynchroneous
1644** Pointer to a variable specifying whether the surface should be
1645** unlocked asynchroneously or not.
1646**
1647** OUTPUT:
1648**
1649** gctBOOL * Asynchroneous
1650** Pointer to a variable receiving the number of bytes used in the
1651** command buffer specified by 'Commands'. If gcvNULL, there is no
1652** command buffer.
1653*/
1654gceSTATUS
1655gckVIDMEM_Unlock(
1656 IN gckKERNEL Kernel,
1657 IN gckVIDMEM_NODE Node,
1658 IN gceSURF_TYPE Type,
1659 IN OUT gctBOOL * Asynchroneous
1660 )
1661{
1662 gceSTATUS status;
1663 gckOS os = gcvNULL;
1664 gctBOOL acquired = gcvFALSE;
1665 gcuVIDMEM_NODE_PTR node = Node->node;
1666
1667 gcmkHEADER_ARG("Node=0x%x Type=%d *Asynchroneous=%d",
1668 Node, Type, gcmOPT_VALUE(Asynchroneous));
1669
1670 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1671
1672 /* Get the gckOS object pointer. */
1673 os = Kernel->os;
1674 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
1675
1676 /* Verify the arguments. */
1677 if ((node == gcvNULL)
1678 || (node->VidMem.memory == gcvNULL)
1679 )
1680 {
1681 /* Invalid object. */
1682 gcmkONERROR(gcvSTATUS_INVALID_OBJECT);
1683 }
1684
1685 /* Grab the mutex. */
1686 gcmkONERROR(gckOS_AcquireMutex(os, Node->mutex, gcvINFINITE));
1687 acquired = gcvTRUE;
1688
1689 /**************************** Video Memory ********************************/
1690
1691 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1692 {
1693 if (node->VidMem.locked <= 0)
1694 {
1695 /* The surface was not locked. */
1696 status = gcvSTATUS_MEMORY_UNLOCKED;
1697 goto OnError;
1698 }
1699
1700 if (Asynchroneous != gcvNULL)
1701 {
1702 /* Schedule an event to sync with GPU. */
1703 *Asynchroneous = gcvTRUE;
1704 }
1705 else
1706 {
1707 /* Decrement the lock count. */
1708 node->VidMem.locked --;
1709 }
1710
1711 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
1712 "Unlocked node 0x%x (%d)",
1713 node,
1714 node->VidMem.locked);
1715 }
1716
1717 /*************************** Virtual Memory *******************************/
1718
1719 else
1720 {
1721
1722
1723 if (Asynchroneous == gcvNULL)
1724 {
1725#if !gcdPROCESS_ADDRESS_SPACE
1726 if (node->Virtual.lockeds[Kernel->core] == 0)
1727 {
1728 status = gcvSTATUS_MEMORY_UNLOCKED;
1729 goto OnError;
1730 }
1731
1732 /* Decrement lock count. */
1733 -- node->Virtual.lockeds[Kernel->core];
1734
1735 /* See if we can unlock the resources. */
1736 if (node->Virtual.lockeds[Kernel->core] == 0)
1737 {
1738 /* Free the page table. */
1739 if (node->Virtual.pageTables[Kernel->core] != gcvNULL)
1740 {
1741 {
1742 gcmkONERROR(
1743 gckMMU_FreePages(Kernel->mmu,
1744 node->Virtual.pageTables[Kernel->core],
1745 node->Virtual.pageCount));
1746 }
1747
1748 gcmkONERROR(gckOS_UnmapPages(
1749 Kernel->os,
1750 node->Virtual.pageCount,
1751 node->Virtual.addresses[Kernel->core]
1752 ));
1753
1754 /* Mark page table as freed. */
1755 node->Virtual.pageTables[Kernel->core] = gcvNULL;
1756 node->Virtual.lockKernels[Kernel->core] = gcvNULL;
1757 }
1758 }
1759
1760 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
1761 "Unmapped virtual node 0x%x from 0x%08X",
1762 node, node->Virtual.addresses[Kernel->core]);
1763#endif
1764
1765 }
1766
1767 else
1768 {
1769 gcmkONERROR(
1770 gckOS_UnlockPages(os,
1771 node->Virtual.physical,
1772 node->Virtual.bytes,
1773 node->Virtual.logical));
1774
1775 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM,
1776 "Scheduled unlock for virtual node 0x%x",
1777 node);
1778
1779 /* Schedule the surface to be unlocked. */
1780 *Asynchroneous = gcvTRUE;
1781 }
1782 }
1783
1784 /* Release the mutex. */
1785 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
1786 acquired = gcvFALSE;
1787
1788 /* Success. */
1789 gcmkFOOTER_ARG("*Asynchroneous=%d", gcmOPT_VALUE(Asynchroneous));
1790 return gcvSTATUS_OK;
1791
1792OnError:
1793 if (acquired)
1794 {
1795 /* Release the mutex. */
1796 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mutex));
1797 }
1798
1799 /* Return the status. */
1800 gcmkFOOTER();
1801 return status;
1802}
1803
1804#if gcdPROCESS_ADDRESS_SPACE
1805gceSTATUS
1806gckVIDMEM_Node_Lock(
1807 IN gckKERNEL Kernel,
1808 IN gckVIDMEM_NODE Node,
1809 OUT gctUINT32 *Address
1810 )
1811{
1812 gceSTATUS status;
1813 gckOS os;
1814 gcuVIDMEM_NODE_PTR node = Node->node;
1815 gcsGPU_MAP_PTR gpuMap;
1816 gctPHYS_ADDR physical = gcvNULL;
1817 gctUINT32 phys = gcvINVALID_ADDRESS;
1818 gctUINT32 processID;
1819 gcsLOCK_INFO_PTR lockInfo;
1820 gctUINT32 pageCount;
1821 gckMMU mmu;
1822 gctUINT32 i;
1823 gctUINT32_PTR pageTableEntry;
1824 gctUINT32 offset = 0;
1825 gctBOOL acquired = gcvFALSE;
1826
1827 gcmkHEADER_ARG("Node = %x", Node);
1828
1829 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1830 gcmkVERIFY_ARGUMENT(Node != gcvNULL);
1831 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1832
1833 os = Kernel->os;
1834 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
1835
1836 gcmkONERROR(gckOS_GetProcessID(&processID));
1837
1838 gcmkONERROR(gckKERNEL_GetProcessMMU(Kernel, &mmu));
1839
1840 gcmkONERROR(gckOS_AcquireMutex(os, Node->mapMutex, gcvINFINITE));
1841 acquired = gcvTRUE;
1842
1843 /* Get map information for current process. */
1844 gpuMap = _FindGPUMap(Node->mapHead, processID);
1845
1846 if (gpuMap == gcvNULL)
1847 {
1848 gpuMap = _CreateGPUMap(os, &Node->mapHead, &Node->mapTail, processID);
1849
1850 if (gpuMap == gcvNULL)
1851 {
1852 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1853 }
1854 }
1855
1856 lockInfo = &gpuMap->lockInfo;
1857
1858 if (lockInfo->lockeds[Kernel->core] ++ == 0)
1859 {
1860 /* Get necessary information. */
1861 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1862 {
1863 phys = node->VidMem.memory->baseAddress
1864 + node->VidMem.offset
1865 + node->VidMem.alignment;
1866
1867 /* GPU page table use 4K page. */
1868 pageCount = ((phys + node->VidMem.bytes + 4096 - 1) >> 12)
1869 - (phys >> 12);
1870
1871 offset = phys & 0xFFF;
1872 }
1873 else
1874 {
1875 pageCount = node->Virtual.pageCount;
1876 physical = node->Virtual.physical;
1877 }
1878
1879 /* Allocate pages inside the MMU. */
1880 gcmkONERROR(gckMMU_AllocatePages(
1881 mmu,
1882 pageCount,
1883 &lockInfo->pageTables[Kernel->core],
1884 &lockInfo->GPUAddresses[Kernel->core]));
1885
1886 /* Record MMU from which pages are allocated. */
1887 lockInfo->lockMmus[Kernel->core] = mmu;
1888
1889 pageTableEntry = lockInfo->pageTables[Kernel->core];
1890
1891 /* Fill page table entries. */
1892 if (phys != gcvINVALID_ADDRESS)
1893 {
1894 gctUINT32 address = lockInfo->GPUAddresses[Kernel->core];
1895 for (i = 0; i < pageCount; i++)
1896 {
1897 gckMMU_GetPageEntry(mmu, address, &pageTableEntry);
1898 gckMMU_SetPage(mmu, phys & 0xFFFFF000, pageTableEntry);
1899 phys += 4096;
1900 address += 4096;
1901 pageTableEntry += 1;
1902 }
1903 }
1904 else
1905 {
1906 gctUINT32 address = lockInfo->GPUAddresses[Kernel->core];
1907 gcmkASSERT(physical != gcvNULL);
1908 gcmkONERROR(gckOS_MapPagesEx(os,
1909 Kernel->core,
1910 physical,
1911 pageCount,
1912 address,
1913 pageTableEntry));
1914 }
1915
1916 gcmkONERROR(gckMMU_Flush(mmu));
1917 }
1918
1919 *Address = lockInfo->GPUAddresses[Kernel->core] + offset;
1920
1921 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mapMutex));
1922 acquired = gcvFALSE;
1923
1924
1925 gcmkFOOTER_NO();
1926 return gcvSTATUS_OK;
1927
1928OnError:
1929 if (acquired)
1930 {
1931 gcmkVERIFY_OK(gckOS_ReleaseMutex(os, Node->mapMutex));
1932 }
1933
1934 gcmkFOOTER();
1935 return status;
1936}
1937
1938gceSTATUS
1939gckVIDMEM_NODE_Unlock(
1940 IN gckKERNEL Kernel,
1941 IN gckVIDMEM_NODE Node,
1942 IN gctUINT32 ProcessID
1943 )
1944{
1945 gceSTATUS status;
1946 gcsGPU_MAP_PTR gpuMap;
1947 gcsLOCK_INFO_PTR lockInfo;
1948 gckMMU mmu;
1949 gcuVIDMEM_NODE_PTR node;
1950 gctUINT32 pageCount;
1951 gctBOOL acquired = gcvFALSE;
1952
1953 gcmkHEADER_ARG("Kernel=0x%08X, Node = %x, ProcessID=%d",
1954 Kernel, Node, ProcessID);
1955
1956 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1957 gcmkVERIFY_ARGUMENT(Node != gcvNULL);
1958
1959 gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Node->mapMutex, gcvINFINITE));
1960 acquired = gcvTRUE;
1961
1962 /* Get map information for current process. */
1963 gpuMap = _FindGPUMap(Node->mapHead, ProcessID);
1964
1965 if (gpuMap == gcvNULL)
1966 {
1967 /* No mapping for this process. */
1968 gcmkONERROR(gcvSTATUS_INVALID_DATA);
1969 }
1970
1971 lockInfo = &gpuMap->lockInfo;
1972
1973 if (--lockInfo->lockeds[Kernel->core] == 0)
1974 {
1975 node = Node->node;
1976
1977 /* Get necessary information. */
1978 if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
1979 {
1980 gctUINT32 phys = node->VidMem.memory->baseAddress
1981 + node->VidMem.offset
1982 + node->VidMem.alignment;
1983
1984 /* GPU page table use 4K page. */
1985 pageCount = ((phys + node->VidMem.bytes + 4096 - 1) >> 12)
1986 - (phys >> 12);
1987 }
1988 else
1989 {
1990 pageCount = node->Virtual.pageCount;
1991 }
1992
1993 /* Get MMU which allocates pages. */
1994 mmu = lockInfo->lockMmus[Kernel->core];
1995
1996 /* Free virtual spaces in page table. */
1997 gcmkVERIFY_OK(gckMMU_FreePagesEx(
1998 mmu,
1999 lockInfo->GPUAddresses[Kernel->core],
2000 pageCount
2001 ));
2002
2003 _DestroyGPUMap(Kernel->os, &Node->mapHead, &Node->mapTail, gpuMap);
2004 }
2005
2006 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Node->mapMutex));
2007 acquired = gcvFALSE;
2008
2009 gcmkFOOTER_NO();
2010 return gcvSTATUS_OK;
2011
2012OnError:
2013 if (acquired)
2014 {
2015 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Node->mapMutex));
2016 }
2017
2018 gcmkFOOTER();
2019 return status;
2020}
2021#endif
2022
2023/*******************************************************************************
2024**
2025** gckVIDMEM_HANDLE_Allocate
2026**
2027** Allocate a handle for a gckVIDMEM_NODE object.
2028**
2029** INPUT:
2030**
2031** gckKERNEL Kernel
2032** Pointer to an gckKERNEL object.
2033**
2034** gckVIDMEM_NODE Node
2035** Pointer to a gckVIDMEM_NODE object.
2036**
2037** OUTPUT:
2038**
2039** gctUINT32 * Handle
2040** Pointer to a variable receiving a handle represent this
2041** gckVIDMEM_NODE in userspace.
2042*/
2043static gceSTATUS
2044gckVIDMEM_HANDLE_Allocate(
2045 IN gckKERNEL Kernel,
2046 IN gckVIDMEM_NODE Node,
2047 OUT gctUINT32 * Handle
2048 )
2049{
2050 gceSTATUS status;
2051 gctUINT32 processID = 0;
2052 gctPOINTER pointer = gcvNULL;
2053 gctPOINTER handleDatabase = gcvNULL;
2054 gctPOINTER mutex = gcvNULL;
2055 gctUINT32 handle = 0;
2056 gckVIDMEM_HANDLE handleObject = gcvNULL;
2057 gckOS os = Kernel->os;
2058
2059 gcmkHEADER_ARG("Kernel=0x%X, Node=0x%X", Kernel, Node);
2060
2061 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
2062
2063 /* Allocate a gckVIDMEM_HANDLE object. */
2064 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsVIDMEM_HANDLE), &pointer));
2065
2066 gcmkVERIFY_OK(gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsVIDMEM_HANDLE)));
2067
2068 handleObject = pointer;
2069
2070 gcmkONERROR(gckOS_AtomConstruct(os, &handleObject->reference));
2071
2072 /* Set default reference count to 1. */
2073 gckOS_AtomSet(os, handleObject->reference, 1);
2074
2075 gcmkVERIFY_OK(gckOS_GetProcessID(&processID));
2076
2077 gcmkONERROR(
2078 gckKERNEL_FindHandleDatbase(Kernel,
2079 processID,
2080 &handleDatabase,
2081 &mutex));
2082
2083 /* Allocate a handle for this object. */
2084 gcmkONERROR(
2085 gckKERNEL_AllocateIntegerId(handleDatabase, handleObject, &handle));
2086
2087 handleObject->node = Node;
2088 handleObject->handle = handle;
2089
2090 *Handle = handle;
2091
2092 gcmkFOOTER_ARG("*Handle=%d", *Handle);
2093 return gcvSTATUS_OK;
2094
2095OnError:
2096 if (handleObject != gcvNULL)
2097 {
2098 if (handleObject->reference != gcvNULL)
2099 {
2100 gcmkVERIFY_OK(gckOS_AtomDestroy(os, handleObject->reference));
2101 }
2102
2103 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, handleObject));
2104 }
2105
2106 gcmkFOOTER();
2107 return status;
2108}
2109
2110static gceSTATUS
2111gckVIDMEM_NODE_Reference(
2112 IN gckKERNEL Kernel,
2113 IN gckVIDMEM_NODE Node
2114 )
2115{
2116 gctINT32 oldValue;
2117 gcmkHEADER_ARG("Kernel=0x%X Node=0x%X", Kernel, Node);
2118
2119 gckOS_AtomIncrement(Kernel->os, Node->reference, &oldValue);
2120
2121 gcmkFOOTER_NO();
2122 return gcvSTATUS_OK;
2123}
2124
2125gceSTATUS
2126gckVIDMEM_HANDLE_Reference(
2127 IN gckKERNEL Kernel,
2128 IN gctUINT32 ProcessID,
2129 IN gctUINT32 Handle
2130 )
2131{
2132 gceSTATUS status;
2133 gckVIDMEM_HANDLE handleObject = gcvNULL;
2134 gctPOINTER database = gcvNULL;
2135 gctPOINTER mutex = gcvNULL;
2136 gctINT32 oldValue = 0;
2137 gctBOOL acquired = gcvFALSE;
2138
2139 gcmkHEADER_ARG("Handle=%d PrcoessID=%d", Handle, ProcessID);
2140
2141 gcmkONERROR(
2142 gckKERNEL_FindHandleDatbase(Kernel, ProcessID, &database, &mutex));
2143
2144 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
2145 acquired = gcvTRUE;
2146
2147 /* Translate handle to gckVIDMEM_HANDLE object. */
2148 gcmkONERROR(
2149 gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
2150
2151 /* Increase the reference count. */
2152 gckOS_AtomIncrement(Kernel->os, handleObject->reference, &oldValue);
2153
2154 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2155 acquired = gcvFALSE;
2156
2157 gcmkFOOTER_NO();
2158 return gcvSTATUS_OK;
2159
2160OnError:
2161 if (acquired)
2162 {
2163 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2164 }
2165
2166 gcmkFOOTER();
2167 return status;
2168}
2169
2170gceSTATUS
2171gckVIDMEM_HANDLE_Dereference(
2172 IN gckKERNEL Kernel,
2173 IN gctUINT32 ProcessID,
2174 IN gctUINT32 Handle
2175 )
2176{
2177 gceSTATUS status;
2178 gctPOINTER handleDatabase = gcvNULL;
2179 gctPOINTER mutex = gcvNULL;
2180 gctINT32 oldValue = 0;
2181 gckVIDMEM_HANDLE handleObject = gcvNULL;
2182 gctBOOL acquired = gcvFALSE;
2183
2184 gcmkHEADER_ARG("Handle=%d PrcoessID=%d", Handle, ProcessID);
2185
2186 gcmkONERROR(
2187 gckKERNEL_FindHandleDatbase(Kernel,
2188 ProcessID,
2189 &handleDatabase,
2190 &mutex));
2191
2192 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
2193 acquired = gcvTRUE;
2194
2195 /* Translate handle to gckVIDMEM_HANDLE. */
2196 gcmkONERROR(
2197 gckKERNEL_QueryIntegerId(handleDatabase, Handle, (gctPOINTER *)&handleObject));
2198
2199 gckOS_AtomDecrement(Kernel->os, handleObject->reference, &oldValue);
2200
2201 if (oldValue == 1)
2202 {
2203 /* Remove handle from database if this is the last reference. */
2204 gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(handleDatabase, Handle));
2205 }
2206
2207 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2208 acquired = gcvFALSE;
2209
2210 if (oldValue == 1)
2211 {
2212 gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, handleObject->reference));
2213 gcmkOS_SAFE_FREE(Kernel->os, handleObject);
2214 }
2215
2216 gcmkFOOTER_NO();
2217 return gcvSTATUS_OK;
2218
2219OnError:
2220 if (acquired)
2221 {
2222 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2223 }
2224
2225 gcmkFOOTER();
2226 return status;
2227}
2228
2229gceSTATUS
2230gckVIDMEM_HANDLE_LookupAndReference(
2231 IN gckKERNEL Kernel,
2232 IN gctUINT32 Handle,
2233 OUT gckVIDMEM_NODE * Node
2234 )
2235{
2236 gceSTATUS status;
2237 gckVIDMEM_HANDLE handleObject = gcvNULL;
2238 gckVIDMEM_NODE node = gcvNULL;
2239 gctPOINTER database = gcvNULL;
2240 gctPOINTER mutex = gcvNULL;
2241 gctUINT32 processID = 0;
2242 gctBOOL acquired = gcvFALSE;
2243
2244 gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
2245
2246 gckOS_GetProcessID(&processID);
2247
2248 gcmkONERROR(
2249 gckKERNEL_FindHandleDatbase(Kernel, processID, &database, &mutex));
2250
2251 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
2252 acquired = gcvTRUE;
2253
2254 /* Translate handle to gckVIDMEM_HANDLE object. */
2255 gcmkONERROR(
2256 gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
2257
2258 /* Get gckVIDMEM_NODE object. */
2259 node = handleObject->node;
2260
2261 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2262 acquired = gcvFALSE;
2263
2264 /* Reference this gckVIDMEM_NODE object. */
2265 gcmkVERIFY_OK(gckVIDMEM_NODE_Reference(Kernel, node));
2266
2267 /* Return result. */
2268 *Node = node;
2269
2270 gcmkFOOTER_ARG("*Node=%d", *Node);
2271 return gcvSTATUS_OK;
2272
2273OnError:
2274 if (acquired)
2275 {
2276 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2277 }
2278
2279 gcmkFOOTER();
2280 return status;
2281}
2282
2283gceSTATUS
2284gckVIDMEM_HANDLE_Lookup(
2285 IN gckKERNEL Kernel,
2286 IN gctUINT32 ProcessID,
2287 IN gctUINT32 Handle,
2288 OUT gckVIDMEM_NODE * Node
2289 )
2290{
2291 gceSTATUS status;
2292 gckVIDMEM_HANDLE handleObject = gcvNULL;
2293 gckVIDMEM_NODE node = gcvNULL;
2294 gctPOINTER database = gcvNULL;
2295 gctPOINTER mutex = gcvNULL;
2296 gctBOOL acquired = gcvFALSE;
2297
2298 gcmkHEADER_ARG("Kernel=0x%X ProcessID=%d Handle=%d",
2299 Kernel, ProcessID, Handle);
2300
2301 gcmkONERROR(
2302 gckKERNEL_FindHandleDatbase(Kernel, ProcessID, &database, &mutex));
2303
2304 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
2305 acquired = gcvTRUE;
2306
2307 gcmkONERROR(
2308 gckKERNEL_QueryIntegerId(database, Handle, (gctPOINTER *)&handleObject));
2309
2310 node = handleObject->node;
2311
2312 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2313 acquired = gcvFALSE;
2314
2315 *Node = node;
2316
2317 gcmkFOOTER_ARG("*Node=%d", *Node);
2318 return gcvSTATUS_OK;
2319
2320OnError:
2321 if (acquired)
2322 {
2323 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2324 }
2325
2326 gcmkFOOTER();
2327 return status;
2328}
2329
2330/*******************************************************************************
2331**
2332** gckVIDMEM_NODE_Allocate
2333**
2334** Allocate a gckVIDMEM_NODE object.
2335**
2336** INPUT:
2337**
2338** gckKERNEL Kernel
2339** Pointer to an gckKERNEL object.
2340**
2341** gcuVIDMEM_NODE_PTR Node
2342** Pointer to a gcuVIDMEM_NODE union.
2343**
2344** OUTPUT:
2345**
2346** gctUINT32 * Handle
2347** Pointer to a variable receiving a handle represent this
2348** gckVIDMEM_NODE in userspace.
2349*/
2350gceSTATUS
2351gckVIDMEM_NODE_Allocate(
2352 IN gckKERNEL Kernel,
2353 IN gcuVIDMEM_NODE_PTR VideoNode,
2354 IN gceSURF_TYPE Type,
2355 IN gcePOOL Pool,
2356 IN gctUINT32 * Handle
2357 )
2358{
2359 gceSTATUS status;
2360 gckVIDMEM_NODE node = gcvNULL;
2361 gctPOINTER pointer = gcvNULL;
2362 gctUINT32 handle = 0;
2363 gckOS os = Kernel->os;
2364
2365 gcmkHEADER_ARG("Kernel=0x%X VideoNode=0x%X", Kernel, VideoNode);
2366
2367 /* Construct a node. */
2368 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcsVIDMEM_NODE), &pointer));
2369
2370 gcmkVERIFY_OK(gckOS_ZeroMemory(pointer, gcmSIZEOF(gcsVIDMEM_NODE)));
2371
2372 node = pointer;
2373
2374 node->node = VideoNode;
2375 node->type = Type;
2376 node->pool = Pool;
2377
2378#if gcdPROCESS_ADDRESS_SPACE
2379 gcmkONERROR(gckOS_CreateMutex(os, &node->mapMutex));
2380#endif
2381
2382 gcmkONERROR(gckOS_AtomConstruct(os, &node->reference));
2383
2384 gcmkONERROR(gckOS_CreateMutex(os, &node->mutex));
2385
2386 /* Reference is 1 by default . */
2387 gckVIDMEM_NODE_Reference(Kernel, node);
2388
2389 /* Create a handle to represent this node. */
2390 gcmkONERROR(gckVIDMEM_HANDLE_Allocate(Kernel, node, &handle));
2391
2392 *Handle = handle;
2393
2394 gcmkFOOTER_ARG("*Handle=%d", *Handle);
2395 return gcvSTATUS_OK;
2396
2397OnError:
2398 if (node != gcvNULL)
2399 {
2400#if gcdPROCESS_ADDRESS_SPACE
2401 if (node->mapMutex != gcvNULL)
2402 {
2403 gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->mapMutex));
2404 }
2405#endif
2406
2407 if (node->mutex)
2408 {
2409 gcmkVERIFY_OK(gckOS_DeleteMutex(os, node->mutex));
2410 }
2411
2412 if (node->reference != gcvNULL)
2413 {
2414 gcmkVERIFY_OK(gckOS_AtomDestroy(os, node->reference));
2415 }
2416
2417 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
2418 }
2419
2420 gcmkFOOTER();
2421 return status;
2422}
2423
2424gceSTATUS
2425gckVIDMEM_NODE_Dereference(
2426 IN gckKERNEL Kernel,
2427 IN gckVIDMEM_NODE Node
2428 )
2429{
2430 gctINT32 oldValue = 0;
2431 gctPOINTER database = Kernel->db->nameDatabase;
2432 gctPOINTER mutex = Kernel->db->nameDatabaseMutex;
2433
2434 gcmkHEADER_ARG("Kernel=0x%X Node=0x%X", Kernel, Node);
2435
2436 gcmkVERIFY_OK(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
2437
2438 gcmkVERIFY_OK(gckOS_AtomDecrement(Kernel->os, Node->reference, &oldValue));
2439
2440 if (oldValue == 1 && Node->name)
2441 {
2442 /* Free name if exists. */
2443 gcmkVERIFY_OK(gckKERNEL_FreeIntegerId(database, Node->name));
2444 }
2445
2446 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2447
2448 if (oldValue == 1)
2449 {
2450 /* Free gcuVIDMEM_NODE. */
2451 gcmkVERIFY_OK(gckVIDMEM_Free(Kernel, Node->node));
2452 gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Node->reference));
2453#if gcdPROCESS_ADDRESS_SPACE
2454 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mapMutex));
2455#endif
2456 gcmkVERIFY_OK(gckOS_DeleteMutex(Kernel->os, Node->mutex));
2457 gcmkOS_SAFE_FREE(Kernel->os, Node);
2458 }
2459
2460 gcmkFOOTER_NO();
2461 return gcvSTATUS_OK;
2462}
2463
2464/*******************************************************************************
2465**
2466** gckVIDMEM_NODE_Name
2467**
2468** Naming a gckVIDMEM_NODE object.
2469**
2470** INPUT:
2471**
2472** gckKERNEL Kernel
2473** Pointer to an gckKERNEL object.
2474**
2475** gctUINT32 Handle
2476** Handle to a gckVIDMEM_NODE object.
2477**
2478** OUTPUT:
2479**
2480** gctUINT32 * Name
2481** Pointer to a variable receiving a name which can be pass to another
2482** process.
2483*/
2484gceSTATUS
2485gckVIDMEM_NODE_Name(
2486 IN gckKERNEL Kernel,
2487 IN gctUINT32 Handle,
2488 IN gctUINT32 * Name
2489 )
2490{
2491 gceSTATUS status;
2492 gckVIDMEM_NODE node = gcvNULL;
2493 gctUINT32 name = 0;
2494 gctUINT32 processID = 0;
2495 gctPOINTER database = Kernel->db->nameDatabase;
2496 gctPOINTER mutex = Kernel->db->nameDatabaseMutex;
2497 gctBOOL acquired = gcvFALSE;
2498 gctBOOL referenced = gcvFALSE;
2499 gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
2500
2501 gcmkONERROR(gckOS_GetProcessID(&processID));
2502
2503 gcmkONERROR(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
2504 acquired = gcvTRUE;
2505
2506 gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
2507 referenced = gcvTRUE;
2508
2509 if (node->name == 0)
2510 {
2511 /* Name this node. */
2512 gcmkONERROR(gckKERNEL_AllocateIntegerId(database, node, &name));
2513 node->name = name;
2514 }
2515
2516 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2517 acquired = gcvFALSE;
2518
2519 gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
2520
2521 if(node)
2522 {
2523 *Name = node->name;
2524 }
2525
2526 gcmkFOOTER_ARG("*Name=%d", *Name);
2527 return gcvSTATUS_OK;
2528
2529OnError:
2530 if (referenced)
2531 {
2532 gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
2533 }
2534
2535 if (acquired)
2536 {
2537 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2538 }
2539
2540 gcmkFOOTER();
2541 return status;
2542}
2543
2544/*******************************************************************************
2545**
2546** gckVIDMEM_NODE_Import
2547**
2548** Import a gckVIDMEM_NODE object.
2549**
2550** INPUT:
2551**
2552** gckKERNEL Kernel
2553** Pointer to an gckKERNEL object.
2554**
2555** gctUINT32 Name
2556** Name of a gckVIDMEM_NODE object.
2557**
2558** OUTPUT:
2559**
2560** gctUINT32 * Handle
2561** Pointer to a variable receiving a handle represent this
2562** gckVIDMEM_NODE in userspace.
2563*/
2564gceSTATUS
2565gckVIDMEM_NODE_Import(
2566 IN gckKERNEL Kernel,
2567 IN gctUINT32 Name,
2568 IN gctUINT32 * Handle
2569 )
2570{
2571 gceSTATUS status;
2572 gckVIDMEM_NODE node = gcvNULL;
2573 gctPOINTER database = Kernel->db->nameDatabase;
2574 gctPOINTER mutex = Kernel->db->nameDatabaseMutex;
2575 gctBOOL acquired = gcvFALSE;
2576 gctBOOL referenced = gcvFALSE;
2577
2578 gcmkHEADER_ARG("Kernel=0x%X Name=%d", Kernel, Name);
2579
2580 gcmkONERROR(gckOS_AcquireMutex(Kernel->os, mutex, gcvINFINITE));
2581 acquired = gcvTRUE;
2582
2583 /* Lookup in database to get the node. */
2584 gcmkONERROR(gckKERNEL_QueryIntegerId(database, Name, (gctPOINTER *)&node));
2585
2586 /* Reference the node. */
2587 gcmkONERROR(gckVIDMEM_NODE_Reference(Kernel, node));
2588 referenced = gcvTRUE;
2589
2590 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2591 acquired = gcvFALSE;
2592
2593 /* Allocate a handle for current process. */
2594 gcmkONERROR(gckVIDMEM_HANDLE_Allocate(Kernel, node, Handle));
2595
2596 gcmkFOOTER_ARG("*Handle=%d", *Handle);
2597 return gcvSTATUS_OK;
2598
2599OnError:
2600 if (referenced)
2601 {
2602 gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
2603 }
2604
2605 if (acquired)
2606 {
2607 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, mutex));
2608 }
2609
2610 gcmkFOOTER();
2611 return status;
2612}
2613
2614
2615typedef struct _gcsVIDMEM_NODE_FDPRIVATE
2616{
2617 gcsFDPRIVATE base;
2618 gckKERNEL kernel;
2619 gckVIDMEM_NODE node;
2620}
2621gcsVIDMEM_NODE_FDPRIVATE;
2622
2623
2624static gctINT
2625_ReleaseFdPrivate(
2626 gcsFDPRIVATE_PTR FdPrivate
2627 )
2628{
2629 /* Cast private info. */
2630 gcsVIDMEM_NODE_FDPRIVATE * private = (gcsVIDMEM_NODE_FDPRIVATE *) FdPrivate;
2631
2632 gckVIDMEM_NODE_Dereference(private->kernel, private->node);
2633 gckOS_Free(private->kernel->os, private);
2634
2635 return 0;
2636}
2637
2638/*******************************************************************************
2639**
2640** gckVIDMEM_NODE_GetFd
2641**
2642** Attach a gckVIDMEM_NODE object to a native fd.
2643**
2644** INPUT:
2645**
2646** gckKERNEL Kernel
2647** Pointer to an gckKERNEL object.
2648**
2649** gctUINT32 Handle
2650** Handle to a gckVIDMEM_NODE object.
2651**
2652** OUTPUT:
2653**
2654** gctUINT32 * Fd
2655** Pointer to a variable receiving a native fd from os.
2656*/
2657gceSTATUS
2658gckVIDMEM_NODE_GetFd(
2659 IN gckKERNEL Kernel,
2660 IN gctUINT32 Handle,
2661 OUT gctINT * Fd
2662 )
2663{
2664 gceSTATUS status;
2665 gckVIDMEM_NODE node = gcvNULL;
2666 gctBOOL referenced = gcvFALSE;
2667 gcsVIDMEM_NODE_FDPRIVATE * fdPrivate = gcvNULL;
2668 gcmkHEADER_ARG("Kernel=0x%X Handle=%d", Kernel, Handle);
2669
2670 /* Query and reference handle. */
2671 gcmkONERROR(gckVIDMEM_HANDLE_LookupAndReference(Kernel, Handle, &node));
2672 referenced = gcvTRUE;
2673
2674 /* Allocate memory for private info. */
2675 gcmkONERROR(gckOS_Allocate(
2676 Kernel->os,
2677 gcmSIZEOF(gcsVIDMEM_NODE_FDPRIVATE),
2678 (gctPOINTER *)&fdPrivate
2679 ));
2680
2681 fdPrivate->base.release = _ReleaseFdPrivate;
2682 fdPrivate->kernel = Kernel;
2683 fdPrivate->node = node;
2684
2685 /* Allocated fd owns a reference. */
2686 gcmkONERROR(gckOS_GetFd("vidmem", &fdPrivate->base, Fd));
2687
2688 gcmkFOOTER_ARG("*Fd=%d", *Fd);
2689 return gcvSTATUS_OK;
2690
2691OnError:
2692 if (referenced)
2693 {
2694 gcmkVERIFY_OK(gckVIDMEM_NODE_Dereference(Kernel, node));
2695 }
2696
2697 if (fdPrivate)
2698 {
2699 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, fdPrivate));
2700 }
2701
2702 gcmkFOOTER();
2703 return status;
2704}
2705
2706gceSTATUS
2707gckVIDMEM_ConstructVirtualFromUserMemory(
2708 IN gckKERNEL Kernel,
2709 IN gcsUSER_MEMORY_DESC_PTR Desc,
2710 OUT gcuVIDMEM_NODE_PTR * Node
2711 )
2712{
2713 gckOS os;
2714 gceSTATUS status;
2715 gcuVIDMEM_NODE_PTR node = gcvNULL;
2716 gctPOINTER pointer = gcvNULL;
2717
2718 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
2719
2720 /* Verify the arguments. */
2721 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
2722 gcmkVERIFY_ARGUMENT(Node != gcvNULL);
2723
2724 /* Extract the gckOS object pointer. */
2725 os = Kernel->os;
2726 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
2727
2728 /* Allocate an gcuVIDMEM_NODE union. */
2729 gcmkONERROR(gckOS_Allocate(os, gcmSIZEOF(gcuVIDMEM_NODE), &pointer));
2730
2731 gckOS_ZeroMemory(pointer, gcmSIZEOF(gcuVIDMEM_NODE));
2732
2733 node = pointer;
2734
2735 /* Initialize gcuVIDMEM_NODE union for virtual memory. */
2736 node->Virtual.kernel = Kernel;
2737 node->Virtual.contiguous = gcvFALSE;
2738
2739 /* Wrap Memory. */
2740 gcmkONERROR(gckOS_WrapMemory(
2741 os, Desc, &node->Virtual.bytes, &node->Virtual.physical));
2742
2743 /* Return pointer to the gcuVIDMEM_NODE union. */
2744 *Node = node;
2745
2746 /* Success. */
2747 gcmkFOOTER_ARG("*Node=0x%x", *Node);
2748 return gcvSTATUS_OK;
2749
2750OnError:
2751 /* Roll back. */
2752 if (node != gcvNULL)
2753 {
2754 /* Free the structure. */
2755 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(os, node));
2756 }
2757
2758 /* Return the status. */
2759 gcmkFOOTER();
2760 return status;
2761}
diff --git a/src/hal/kernel/inc/gc_hal.h b/src/hal/kernel/inc/gc_hal.h
new file mode 100755
index 0000000..6a44f1b
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal.h
@@ -0,0 +1,2767 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_h_
57#define __gc_hal_h_
58
59#include "gc_hal_rename.h"
60#include "gc_hal_types.h"
61#include "gc_hal_enum.h"
62#include "gc_hal_base.h"
63#include "gc_hal_profiler.h"
64#include "gc_hal_driver.h"
65
66
67#ifdef __cplusplus
68extern "C" {
69#endif
70
71/******************************************************************************\
72******************************* Alignment Macros *******************************
73\******************************************************************************/
74
75/* Alignment with a non-power of two value. */
76#define gcmALIGN_NP2(n, align) \
77( \
78 ((n) + (align) - 1) - (((n) + (align) - 1) % (align)) \
79)
80
81/* Alignment with a power of two value. */
82#define gcmALIGN(n, align) \
83( \
84 ((n) + ((align) - 1)) & ~((align) - 1) \
85)
86
87#define gcmALIGN_BASE(n, align) \
88( \
89 ((n) & ~((align) - 1)) \
90)
91
92/******************************************************************************\
93***************************** Element Count Macro *****************************
94\******************************************************************************/
95
96#define gcmSIZEOF(a) \
97( \
98 (gctSIZE_T) (sizeof(a)) \
99)
100
101#define gcmCOUNTOF(a) \
102( \
103 sizeof(a) / sizeof(a[0]) \
104)
105
106/******************************************************************************\
107********************************* Cast Macro **********************************
108\******************************************************************************/
109#define gcmNAME_TO_PTR(na) \
110 gckKERNEL_QueryPointerFromName(kernel, gcmALL_TO_UINT32(na))
111
112#define gcmPTR_TO_NAME(ptr) \
113 gckKERNEL_AllocateNameFromPointer(kernel, ptr)
114
115#define gcmRELEASE_NAME(na) \
116 gckKERNEL_DeleteName(kernel, gcmALL_TO_UINT32(na))
117
118#define gcmALL_TO_UINT32(t) \
119( \
120 (gctUINT32) (gctUINTPTR_T) (t)\
121)
122
123#define gcmPTR_TO_UINT64(p) \
124( \
125 (gctUINT64) (gctUINTPTR_T) (p)\
126)
127
128#define gcmUINT64_TO_PTR(u) \
129( \
130 (gctPOINTER) (gctUINTPTR_T) (u)\
131)
132
133#define gcmUINT64_TO_TYPE(u, t) \
134( \
135 (t) (gctUINTPTR_T) (u)\
136)
137
138/******************************************************************************\
139******************************** Useful Macro *********************************
140\******************************************************************************/
141
142#define gcvINVALID_ADDRESS ~0U
143
144#define gcmGET_PRE_ROTATION(rotate) \
145 ((rotate) & (~(gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y)))
146
147#define gcmGET_POST_ROTATION(rotate) \
148 ((rotate) & (gcvSURF_POST_FLIP_X | gcvSURF_POST_FLIP_Y))
149
150/******************************************************************************\
151******************************** gcsOBJECT Object *******************************
152\******************************************************************************/
153
154/* Type of objects. */
155typedef enum _gceOBJECT_TYPE
156{
157 gcvOBJ_UNKNOWN = 0,
158 gcvOBJ_2D = gcmCC('2','D',' ',' '),
159 gcvOBJ_3D = gcmCC('3','D',' ',' '),
160 gcvOBJ_ATTRIBUTE = gcmCC('A','T','T','R'),
161 gcvOBJ_BRUSHCACHE = gcmCC('B','R','U','$'),
162 gcvOBJ_BRUSHNODE = gcmCC('B','R','U','n'),
163 gcvOBJ_BRUSH = gcmCC('B','R','U','o'),
164 gcvOBJ_BUFFER = gcmCC('B','U','F','R'),
165 gcvOBJ_COMMAND = gcmCC('C','M','D',' '),
166 gcvOBJ_COMMANDBUFFER = gcmCC('C','M','D','B'),
167 gcvOBJ_CONTEXT = gcmCC('C','T','X','T'),
168 gcvOBJ_DEVICE = gcmCC('D','E','V',' '),
169 gcvOBJ_DUMP = gcmCC('D','U','M','P'),
170 gcvOBJ_EVENT = gcmCC('E','V','N','T'),
171 gcvOBJ_FUNCTION = gcmCC('F','U','N','C'),
172 gcvOBJ_HAL = gcmCC('H','A','L',' '),
173 gcvOBJ_HARDWARE = gcmCC('H','A','R','D'),
174 gcvOBJ_HEAP = gcmCC('H','E','A','P'),
175 gcvOBJ_INDEX = gcmCC('I','N','D','X'),
176 gcvOBJ_INTERRUPT = gcmCC('I','N','T','R'),
177 gcvOBJ_KERNEL = gcmCC('K','E','R','N'),
178 gcvOBJ_KERNEL_FUNCTION = gcmCC('K','F','C','N'),
179 gcvOBJ_MEMORYBUFFER = gcmCC('M','E','M','B'),
180 gcvOBJ_MMU = gcmCC('M','M','U',' '),
181 gcvOBJ_OS = gcmCC('O','S',' ',' '),
182 gcvOBJ_OUTPUT = gcmCC('O','U','T','P'),
183 gcvOBJ_PAINT = gcmCC('P','N','T',' '),
184 gcvOBJ_PATH = gcmCC('P','A','T','H'),
185 gcvOBJ_QUEUE = gcmCC('Q','U','E',' '),
186 gcvOBJ_SAMPLER = gcmCC('S','A','M','P'),
187 gcvOBJ_SHADER = gcmCC('S','H','D','R'),
188 gcvOBJ_STREAM = gcmCC('S','T','R','M'),
189 gcvOBJ_SURF = gcmCC('S','U','R','F'),
190 gcvOBJ_TEXTURE = gcmCC('T','X','T','R'),
191 gcvOBJ_UNIFORM = gcmCC('U','N','I','F'),
192 gcvOBJ_VARIABLE = gcmCC('V','A','R','I'),
193 gcvOBJ_VERTEX = gcmCC('V','R','T','X'),
194 gcvOBJ_VIDMEM = gcmCC('V','M','E','M'),
195 gcvOBJ_VG = gcmCC('V','G',' ',' '),
196 gcvOBJ_BUFOBJ = gcmCC('B','U','F','O'),
197 gcvOBJ_UNIFORM_BLOCK = gcmCC('U','B','L','K'),
198 gcvOBJ_CL = gcmCC('C','L',' ',' '),
199}
200gceOBJECT_TYPE;
201
202/* gcsOBJECT object defintinon. */
203typedef struct _gcsOBJECT
204{
205 /* Type of an object. */
206 gceOBJECT_TYPE type;
207}
208gcsOBJECT;
209
210typedef struct _gckHARDWARE * gckHARDWARE;
211
212/* CORE flags. */
213typedef enum _gceCORE
214{
215 gcvCORE_MAJOR = 0x0,
216 gcvCORE_2D = 0x1,
217 gcvCORE_VG = 0x2,
218#if gcdMULTI_GPU_AFFINITY
219 gcvCORE_OCL = 0x3,
220#endif
221#if gcdENABLE_DEC_COMPRESSION
222 gcvCORE_DEC = 0x4,
223#endif
224 gcvCORE_COUNT
225}
226gceCORE;
227
228#define gcdMAX_GPU_COUNT gcvCORE_COUNT
229
230#define gcdMAX_SURF_LAYERS 4
231
232#define gcdMAX_DRAW_BUFFERS 8
233
234/*******************************************************************************
235**
236** gcmVERIFY_OBJECT
237**
238** Assert if an object is invalid or is not of the specified type. If the
239** object is invalid or not of the specified type, gcvSTATUS_INVALID_OBJECT
240** will be returned from the current function. In retail mode this macro
241** does nothing.
242**
243** ARGUMENTS:
244**
245** obj Object to test.
246** t Expected type of the object.
247*/
248#if gcmIS_DEBUG(gcdDEBUG_TRACE)
249#define _gcmVERIFY_OBJECT(prefix, obj, t) \
250 if ((obj) == gcvNULL) \
251 { \
252 prefix##TRACE(gcvLEVEL_ERROR, \
253 #prefix "VERIFY_OBJECT failed: NULL"); \
254 prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
255 gcmCC_PRINT(t)); \
256 prefix##ASSERT((obj) != gcvNULL); \
257 prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
258 return gcvSTATUS_INVALID_OBJECT; \
259 } \
260 else if (((gcsOBJECT*) (obj))->type != t) \
261 { \
262 prefix##TRACE(gcvLEVEL_ERROR, \
263 #prefix "VERIFY_OBJECT failed: %c%c%c%c", \
264 gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
265 prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
266 gcmCC_PRINT(t)); \
267 prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
268 prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_OBJECT); \
269 return gcvSTATUS_INVALID_OBJECT; \
270 }
271
272# define gcmVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcm, obj, t)
273# define gcmkVERIFY_OBJECT(obj, t) _gcmVERIFY_OBJECT(gcmk, obj, t)
274#else
275# define gcmVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
276# define gcmkVERIFY_OBJECT(obj, t) do {} while (gcvFALSE)
277#endif
278
279/******************************************************************************/
280/*VERIFY_OBJECT if special return expected*/
281/******************************************************************************/
282#ifndef EGL_API_ANDROID
283# define _gcmVERIFY_OBJECT_RETURN(prefix, obj, t, retVal) \
284 do \
285 { \
286 if ((obj) == gcvNULL) \
287 { \
288 prefix##PRINT_VERSION(); \
289 prefix##TRACE(gcvLEVEL_ERROR, \
290 #prefix "VERIFY_OBJECT_RETURN failed: NULL"); \
291 prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
292 gcmCC_PRINT(t)); \
293 prefix##ASSERT((obj) != gcvNULL); \
294 prefix##FOOTER_ARG("retVal=%d", retVal); \
295 return retVal; \
296 } \
297 else if (((gcsOBJECT*) (obj))->type != t) \
298 { \
299 prefix##PRINT_VERSION(); \
300 prefix##TRACE(gcvLEVEL_ERROR, \
301 #prefix "VERIFY_OBJECT_RETURN failed: %c%c%c%c", \
302 gcmCC_PRINT(((gcsOBJECT*) (obj))->type)); \
303 prefix##TRACE(gcvLEVEL_ERROR, " expected: %c%c%c%c", \
304 gcmCC_PRINT(t)); \
305 prefix##ASSERT(((gcsOBJECT*)(obj))->type == t); \
306 prefix##FOOTER_ARG("retVal=%d", retVal); \
307 return retVal; \
308 } \
309 } \
310 while (gcvFALSE)
311# define gcmVERIFY_OBJECT_RETURN(obj, t, retVal) \
312 _gcmVERIFY_OBJECT_RETURN(gcm, obj, t, retVal)
313# define gcmkVERIFY_OBJECT_RETURN(obj, t, retVal) \
314 _gcmVERIFY_OBJECT_RETURN(gcmk, obj, t, retVal)
315#else
316# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
317# define gcmVERIFY_OBJECT_RETURN(obj, t) do {} while (gcvFALSE)
318#endif
319
320/******************************************************************************\
321********************************** gckOS Object *********************************
322\******************************************************************************/
323
324/* Construct a new gckOS object. */
325gceSTATUS
326gckOS_Construct(
327 IN gctPOINTER Context,
328 OUT gckOS * Os
329 );
330
331/* Destroy an gckOS object. */
332gceSTATUS
333gckOS_Destroy(
334 IN gckOS Os
335 );
336
337/* Query the video memory. */
338gceSTATUS
339gckOS_QueryVideoMemory(
340 IN gckOS Os,
341 OUT gctPHYS_ADDR * InternalAddress,
342 OUT gctSIZE_T * InternalSize,
343 OUT gctPHYS_ADDR * ExternalAddress,
344 OUT gctSIZE_T * ExternalSize,
345 OUT gctPHYS_ADDR * ContiguousAddress,
346 OUT gctSIZE_T * ContiguousSize
347 );
348
349/* Allocate memory from the heap. */
350gceSTATUS
351gckOS_Allocate(
352 IN gckOS Os,
353 IN gctSIZE_T Bytes,
354 OUT gctPOINTER * Memory
355 );
356
357/* Free allocated memory. */
358gceSTATUS
359gckOS_Free(
360 IN gckOS Os,
361 IN gctPOINTER Memory
362 );
363
364/* Wrapper for allocation memory.. */
365gceSTATUS
366gckOS_AllocateMemory(
367 IN gckOS Os,
368 IN gctSIZE_T Bytes,
369 OUT gctPOINTER * Memory
370 );
371
372/* Wrapper for freeing memory. */
373gceSTATUS
374gckOS_FreeMemory(
375 IN gckOS Os,
376 IN gctPOINTER Memory
377 );
378
379/* Allocate paged memory. */
380gceSTATUS
381gckOS_AllocatePagedMemory(
382 IN gckOS Os,
383 IN gctSIZE_T Bytes,
384 OUT gctPHYS_ADDR * Physical
385 );
386
387/* Allocate paged memory. */
388gceSTATUS
389gckOS_AllocatePagedMemoryEx(
390 IN gckOS Os,
391 IN gctUINT32 Flag,
392 IN gctSIZE_T Bytes,
393 OUT gctUINT32 * Gid,
394 OUT gctPHYS_ADDR * Physical
395 );
396
397/* Lock pages. */
398gceSTATUS
399gckOS_LockPages(
400 IN gckOS Os,
401 IN gctPHYS_ADDR Physical,
402 IN gctSIZE_T Bytes,
403 IN gctBOOL Cacheable,
404 OUT gctPOINTER * Logical,
405 OUT gctSIZE_T * PageCount
406 );
407
408/* Map pages. */
409gceSTATUS
410gckOS_MapPages(
411 IN gckOS Os,
412 IN gctPHYS_ADDR Physical,
413 IN gctSIZE_T PageCount,
414 IN gctPOINTER PageTable
415 );
416
417/* Map pages. */
418gceSTATUS
419gckOS_MapPagesEx(
420 IN gckOS Os,
421 IN gceCORE Core,
422 IN gctPHYS_ADDR Physical,
423 IN gctSIZE_T PageCount,
424 IN gctUINT32 Address,
425 IN gctPOINTER PageTable
426 );
427
428gceSTATUS
429gckOS_UnmapPages(
430 IN gckOS Os,
431 IN gctSIZE_T PageCount,
432 IN gctUINT32 Address
433 );
434
435/* Unlock pages. */
436gceSTATUS
437gckOS_UnlockPages(
438 IN gckOS Os,
439 IN gctPHYS_ADDR Physical,
440 IN gctSIZE_T Bytes,
441 IN gctPOINTER Logical
442 );
443
444/* Free paged memory. */
445gceSTATUS
446gckOS_FreePagedMemory(
447 IN gckOS Os,
448 IN gctPHYS_ADDR Physical,
449 IN gctSIZE_T Bytes
450 );
451
452/* Allocate non-paged memory. */
453gceSTATUS
454gckOS_AllocateNonPagedMemory(
455 IN gckOS Os,
456 IN gctBOOL InUserSpace,
457 IN OUT gctSIZE_T * Bytes,
458 OUT gctPHYS_ADDR * Physical,
459 OUT gctPOINTER * Logical
460 );
461
462/* Free non-paged memory. */
463gceSTATUS
464gckOS_FreeNonPagedMemory(
465 IN gckOS Os,
466 IN gctSIZE_T Bytes,
467 IN gctPHYS_ADDR Physical,
468 IN gctPOINTER Logical
469 );
470
471/* Allocate contiguous memory. */
472gceSTATUS
473gckOS_AllocateContiguous(
474 IN gckOS Os,
475 IN gctBOOL InUserSpace,
476 IN OUT gctSIZE_T * Bytes,
477 OUT gctPHYS_ADDR * Physical,
478 OUT gctPOINTER * Logical
479 );
480
481/* Free contiguous memory. */
482gceSTATUS
483gckOS_FreeContiguous(
484 IN gckOS Os,
485 IN gctPHYS_ADDR Physical,
486 IN gctPOINTER Logical,
487 IN gctSIZE_T Bytes
488 );
489
490/* Get the number fo bytes per page. */
491gceSTATUS
492gckOS_GetPageSize(
493 IN gckOS Os,
494 OUT gctSIZE_T * PageSize
495 );
496
497/* Get the physical address of a corresponding logical address. */
498gceSTATUS
499gckOS_GetPhysicalAddress(
500 IN gckOS Os,
501 IN gctPOINTER Logical,
502 OUT gctPHYS_ADDR_T * Address
503 );
504
505/* Get the physical address of a corresponding user logical address. */
506gceSTATUS
507gckOS_UserLogicalToPhysical(
508 IN gckOS Os,
509 IN gctPOINTER Logical,
510 OUT gctUINT64 * Address
511 );
512
513/* Map physical memory. */
514gceSTATUS
515gckOS_MapPhysical(
516 IN gckOS Os,
517 IN gctUINT32 Physical,
518 IN gctSIZE_T Bytes,
519 OUT gctPOINTER * Logical
520 );
521
522/* Unmap previously mapped physical memory. */
523gceSTATUS
524gckOS_UnmapPhysical(
525 IN gckOS Os,
526 IN gctPOINTER Logical,
527 IN gctSIZE_T Bytes
528 );
529
530/* Get real physical address from descriptor. */
531gceSTATUS
532gckOS_PhysicalToPhysicalAddress(
533 IN gckOS Os,
534 IN gctPOINTER Physical,
535 OUT gctPHYS_ADDR_T * PhysicalAddress
536 );
537
538/* Read data from a hardware register. */
539gceSTATUS
540gckOS_ReadRegister(
541 IN gckOS Os,
542 IN gctUINT32 Address,
543 OUT gctUINT32 * Data
544 );
545
546/* Read data from a hardware register. */
547gceSTATUS
548gckOS_ReadRegisterEx(
549 IN gckOS Os,
550 IN gceCORE Core,
551 IN gctUINT32 Address,
552 OUT gctUINT32 * Data
553 );
554
555/* Write data to a hardware register. */
556gceSTATUS
557gckOS_WriteRegister(
558 IN gckOS Os,
559 IN gctUINT32 Address,
560 IN gctUINT32 Data
561 );
562
563/* Write data to a hardware register. */
564gceSTATUS
565gckOS_WriteRegisterEx(
566 IN gckOS Os,
567 IN gceCORE Core,
568 IN gctUINT32 Address,
569 IN gctUINT32 Data
570 );
571
572
573/* Write data to a 32-bit memory location. */
574gceSTATUS
575gckOS_WriteMemory(
576 IN gckOS Os,
577 IN gctPOINTER Address,
578 IN gctUINT32 Data
579 );
580
581/* Map physical memory into the process space. */
582gceSTATUS
583gckOS_MapMemory(
584 IN gckOS Os,
585 IN gctPHYS_ADDR Physical,
586 IN gctSIZE_T Bytes,
587 OUT gctPOINTER * Logical
588 );
589
590/* Unmap physical memory from the specified process space. */
591gceSTATUS
592gckOS_UnmapMemoryEx(
593 IN gckOS Os,
594 IN gctPHYS_ADDR Physical,
595 IN gctSIZE_T Bytes,
596 IN gctPOINTER Logical,
597 IN gctUINT32 PID
598 );
599
600/* Unmap physical memory from the process space. */
601gceSTATUS
602gckOS_UnmapMemory(
603 IN gckOS Os,
604 IN gctPHYS_ADDR Physical,
605 IN gctSIZE_T Bytes,
606 IN gctPOINTER Logical
607 );
608
609/* Unmap user logical memory out of physical memory.
610 * This function is only supported in Linux currently.
611 */
612gceSTATUS
613gckOS_UnmapUserLogical(
614 IN gckOS Os,
615 IN gctPHYS_ADDR Physical,
616 IN gctSIZE_T Bytes,
617 IN gctPOINTER Logical
618 );
619
620/* Delete a mutex. */
621gceSTATUS
622gckOS_DeleteMutex(
623 IN gckOS Os,
624 IN gctPOINTER Mutex
625 );
626
627/* Acquire a mutex. */
628gceSTATUS
629gckOS_AcquireMutex(
630 IN gckOS Os,
631 IN gctPOINTER Mutex,
632 IN gctUINT32 Timeout
633 );
634
635/* Release a mutex. */
636gceSTATUS
637gckOS_ReleaseMutex(
638 IN gckOS Os,
639 IN gctPOINTER Mutex
640 );
641
642/* Atomically exchange a pair of 32-bit values. */
643gceSTATUS
644gckOS_AtomicExchange(
645 IN gckOS Os,
646 IN OUT gctUINT32_PTR Target,
647 IN gctUINT32 NewValue,
648 OUT gctUINT32_PTR OldValue
649 );
650
651/* Atomically exchange a pair of pointers. */
652gceSTATUS
653gckOS_AtomicExchangePtr(
654 IN gckOS Os,
655 IN OUT gctPOINTER * Target,
656 IN gctPOINTER NewValue,
657 OUT gctPOINTER * OldValue
658 );
659
660gceSTATUS
661gckOS_AtomSetMask(
662 IN gctPOINTER Atom,
663 IN gctUINT32 Mask
664 );
665
666gceSTATUS
667gckOS_AtomClearMask(
668 IN gctPOINTER Atom,
669 IN gctUINT32 Mask
670 );
671
672gceSTATUS
673gckOS_DumpCallStack(
674 IN gckOS Os
675 );
676
677gceSTATUS
678gckOS_GetProcessNameByPid(
679 IN gctINT Pid,
680 IN gctSIZE_T Length,
681 OUT gctUINT8_PTR String
682 );
683
684/*******************************************************************************
685**
686** gckOS_AtomConstruct
687**
688** Create an atom.
689**
690** INPUT:
691**
692** gckOS Os
693** Pointer to a gckOS object.
694**
695** OUTPUT:
696**
697** gctPOINTER * Atom
698** Pointer to a variable receiving the constructed atom.
699*/
700gceSTATUS
701gckOS_AtomConstruct(
702 IN gckOS Os,
703 OUT gctPOINTER * Atom
704 );
705
706/*******************************************************************************
707**
708** gckOS_AtomDestroy
709**
710** Destroy an atom.
711**
712** INPUT:
713**
714** gckOS Os
715** Pointer to a gckOS object.
716**
717** gctPOINTER Atom
718** Pointer to the atom to destroy.
719**
720** OUTPUT:
721**
722** Nothing.
723*/
724gceSTATUS
725gckOS_AtomDestroy(
726 IN gckOS Os,
727 OUT gctPOINTER Atom
728 );
729
730/*******************************************************************************
731**
732** gckOS_AtomGet
733**
734** Get the 32-bit value protected by an atom.
735**
736** INPUT:
737**
738** gckOS Os
739** Pointer to a gckOS object.
740**
741** gctPOINTER Atom
742** Pointer to the atom.
743**
744** OUTPUT:
745**
746** gctINT32_PTR Value
747** Pointer to a variable the receives the value of the atom.
748*/
749gceSTATUS
750gckOS_AtomGet(
751 IN gckOS Os,
752 IN gctPOINTER Atom,
753 OUT gctINT32_PTR Value
754 );
755
756/*******************************************************************************
757**
758** gckOS_AtomSet
759**
760** Set the 32-bit value protected by an atom.
761**
762** INPUT:
763**
764** gckOS Os
765** Pointer to a gckOS object.
766**
767** gctPOINTER Atom
768** Pointer to the atom.
769**
770** gctINT32 Value
771** The value of the atom.
772**
773** OUTPUT:
774**
775** Nothing.
776*/
777gceSTATUS
778gckOS_AtomSet(
779 IN gckOS Os,
780 IN gctPOINTER Atom,
781 IN gctINT32 Value
782 );
783
784/*******************************************************************************
785**
786** gckOS_AtomIncrement
787**
788** Atomically increment the 32-bit integer value inside an atom.
789**
790** INPUT:
791**
792** gckOS Os
793** Pointer to a gckOS object.
794**
795** gctPOINTER Atom
796** Pointer to the atom.
797**
798** OUTPUT:
799**
800** gctINT32_PTR Value
801** Pointer to a variable the receives the original value of the atom.
802*/
803gceSTATUS
804gckOS_AtomIncrement(
805 IN gckOS Os,
806 IN gctPOINTER Atom,
807 OUT gctINT32_PTR Value
808 );
809
810/*******************************************************************************
811**
812** gckOS_AtomDecrement
813**
814** Atomically decrement the 32-bit integer value inside an atom.
815**
816** INPUT:
817**
818** gckOS Os
819** Pointer to a gckOS object.
820**
821** gctPOINTER Atom
822** Pointer to the atom.
823**
824** OUTPUT:
825**
826** gctINT32_PTR Value
827** Pointer to a variable the receives the original value of the atom.
828*/
829gceSTATUS
830gckOS_AtomDecrement(
831 IN gckOS Os,
832 IN gctPOINTER Atom,
833 OUT gctINT32_PTR Value
834 );
835
836/* Delay a number of microseconds. */
837gceSTATUS
838gckOS_Delay(
839 IN gckOS Os,
840 IN gctUINT32 Delay
841 );
842
843/* Get time in milliseconds. */
844gceSTATUS
845gckOS_GetTicks(
846 OUT gctUINT32_PTR Time
847 );
848
849/* Compare time value. */
850gceSTATUS
851gckOS_TicksAfter(
852 IN gctUINT32 Time1,
853 IN gctUINT32 Time2,
854 OUT gctBOOL_PTR IsAfter
855 );
856
857/* Get time in microseconds. */
858gceSTATUS
859gckOS_GetTime(
860 OUT gctUINT64_PTR Time
861 );
862
863/* Memory barrier. */
864gceSTATUS
865gckOS_MemoryBarrier(
866 IN gckOS Os,
867 IN gctPOINTER Address
868 );
869
870/* Map user pointer. */
871gceSTATUS
872gckOS_MapUserPointer(
873 IN gckOS Os,
874 IN gctPOINTER Pointer,
875 IN gctSIZE_T Size,
876 OUT gctPOINTER * KernelPointer
877 );
878
879/* Unmap user pointer. */
880gceSTATUS
881gckOS_UnmapUserPointer(
882 IN gckOS Os,
883 IN gctPOINTER Pointer,
884 IN gctSIZE_T Size,
885 IN gctPOINTER KernelPointer
886 );
887
888/*******************************************************************************
889**
890** gckOS_QueryNeedCopy
891**
892** Query whether the memory can be accessed or mapped directly or it has to be
893** copied.
894**
895** INPUT:
896**
897** gckOS Os
898** Pointer to an gckOS object.
899**
900** gctUINT32 ProcessID
901** Process ID of the current process.
902**
903** OUTPUT:
904**
905** gctBOOL_PTR NeedCopy
906** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
907** gcvFALSE if the memory can be accessed or mapped dircetly.
908*/
909gceSTATUS
910gckOS_QueryNeedCopy(
911 IN gckOS Os,
912 IN gctUINT32 ProcessID,
913 OUT gctBOOL_PTR NeedCopy
914 );
915
916/*******************************************************************************
917**
918** gckOS_CopyFromUserData
919**
920** Copy data from user to kernel memory.
921**
922** INPUT:
923**
924** gckOS Os
925** Pointer to an gckOS object.
926**
927** gctPOINTER KernelPointer
928** Pointer to kernel memory.
929**
930** gctPOINTER Pointer
931** Pointer to user memory.
932**
933** gctSIZE_T Size
934** Number of bytes to copy.
935**
936** OUTPUT:
937**
938** Nothing.
939*/
940gceSTATUS
941gckOS_CopyFromUserData(
942 IN gckOS Os,
943 IN gctPOINTER KernelPointer,
944 IN gctPOINTER Pointer,
945 IN gctSIZE_T Size
946 );
947
948/*******************************************************************************
949**
950** gckOS_CopyToUserData
951**
952** Copy data from kernel to user memory.
953**
954** INPUT:
955**
956** gckOS Os
957** Pointer to an gckOS object.
958**
959** gctPOINTER KernelPointer
960** Pointer to kernel memory.
961**
962** gctPOINTER Pointer
963** Pointer to user memory.
964**
965** gctSIZE_T Size
966** Number of bytes to copy.
967**
968** OUTPUT:
969**
970** Nothing.
971*/
972gceSTATUS
973gckOS_CopyToUserData(
974 IN gckOS Os,
975 IN gctPOINTER KernelPointer,
976 IN gctPOINTER Pointer,
977 IN gctSIZE_T Size
978 );
979
980gceSTATUS
981gckOS_SuspendInterrupt(
982 IN gckOS Os
983 );
984
985gceSTATUS
986gckOS_SuspendInterruptEx(
987 IN gckOS Os,
988 IN gceCORE Core
989 );
990
991gceSTATUS
992gckOS_ResumeInterrupt(
993 IN gckOS Os
994 );
995
996gceSTATUS
997gckOS_ResumeInterruptEx(
998 IN gckOS Os,
999 IN gceCORE Core
1000 );
1001
1002/* Get the base address for the physical memory. */
1003gceSTATUS
1004gckOS_GetBaseAddress(
1005 IN gckOS Os,
1006 OUT gctUINT32_PTR BaseAddress
1007 );
1008
1009/* Perform a memory copy. */
1010gceSTATUS
1011gckOS_MemCopy(
1012 IN gctPOINTER Destination,
1013 IN gctCONST_POINTER Source,
1014 IN gctSIZE_T Bytes
1015 );
1016
1017/* Zero memory. */
1018gceSTATUS
1019gckOS_ZeroMemory(
1020 IN gctPOINTER Memory,
1021 IN gctSIZE_T Bytes
1022 );
1023
1024/* Device I/O control to the kernel HAL layer. */
1025gceSTATUS
1026gckOS_DeviceControl(
1027 IN gckOS Os,
1028 IN gctBOOL FromUser,
1029 IN gctUINT32 IoControlCode,
1030 IN gctPOINTER InputBuffer,
1031 IN gctSIZE_T InputBufferSize,
1032 OUT gctPOINTER OutputBuffer,
1033 IN gctSIZE_T OutputBufferSize
1034 );
1035
1036/*******************************************************************************
1037**
1038** gckOS_GetProcessID
1039**
1040** Get current process ID.
1041**
1042** INPUT:
1043**
1044** Nothing.
1045**
1046** OUTPUT:
1047**
1048** gctUINT32_PTR ProcessID
1049** Pointer to the variable that receives the process ID.
1050*/
1051gceSTATUS
1052gckOS_GetProcessID(
1053 OUT gctUINT32_PTR ProcessID
1054 );
1055
1056gceSTATUS
1057gckOS_GetCurrentProcessID(
1058 OUT gctUINT32_PTR ProcessID
1059 );
1060
1061/*******************************************************************************
1062**
1063** gckOS_GetThreadID
1064**
1065** Get current thread ID.
1066**
1067** INPUT:
1068**
1069** Nothing.
1070**
1071** OUTPUT:
1072**
1073** gctUINT32_PTR ThreadID
1074** Pointer to the variable that receives the thread ID.
1075*/
1076gceSTATUS
1077gckOS_GetThreadID(
1078 OUT gctUINT32_PTR ThreadID
1079 );
1080
1081
1082/******************************************************************************\
1083********************************** Signal Object *********************************
1084\******************************************************************************/
1085
1086/* Create a signal. */
1087gceSTATUS
1088gckOS_CreateSignal(
1089 IN gckOS Os,
1090 IN gctBOOL ManualReset,
1091 OUT gctSIGNAL * Signal
1092 );
1093
1094/* Destroy a signal. */
1095gceSTATUS
1096gckOS_DestroySignal(
1097 IN gckOS Os,
1098 IN gctSIGNAL Signal
1099 );
1100
1101/* Signal a signal. */
1102gceSTATUS
1103gckOS_Signal(
1104 IN gckOS Os,
1105 IN gctSIGNAL Signal,
1106 IN gctBOOL State
1107 );
1108
1109/* Wait for a signal. */
1110gceSTATUS
1111gckOS_WaitSignal(
1112 IN gckOS Os,
1113 IN gctSIGNAL Signal,
1114 IN gctUINT32 Wait
1115 );
1116
1117#ifdef __QNXNTO__
1118gceSTATUS
1119gckOS_SignalPulse(
1120 IN gckOS Os,
1121 IN gctSIGNAL Signal
1122 );
1123
1124gceSTATUS
1125gckOS_SignalPending(
1126 IN gckOS Os,
1127 IN gctSIGNAL Signal
1128 );
1129#endif
1130
1131/* Map a user signal to the kernel space. */
1132gceSTATUS
1133gckOS_MapSignal(
1134 IN gckOS Os,
1135 IN gctSIGNAL Signal,
1136 IN gctHANDLE Process,
1137 OUT gctSIGNAL * MappedSignal
1138 );
1139
1140/* Unmap a user signal */
1141gceSTATUS
1142gckOS_UnmapSignal(
1143 IN gckOS Os,
1144 IN gctSIGNAL Signal
1145 );
1146
1147/* Map user memory. */
1148gceSTATUS
1149gckOS_MapUserMemory(
1150 IN gckOS Os,
1151 IN gceCORE Core,
1152 IN gctPOINTER Memory,
1153 IN gctUINT32 Physical,
1154 IN gctSIZE_T Size,
1155 OUT gctPOINTER * Info,
1156 OUT gctUINT32_PTR Address
1157 );
1158
1159/* Unmap user memory. */
1160gceSTATUS
1161gckOS_UnmapUserMemory(
1162 IN gckOS Os,
1163 IN gceCORE Core,
1164 IN gctPOINTER Memory,
1165 IN gctSIZE_T Size,
1166 IN gctPOINTER Info,
1167 IN gctUINT32 Address
1168 );
1169
1170/* Wrap a user memory to gctPHYS_ADDR. */
1171gceSTATUS
1172gckOS_WrapMemory(
1173 IN gckOS Os,
1174 IN gcsUSER_MEMORY_DESC_PTR Desc,
1175 OUT gctSIZE_T *Bytes,
1176 OUT gctPHYS_ADDR * Physical
1177 );
1178
1179/******************************************************************************\
1180************************** Android Native Fence Sync ***************************
1181\******************************************************************************/
1182gceSTATUS
1183gckOS_CreateSyncTimeline(
1184 IN gckOS Os,
1185 OUT gctHANDLE * Timeline
1186 );
1187
1188gceSTATUS
1189gckOS_DestroySyncTimeline(
1190 IN gckOS Os,
1191 IN gctHANDLE Timeline
1192 );
1193
1194gceSTATUS
1195gckOS_CreateSyncPoint(
1196 IN gckOS Os,
1197 OUT gctSYNC_POINT * SyncPoint
1198 );
1199
1200gceSTATUS
1201gckOS_ReferenceSyncPoint(
1202 IN gckOS Os,
1203 IN gctSYNC_POINT SyncPoint
1204 );
1205
1206gceSTATUS
1207gckOS_DestroySyncPoint(
1208 IN gckOS Os,
1209 IN gctSYNC_POINT SyncPoint
1210 );
1211
1212gceSTATUS
1213gckOS_SignalSyncPoint(
1214 IN gckOS Os,
1215 IN gctSYNC_POINT SyncPoint
1216 );
1217
1218gceSTATUS
1219gckOS_QuerySyncPoint(
1220 IN gckOS Os,
1221 IN gctSYNC_POINT SyncPoint,
1222 OUT gctBOOL_PTR State
1223 );
1224
1225gceSTATUS
1226gckOS_CreateNativeFence(
1227 IN gckOS Os,
1228 IN gctHANDLE Timeline,
1229 IN gctSYNC_POINT SyncPoint,
1230 OUT gctINT * FenceFD
1231 );
1232
1233gceSTATUS
1234gckOS_WaitNativeFence(
1235 IN gckOS Os,
1236 IN gctHANDLE Timeline,
1237 IN gctINT FenceFD,
1238 IN gctUINT32 Timeout
1239 );
1240
1241#if !USE_NEW_LINUX_SIGNAL
1242/* Create signal to be used in the user space. */
1243gceSTATUS
1244gckOS_CreateUserSignal(
1245 IN gckOS Os,
1246 IN gctBOOL ManualReset,
1247 OUT gctINT * SignalID
1248 );
1249
1250/* Destroy signal used in the user space. */
1251gceSTATUS
1252gckOS_DestroyUserSignal(
1253 IN gckOS Os,
1254 IN gctINT SignalID
1255 );
1256
1257/* Wait for signal used in the user space. */
1258gceSTATUS
1259gckOS_WaitUserSignal(
1260 IN gckOS Os,
1261 IN gctINT SignalID,
1262 IN gctUINT32 Wait
1263 );
1264
1265/* Signal a signal used in the user space. */
1266gceSTATUS
1267gckOS_SignalUserSignal(
1268 IN gckOS Os,
1269 IN gctINT SignalID,
1270 IN gctBOOL State
1271 );
1272#endif /* USE_NEW_LINUX_SIGNAL */
1273
1274/* Set a signal owned by a process. */
1275#if defined(__QNXNTO__)
1276gceSTATUS
1277gckOS_UserSignal(
1278 IN gckOS Os,
1279 IN gctSIGNAL Signal,
1280 IN gctINT Recvid,
1281 IN gctINT Coid
1282 );
1283#else
1284gceSTATUS
1285gckOS_UserSignal(
1286 IN gckOS Os,
1287 IN gctSIGNAL Signal,
1288 IN gctHANDLE Process
1289 );
1290#endif
1291
1292/******************************************************************************\
1293** Cache Support
1294*/
1295
1296gceSTATUS
1297gckOS_CacheClean(
1298 gckOS Os,
1299 gctUINT32 ProcessID,
1300 gctPHYS_ADDR Handle,
1301 gctPHYS_ADDR_T Physical,
1302 gctPOINTER Logical,
1303 gctSIZE_T Bytes
1304 );
1305
1306gceSTATUS
1307gckOS_CacheFlush(
1308 gckOS Os,
1309 gctUINT32 ProcessID,
1310 gctPHYS_ADDR Handle,
1311 gctPHYS_ADDR_T Physical,
1312 gctPOINTER Logical,
1313 gctSIZE_T Bytes
1314 );
1315
1316gceSTATUS
1317gckOS_CacheInvalidate(
1318 gckOS Os,
1319 gctUINT32 ProcessID,
1320 gctPHYS_ADDR Handle,
1321 gctPHYS_ADDR_T Physical,
1322 gctPOINTER Logical,
1323 gctSIZE_T Bytes
1324 );
1325
1326gceSTATUS
1327gckOS_CPUPhysicalToGPUPhysical(
1328 IN gckOS Os,
1329 IN gctPHYS_ADDR_T CPUPhysical,
1330 IN gctPHYS_ADDR_T * GPUPhysical
1331 );
1332
1333gceSTATUS
1334gckOS_GPUPhysicalToCPUPhysical(
1335 IN gckOS Os,
1336 IN gctUINT32 GPUPhysical,
1337 IN gctUINT32_PTR CPUPhysical
1338 );
1339
1340gceSTATUS
1341gckOS_QueryOption(
1342 IN gckOS Os,
1343 IN gctCONST_STRING Option,
1344 OUT gctUINT32 * Value
1345 );
1346
1347/******************************************************************************\
1348** Debug Support
1349*/
1350
1351void
1352gckOS_SetDebugLevel(
1353 IN gctUINT32 Level
1354 );
1355
1356void
1357gckOS_SetDebugZone(
1358 IN gctUINT32 Zone
1359 );
1360
1361void
1362gckOS_SetDebugLevelZone(
1363 IN gctUINT32 Level,
1364 IN gctUINT32 Zone
1365 );
1366
1367void
1368gckOS_SetDebugZones(
1369 IN gctUINT32 Zones,
1370 IN gctBOOL Enable
1371 );
1372
1373void
1374gckOS_SetDebugFile(
1375 IN gctCONST_STRING FileName
1376 );
1377
1378/*******************************************************************************
1379** Broadcast interface.
1380*/
1381
1382typedef enum _gceBROADCAST
1383{
1384 /* GPU might be idle. */
1385 gcvBROADCAST_GPU_IDLE,
1386
1387 /* A commit is going to happen. */
1388 gcvBROADCAST_GPU_COMMIT,
1389
1390 /* GPU seems to be stuck. */
1391 gcvBROADCAST_GPU_STUCK,
1392
1393 /* First process gets attached. */
1394 gcvBROADCAST_FIRST_PROCESS,
1395
1396 /* Last process gets detached. */
1397 gcvBROADCAST_LAST_PROCESS,
1398
1399 /* AXI bus error. */
1400 gcvBROADCAST_AXI_BUS_ERROR,
1401
1402 /* Out of memory. */
1403 gcvBROADCAST_OUT_OF_MEMORY,
1404}
1405gceBROADCAST;
1406
1407gceSTATUS
1408gckOS_Broadcast(
1409 IN gckOS Os,
1410 IN gckHARDWARE Hardware,
1411 IN gceBROADCAST Reason
1412 );
1413
1414gceSTATUS
1415gckOS_BroadcastHurry(
1416 IN gckOS Os,
1417 IN gckHARDWARE Hardware,
1418 IN gctUINT Urgency
1419 );
1420
1421gceSTATUS
1422gckOS_BroadcastCalibrateSpeed(
1423 IN gckOS Os,
1424 IN gckHARDWARE Hardware,
1425 IN gctUINT Idle,
1426 IN gctUINT Time
1427 );
1428
1429/*******************************************************************************
1430**
1431** gckOS_SetGPUPower
1432**
1433** Set the power of the GPU on or off.
1434**
1435** INPUT:
1436**
1437** gckOS Os
1438** Pointer to a gckOS object.
1439**
1440** gceCORE Core
1441** GPU whose power is set.
1442**
1443** gctBOOL Clock
1444** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
1445**
1446** gctBOOL Power
1447** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
1448**
1449** OUTPUT:
1450**
1451** Nothing.
1452*/
1453gceSTATUS
1454gckOS_SetGPUPower(
1455 IN gckOS Os,
1456 IN gceCORE Core,
1457 IN gctBOOL Clock,
1458 IN gctBOOL Power
1459 );
1460
1461gceSTATUS
1462gckOS_ResetGPU(
1463 IN gckOS Os,
1464 IN gceCORE Core
1465 );
1466
1467gceSTATUS
1468gckOS_PrepareGPUFrequency(
1469 IN gckOS Os,
1470 IN gceCORE Core
1471 );
1472
1473gceSTATUS
1474gckOS_FinishGPUFrequency(
1475 IN gckOS Os,
1476 IN gceCORE Core
1477 );
1478
1479gceSTATUS
1480gckOS_QueryGPUFrequency(
1481 IN gckOS Os,
1482 IN gceCORE Core,
1483 OUT gctUINT32 * Frequency,
1484 OUT gctUINT8 * Scale
1485 );
1486
1487gceSTATUS
1488gckOS_SetGPUFrequency(
1489 IN gckOS Os,
1490 IN gceCORE Core,
1491 IN gctUINT8 Scale
1492 );
1493
1494/*******************************************************************************
1495** Semaphores.
1496*/
1497
1498/* Create a new semaphore. */
1499gceSTATUS
1500gckOS_CreateSemaphore(
1501 IN gckOS Os,
1502 OUT gctPOINTER * Semaphore
1503 );
1504
1505
1506/* Delete a semahore. */
1507gceSTATUS
1508gckOS_DestroySemaphore(
1509 IN gckOS Os,
1510 IN gctPOINTER Semaphore
1511 );
1512
1513/* Acquire a semahore. */
1514gceSTATUS
1515gckOS_AcquireSemaphore(
1516 IN gckOS Os,
1517 IN gctPOINTER Semaphore
1518 );
1519
1520/* Try to acquire a semahore. */
1521gceSTATUS
1522gckOS_TryAcquireSemaphore(
1523 IN gckOS Os,
1524 IN gctPOINTER Semaphore
1525 );
1526
1527/* Release a semahore. */
1528gceSTATUS
1529gckOS_ReleaseSemaphore(
1530 IN gckOS Os,
1531 IN gctPOINTER Semaphore
1532 );
1533
1534/*******************************************************************************
1535** Timer API.
1536*/
1537
1538typedef void (*gctTIMERFUNCTION)(gctPOINTER);
1539
1540/* Create a timer. */
1541gceSTATUS
1542gckOS_CreateTimer(
1543 IN gckOS Os,
1544 IN gctTIMERFUNCTION Function,
1545 IN gctPOINTER Data,
1546 OUT gctPOINTER * Timer
1547 );
1548
1549/* Destory a timer. */
1550gceSTATUS
1551gckOS_DestroyTimer(
1552 IN gckOS Os,
1553 IN gctPOINTER Timer
1554 );
1555
1556/* Start a timer. */
1557gceSTATUS
1558gckOS_StartTimer(
1559 IN gckOS Os,
1560 IN gctPOINTER Timer,
1561 IN gctUINT32 Delay
1562 );
1563
1564/* Stop a timer. */
1565gceSTATUS
1566gckOS_StopTimer(
1567 IN gckOS Os,
1568 IN gctPOINTER Timer
1569 );
1570
1571/******************************************************************************\
1572********************************* gckHEAP Object ********************************
1573\******************************************************************************/
1574
1575typedef struct _gckHEAP * gckHEAP;
1576
1577/* Construct a new gckHEAP object. */
1578gceSTATUS
1579gckHEAP_Construct(
1580 IN gckOS Os,
1581 IN gctSIZE_T AllocationSize,
1582 OUT gckHEAP * Heap
1583 );
1584
1585/* Destroy an gckHEAP object. */
1586gceSTATUS
1587gckHEAP_Destroy(
1588 IN gckHEAP Heap
1589 );
1590
1591/* Allocate memory. */
1592gceSTATUS
1593gckHEAP_Allocate(
1594 IN gckHEAP Heap,
1595 IN gctSIZE_T Bytes,
1596 OUT gctPOINTER * Node
1597 );
1598
1599/* Free memory. */
1600gceSTATUS
1601gckHEAP_Free(
1602 IN gckHEAP Heap,
1603 IN gctPOINTER Node
1604 );
1605
1606/* Profile the heap. */
1607gceSTATUS
1608gckHEAP_ProfileStart(
1609 IN gckHEAP Heap
1610 );
1611
1612gceSTATUS
1613gckHEAP_ProfileEnd(
1614 IN gckHEAP Heap,
1615 IN gctCONST_STRING Title
1616 );
1617
1618
1619/******************************************************************************\
1620******************************** gckVIDMEM Object ******************************
1621\******************************************************************************/
1622
1623typedef struct _gckVIDMEM * gckVIDMEM;
1624typedef struct _gckKERNEL * gckKERNEL;
1625typedef struct _gckDB * gckDB;
1626typedef struct _gckDVFS * gckDVFS;
1627
1628/* Construct a new gckVIDMEM object. */
1629gceSTATUS
1630gckVIDMEM_Construct(
1631 IN gckOS Os,
1632 IN gctUINT32 BaseAddress,
1633 IN gctSIZE_T Bytes,
1634 IN gctSIZE_T Threshold,
1635 IN gctSIZE_T Banking,
1636 OUT gckVIDMEM * Memory
1637 );
1638
1639/* Destroy an gckVDIMEM object. */
1640gceSTATUS
1641gckVIDMEM_Destroy(
1642 IN gckVIDMEM Memory
1643 );
1644
1645/* Allocate linear memory. */
1646gceSTATUS
1647gckVIDMEM_AllocateLinear(
1648 IN gckKERNEL Kernel,
1649 IN gckVIDMEM Memory,
1650 IN gctSIZE_T Bytes,
1651 IN gctUINT32 Alignment,
1652 IN gceSURF_TYPE Type,
1653 IN gctBOOL Specified,
1654 OUT gcuVIDMEM_NODE_PTR * Node
1655 );
1656
1657/* Free memory. */
1658gceSTATUS
1659gckVIDMEM_Free(
1660 IN gckKERNEL Kernel,
1661 IN gcuVIDMEM_NODE_PTR Node
1662 );
1663
1664/* Lock memory. */
1665gceSTATUS
1666gckVIDMEM_Lock(
1667 IN gckKERNEL Kernel,
1668 IN gckVIDMEM_NODE Node,
1669 IN gctBOOL Cacheable,
1670 OUT gctUINT32 * Address,
1671 OUT gctUINT32 * Gid,
1672 OUT gctUINT64 * PhysicalAddress
1673 );
1674
1675/* Unlock memory. */
1676gceSTATUS
1677gckVIDMEM_Unlock(
1678 IN gckKERNEL Kernel,
1679 IN gckVIDMEM_NODE Node,
1680 IN gceSURF_TYPE Type,
1681 IN OUT gctBOOL * Asynchroneous
1682 );
1683
1684/* Construct a gcuVIDMEM_NODE union for virtual memory. */
1685gceSTATUS
1686gckVIDMEM_ConstructVirtual(
1687 IN gckKERNEL Kernel,
1688 IN gctUINT32 Flag,
1689 IN gctSIZE_T Bytes,
1690 OUT gcuVIDMEM_NODE_PTR * Node
1691 );
1692
1693/* Destroy a gcuVIDMEM_NODE union for virtual memory. */
1694gceSTATUS
1695gckVIDMEM_DestroyVirtual(
1696 IN gcuVIDMEM_NODE_PTR Node
1697 );
1698
1699/******************************************************************************\
1700******************************** gckKERNEL Object ******************************
1701\******************************************************************************/
1702
1703struct _gcsHAL_INTERFACE;
1704
1705/* Notifications. */
1706typedef enum _gceNOTIFY
1707{
1708 gcvNOTIFY_INTERRUPT,
1709 gcvNOTIFY_COMMAND_QUEUE,
1710}
1711gceNOTIFY;
1712
1713/* Flush flags. */
1714typedef enum _gceKERNEL_FLUSH
1715{
1716 gcvFLUSH_COLOR = 0x01,
1717 gcvFLUSH_DEPTH = 0x02,
1718 gcvFLUSH_TEXTURE = 0x04,
1719 gcvFLUSH_2D = 0x08,
1720 gcvFLUSH_TILE_STATUS = 0x20,
1721 gcvFLUSH_ALL = gcvFLUSH_COLOR
1722 | gcvFLUSH_DEPTH
1723 | gcvFLUSH_TEXTURE
1724 | gcvFLUSH_2D
1725 | gcvFLUSH_TILE_STATUS
1726}
1727gceKERNEL_FLUSH;
1728
1729/* Construct a new gckKERNEL object. */
1730gceSTATUS
1731gckKERNEL_Construct(
1732 IN gckOS Os,
1733 IN gceCORE Core,
1734 IN gctPOINTER Context,
1735 IN gckDB SharedDB,
1736 OUT gckKERNEL * Kernel
1737 );
1738
1739/* Destroy an gckKERNEL object. */
1740gceSTATUS
1741gckKERNEL_Destroy(
1742 IN gckKERNEL Kernel
1743 );
1744
1745/* Dispatch a user-level command. */
1746gceSTATUS
1747gckKERNEL_Dispatch(
1748 IN gckKERNEL Kernel,
1749 IN gctBOOL FromUser,
1750 IN OUT struct _gcsHAL_INTERFACE * Interface
1751 );
1752
1753/* Query Database requirements. */
1754gceSTATUS
1755 gckKERNEL_QueryDatabase(
1756 IN gckKERNEL Kernel,
1757 IN gctUINT32 ProcessID,
1758 IN OUT gcsHAL_INTERFACE * Interface
1759 );
1760
1761/* Query the video memory. */
1762gceSTATUS
1763gckKERNEL_QueryVideoMemory(
1764 IN gckKERNEL Kernel,
1765 OUT struct _gcsHAL_INTERFACE * Interface
1766 );
1767
1768/* Lookup the gckVIDMEM object for a pool. */
1769gceSTATUS
1770gckKERNEL_GetVideoMemoryPool(
1771 IN gckKERNEL Kernel,
1772 IN gcePOOL Pool,
1773 OUT gckVIDMEM * VideoMemory
1774 );
1775
1776gceSTATUS
1777gckKERNEL_AllocateLinearMemory(
1778 IN gckKERNEL Kernel,
1779 IN gctUINT32 ProcessID,
1780 IN OUT gcePOOL * Pool,
1781 IN gctSIZE_T Bytes,
1782 IN gctUINT32 Alignment,
1783 IN gceSURF_TYPE Type,
1784 IN gctUINT32 Flag,
1785 OUT gctUINT32 * Node
1786 );
1787
1788gceSTATUS
1789gckKERNEL_ReleaseVideoMemory(
1790 IN gckKERNEL Kernel,
1791 IN gctUINT32 ProcessID,
1792 IN gctUINT32 Handle
1793 );
1794
1795gceSTATUS
1796gckKERNEL_LockVideoMemory(
1797 IN gckKERNEL Kernel,
1798 IN gceCORE Core,
1799 IN gctUINT32 ProcessID,
1800 IN gctBOOL FromUser,
1801 IN OUT gcsHAL_INTERFACE * Interface
1802 );
1803
1804gceSTATUS
1805gckKERNEL_UnlockVideoMemory(
1806 IN gckKERNEL Kernel,
1807 IN gctUINT32 ProcessID,
1808 IN OUT gcsHAL_INTERFACE * Interface
1809 );
1810
1811/* Map video memory. */
1812gceSTATUS
1813gckKERNEL_MapVideoMemory(
1814 IN gckKERNEL Kernel,
1815 IN gctBOOL InUserSpace,
1816 IN gctUINT32 Address,
1817#ifdef __QNXNTO__
1818 IN gctUINT32 Pid,
1819 IN gctUINT32 Bytes,
1820#endif
1821 OUT gctPOINTER * Logical
1822 );
1823
1824/* Map video memory. */
1825gceSTATUS
1826gckKERNEL_MapVideoMemoryEx(
1827 IN gckKERNEL Kernel,
1828 IN gceCORE Core,
1829 IN gctBOOL InUserSpace,
1830 IN gctUINT32 Address,
1831#ifdef __QNXNTO__
1832 IN gctUINT32 Pid,
1833 IN gctUINT32 Bytes,
1834#endif
1835 OUT gctPOINTER * Logical
1836 );
1837
1838#ifdef __QNXNTO__
1839/* Unmap video memory. */
1840gceSTATUS
1841gckKERNEL_UnmapVideoMemory(
1842 IN gckKERNEL Kernel,
1843 IN gctPOINTER Logical,
1844 IN gctUINT32 Pid,
1845 IN gctUINT32 Bytes
1846 );
1847#endif
1848
1849/* Map memory. */
1850gceSTATUS
1851gckKERNEL_MapMemory(
1852 IN gckKERNEL Kernel,
1853 IN gctPHYS_ADDR Physical,
1854 IN gctSIZE_T Bytes,
1855 OUT gctPOINTER * Logical
1856 );
1857
1858/* Unmap memory. */
1859gceSTATUS
1860gckKERNEL_UnmapMemory(
1861 IN gckKERNEL Kernel,
1862 IN gctPHYS_ADDR Physical,
1863 IN gctSIZE_T Bytes,
1864 IN gctPOINTER Logical
1865 );
1866
1867/* Notification of events. */
1868gceSTATUS
1869gckKERNEL_Notify(
1870 IN gckKERNEL Kernel,
1871 IN gceNOTIFY Notifcation,
1872 IN gctBOOL Data
1873 );
1874
1875gceSTATUS
1876gckKERNEL_QuerySettings(
1877 IN gckKERNEL Kernel,
1878 OUT gcsKERNEL_SETTINGS * Settings
1879 );
1880
1881/*******************************************************************************
1882**
1883** gckKERNEL_Recovery
1884**
1885** Try to recover the GPU from a fatal error.
1886**
1887** INPUT:
1888**
1889** gckKERNEL Kernel
1890** Pointer to an gckKERNEL object.
1891**
1892** OUTPUT:
1893**
1894** Nothing.
1895*/
1896gceSTATUS
1897gckKERNEL_Recovery(
1898 IN gckKERNEL Kernel
1899 );
1900
1901/* Set the value of timeout on HW operation. */
1902void
1903gckKERNEL_SetTimeOut(
1904 IN gckKERNEL Kernel,
1905 IN gctUINT32 timeOut
1906 );
1907
1908/* Get access to the user data. */
1909gceSTATUS
1910gckKERNEL_OpenUserData(
1911 IN gckKERNEL Kernel,
1912 IN gctBOOL NeedCopy,
1913 IN gctPOINTER StaticStorage,
1914 IN gctPOINTER UserPointer,
1915 IN gctSIZE_T Size,
1916 OUT gctPOINTER * KernelPointer
1917 );
1918
1919/* Release resources associated with the user data connection. */
1920gceSTATUS
1921gckKERNEL_CloseUserData(
1922 IN gckKERNEL Kernel,
1923 IN gctBOOL NeedCopy,
1924 IN gctBOOL FlushData,
1925 IN gctPOINTER UserPointer,
1926 IN gctSIZE_T Size,
1927 OUT gctPOINTER * KernelPointer
1928 );
1929
1930gceSTATUS
1931gckDVFS_Construct(
1932 IN gckHARDWARE Hardware,
1933 OUT gckDVFS * Frequency
1934 );
1935
1936gceSTATUS
1937gckDVFS_Destroy(
1938 IN gckDVFS Dvfs
1939 );
1940
1941gceSTATUS
1942gckDVFS_Start(
1943 IN gckDVFS Dvfs
1944 );
1945
1946gceSTATUS
1947gckDVFS_Stop(
1948 IN gckDVFS Dvfs
1949 );
1950
1951/******************************************************************************\
1952******************************* gckHARDWARE Object *****************************
1953\******************************************************************************/
1954
1955/* Construct a new gckHARDWARE object. */
1956gceSTATUS
1957gckHARDWARE_Construct(
1958 IN gckOS Os,
1959 IN gceCORE Core,
1960 OUT gckHARDWARE * Hardware
1961 );
1962
1963/* Destroy an gckHARDWARE object. */
1964gceSTATUS
1965gckHARDWARE_Destroy(
1966 IN gckHARDWARE Hardware
1967 );
1968
1969/* Get hardware type. */
1970gceSTATUS
1971gckHARDWARE_GetType(
1972 IN gckHARDWARE Hardware,
1973 OUT gceHARDWARE_TYPE * Type
1974 );
1975
1976/* Query system memory requirements. */
1977gceSTATUS
1978gckHARDWARE_QuerySystemMemory(
1979 IN gckHARDWARE Hardware,
1980 OUT gctSIZE_T * SystemSize,
1981 OUT gctUINT32 * SystemBaseAddress
1982 );
1983
1984/* Build virtual address. */
1985gceSTATUS
1986gckHARDWARE_BuildVirtualAddress(
1987 IN gckHARDWARE Hardware,
1988 IN gctUINT32 Index,
1989 IN gctUINT32 Offset,
1990 OUT gctUINT32 * Address
1991 );
1992
1993/* Query command buffer requirements. */
1994gceSTATUS
1995gckHARDWARE_QueryCommandBuffer(
1996 IN gckHARDWARE Hardware,
1997 OUT gctUINT32 * Alignment,
1998 OUT gctUINT32 * ReservedHead,
1999 OUT gctUINT32 * ReservedTail
2000 );
2001
2002/* Add a WAIT/LINK pair in the command queue. */
2003gceSTATUS
2004gckHARDWARE_WaitLink(
2005 IN gckHARDWARE Hardware,
2006 IN gctPOINTER Logical,
2007 IN gctUINT32 Offset,
2008 IN OUT gctUINT32 * Bytes,
2009 OUT gctUINT32 * WaitOffset,
2010 OUT gctUINT32 * WaitBytes
2011 );
2012
2013/* Kickstart the command processor. */
2014gceSTATUS
2015gckHARDWARE_Execute(
2016 IN gckHARDWARE Hardware,
2017 IN gctUINT32 Address,
2018 IN gctSIZE_T Bytes
2019 );
2020
2021/* Add an END command in the command queue. */
2022gceSTATUS
2023gckHARDWARE_End(
2024 IN gckHARDWARE Hardware,
2025 IN gctPOINTER Logical,
2026 IN OUT gctUINT32 * Bytes
2027 );
2028
2029
2030/* Add a NOP command in the command queue. */
2031gceSTATUS
2032gckHARDWARE_Nop(
2033 IN gckHARDWARE Hardware,
2034 IN gctPOINTER Logical,
2035 IN OUT gctSIZE_T * Bytes
2036 );
2037
2038/* Add a PIPESELECT command in the command queue. */
2039gceSTATUS
2040gckHARDWARE_PipeSelect(
2041 IN gckHARDWARE Hardware,
2042 IN gctPOINTER Logical,
2043 IN gcePIPE_SELECT Pipe,
2044 IN OUT gctUINT32 * Bytes
2045 );
2046
2047/* Add a LINK command in the command queue. */
2048gceSTATUS
2049gckHARDWARE_Link(
2050 IN gckHARDWARE Hardware,
2051 IN gctPOINTER Logical,
2052 IN gctUINT32 FetchAddress,
2053 IN gctUINT32 FetchSize,
2054 IN OUT gctUINT32 * Bytes,
2055 OUT gctUINT32 * Low,
2056 OUT gctUINT32 * High
2057 );
2058
2059/* Add an EVENT command in the command queue. */
2060gceSTATUS
2061gckHARDWARE_Event(
2062 IN gckHARDWARE Hardware,
2063 IN gctPOINTER Logical,
2064 IN gctUINT8 Event,
2065 IN gceKERNEL_WHERE FromWhere,
2066 IN OUT gctUINT32 * Bytes
2067 );
2068
2069/* Query the available memory. */
2070gceSTATUS
2071gckHARDWARE_QueryMemory(
2072 IN gckHARDWARE Hardware,
2073 OUT gctSIZE_T * InternalSize,
2074 OUT gctUINT32 * InternalBaseAddress,
2075 OUT gctUINT32 * InternalAlignment,
2076 OUT gctSIZE_T * ExternalSize,
2077 OUT gctUINT32 * ExternalBaseAddress,
2078 OUT gctUINT32 * ExternalAlignment,
2079 OUT gctUINT32 * HorizontalTileSize,
2080 OUT gctUINT32 * VerticalTileSize
2081 );
2082
2083/* Query the identity of the hardware. */
2084gceSTATUS
2085gckHARDWARE_QueryChipIdentity(
2086 IN gckHARDWARE Hardware,
2087 OUT gcsHAL_QUERY_CHIP_IDENTITY_PTR Identity
2088 );
2089
2090/* Query the shader uniforms support. */
2091gceSTATUS
2092gckHARDWARE_QueryShaderCaps(
2093 IN gckHARDWARE Hardware,
2094 OUT gctUINT * VertexUniforms,
2095 OUT gctUINT * FragmentUniforms,
2096 OUT gctBOOL * UnifiedUnforms
2097 );
2098
2099/* Split a harwdare specific address into API stuff. */
2100gceSTATUS
2101gckHARDWARE_SplitMemory(
2102 IN gckHARDWARE Hardware,
2103 IN gctUINT32 Address,
2104 OUT gcePOOL * Pool,
2105 OUT gctUINT32 * Offset
2106 );
2107
2108/* Update command queue tail pointer. */
2109gceSTATUS
2110gckHARDWARE_UpdateQueueTail(
2111 IN gckHARDWARE Hardware,
2112 IN gctPOINTER Logical,
2113 IN gctUINT32 Offset
2114 );
2115
2116/* Convert logical address to hardware specific address. */
2117gceSTATUS
2118gckHARDWARE_ConvertLogical(
2119 IN gckHARDWARE Hardware,
2120 IN gctPOINTER Logical,
2121 IN gctBOOL InUserSpace,
2122 OUT gctUINT32 * Address
2123 );
2124
2125/* Interrupt manager. */
2126gceSTATUS
2127gckHARDWARE_Interrupt(
2128 IN gckHARDWARE Hardware,
2129 IN gctBOOL InterruptValid
2130 );
2131
2132/* Program MMU. */
2133gceSTATUS
2134gckHARDWARE_SetMMU(
2135 IN gckHARDWARE Hardware,
2136 IN gctPOINTER Logical
2137 );
2138
2139/* Flush the MMU. */
2140gceSTATUS
2141gckHARDWARE_FlushMMU(
2142 IN gckHARDWARE Hardware
2143 );
2144
2145/* Set the page table base address. */
2146gceSTATUS
2147gckHARDWARE_SetMMUv2(
2148 IN gckHARDWARE Hardware,
2149 IN gctBOOL Enable,
2150 IN gctPOINTER MtlbAddress,
2151 IN gceMMU_MODE Mode,
2152 IN gctPOINTER SafeAddress,
2153 IN gctBOOL FromPower
2154 );
2155
2156#if gcdPROCESS_ADDRESS_SPACE
2157/* Configure mmu configuration. */
2158gceSTATUS
2159gckHARDWARE_ConfigMMU(
2160 IN gckHARDWARE Hardware,
2161 IN gctPOINTER Logical,
2162 IN gctPOINTER MtlbLogical,
2163 IN gctUINT32 Offset,
2164 IN OUT gctSIZE_T * Bytes,
2165 OUT gctSIZE_T * WaitLinkOffset,
2166 OUT gctSIZE_T * WaitLinkBytes
2167 );
2168#endif
2169
2170/* Get idle register. */
2171gceSTATUS
2172gckHARDWARE_GetIdle(
2173 IN gckHARDWARE Hardware,
2174 IN gctBOOL Wait,
2175 OUT gctUINT32 * Data
2176 );
2177
2178/* Flush the caches. */
2179gceSTATUS
2180gckHARDWARE_Flush(
2181 IN gckHARDWARE Hardware,
2182 IN gceKERNEL_FLUSH Flush,
2183 IN gctPOINTER Logical,
2184 IN OUT gctUINT32 * Bytes
2185 );
2186
2187/* Enable/disable fast clear. */
2188gceSTATUS
2189gckHARDWARE_SetFastClear(
2190 IN gckHARDWARE Hardware,
2191 IN gctINT Enable,
2192 IN gctINT Compression
2193 );
2194
2195gceSTATUS
2196gckHARDWARE_ReadInterrupt(
2197 IN gckHARDWARE Hardware,
2198 OUT gctUINT32_PTR IDs
2199 );
2200
2201/* Power management. */
2202gceSTATUS
2203gckHARDWARE_SetPowerManagementState(
2204 IN gckHARDWARE Hardware,
2205 IN gceCHIPPOWERSTATE State
2206 );
2207
2208gceSTATUS
2209gckHARDWARE_QueryPowerManagementState(
2210 IN gckHARDWARE Hardware,
2211 OUT gceCHIPPOWERSTATE* State
2212 );
2213
2214gceSTATUS
2215gckHARDWARE_SetPowerManagement(
2216 IN gckHARDWARE Hardware,
2217 IN gctBOOL PowerManagement
2218 );
2219
2220gceSTATUS
2221gckHARDWARE_SetGpuProfiler(
2222 IN gckHARDWARE Hardware,
2223 IN gctBOOL GpuProfiler
2224 );
2225
2226#if gcdENABLE_FSCALE_VAL_ADJUST
2227gceSTATUS
2228gckHARDWARE_SetFscaleValue(
2229 IN gckHARDWARE Hardware,
2230 IN gctUINT32 FscaleValue
2231 );
2232
2233gceSTATUS
2234gckHARDWARE_GetFscaleValue(
2235 IN gckHARDWARE Hardware,
2236 IN gctUINT * FscaleValue,
2237 IN gctUINT * MinFscaleValue,
2238 IN gctUINT * MaxFscaleValue
2239 );
2240
2241gceSTATUS
2242gckHARDWARE_SetMinFscaleValue(
2243 IN gckHARDWARE Hardware,
2244 IN gctUINT MinFscaleValue
2245 );
2246#endif
2247
2248#if gcdPOWEROFF_TIMEOUT
2249gceSTATUS
2250gckHARDWARE_SetPowerOffTimeout(
2251 IN gckHARDWARE Hardware,
2252 IN gctUINT32 Timeout
2253);
2254
2255gceSTATUS
2256gckHARDWARE_QueryPowerOffTimeout(
2257 IN gckHARDWARE Hardware,
2258 OUT gctUINT32* Timeout
2259);
2260#endif
2261
2262/* Profile 2D Engine. */
2263gceSTATUS
2264gckHARDWARE_ProfileEngine2D(
2265 IN gckHARDWARE Hardware,
2266 OUT gcs2D_PROFILE_PTR Profile
2267 );
2268
2269gceSTATUS
2270gckHARDWARE_InitializeHardware(
2271 IN gckHARDWARE Hardware
2272 );
2273
2274gceSTATUS
2275gckHARDWARE_Reset(
2276 IN gckHARDWARE Hardware
2277 );
2278
2279typedef gceSTATUS (*gctISRMANAGERFUNC)(gctPOINTER Context);
2280
2281gceSTATUS
2282gckHARDWARE_SetIsrManager(
2283 IN gckHARDWARE Hardware,
2284 IN gctISRMANAGERFUNC StartIsr,
2285 IN gctISRMANAGERFUNC StopIsr,
2286 IN gctPOINTER Context
2287 );
2288
2289/* Start a composition. */
2290gceSTATUS
2291gckHARDWARE_Compose(
2292 IN gckHARDWARE Hardware,
2293 IN gctUINT32 ProcessID,
2294 IN gctPHYS_ADDR Physical,
2295 IN gctPOINTER Logical,
2296 IN gctSIZE_T Offset,
2297 IN gctSIZE_T Size,
2298 IN gctUINT8 EventID
2299 );
2300
2301/* Check for Hardware features. */
2302gceSTATUS
2303gckHARDWARE_IsFeatureAvailable(
2304 IN gckHARDWARE Hardware,
2305 IN gceFEATURE Feature
2306 );
2307
2308gceSTATUS
2309gckHARDWARE_DumpMMUException(
2310 IN gckHARDWARE Hardware
2311 );
2312
2313gceSTATUS
2314gckHARDWARE_DumpGPUState(
2315 IN gckHARDWARE Hardware
2316 );
2317
2318gceSTATUS
2319gckHARDWARE_InitDVFS(
2320 IN gckHARDWARE Hardware
2321 );
2322
2323gceSTATUS
2324gckHARDWARE_QueryLoad(
2325 IN gckHARDWARE Hardware,
2326 OUT gctUINT32 * Load
2327 );
2328
2329gceSTATUS
2330gckHARDWARE_SetDVFSPeroid(
2331 IN gckHARDWARE Hardware,
2332 IN gctUINT32 Frequency
2333 );
2334
2335gceSTATUS
2336gckHARDWARE_PrepareFunctions(
2337 gckHARDWARE Hardware
2338 );
2339
2340gceSTATUS
2341gckHARDWARE_SetMMUStates(
2342 IN gckHARDWARE Hardware,
2343 IN gctPOINTER MtlbAddress,
2344 IN gceMMU_MODE Mode,
2345 IN gctPOINTER SafeAddress,
2346 IN gctPOINTER Logical,
2347 IN OUT gctUINT32 * Bytes
2348 );
2349
2350gceSTATUS
2351gckHARDWARE_QueryStateTimer(
2352 IN gckHARDWARE Hardware,
2353 OUT gctUINT64_PTR Start,
2354 OUT gctUINT64_PTR End,
2355 OUT gctUINT64_PTR On,
2356 OUT gctUINT64_PTR Off,
2357 OUT gctUINT64_PTR Idle,
2358 OUT gctUINT64_PTR Suspend
2359 );
2360
2361/******************************************************************************\
2362***************************** gckINTERRUPT Object ******************************
2363\******************************************************************************/
2364
2365typedef struct _gckINTERRUPT * gckINTERRUPT;
2366
2367typedef gceSTATUS (* gctINTERRUPT_HANDLER)(
2368 IN gckKERNEL Kernel
2369 );
2370
2371gceSTATUS
2372gckINTERRUPT_Construct(
2373 IN gckKERNEL Kernel,
2374 OUT gckINTERRUPT * Interrupt
2375 );
2376
2377gceSTATUS
2378gckINTERRUPT_Destroy(
2379 IN gckINTERRUPT Interrupt
2380 );
2381
2382gceSTATUS
2383gckINTERRUPT_SetHandler(
2384 IN gckINTERRUPT Interrupt,
2385 IN OUT gctINT32_PTR Id,
2386 IN gctINTERRUPT_HANDLER Handler
2387 );
2388
2389gceSTATUS
2390gckINTERRUPT_Notify(
2391 IN gckINTERRUPT Interrupt,
2392 IN gctBOOL Valid
2393 );
2394/******************************************************************************\
2395******************************** gckEVENT Object *******************************
2396\******************************************************************************/
2397
2398typedef struct _gckEVENT * gckEVENT;
2399
2400/* Construct a new gckEVENT object. */
2401gceSTATUS
2402gckEVENT_Construct(
2403 IN gckKERNEL Kernel,
2404 OUT gckEVENT * Event
2405 );
2406
2407/* Destroy an gckEVENT object. */
2408gceSTATUS
2409gckEVENT_Destroy(
2410 IN gckEVENT Event
2411 );
2412
2413/* Reserve the next available hardware event. */
2414gceSTATUS
2415gckEVENT_GetEvent(
2416 IN gckEVENT Event,
2417 IN gctBOOL Wait,
2418 OUT gctUINT8 * EventID,
2419 IN gceKERNEL_WHERE Source
2420 );
2421
2422/* Add a new event to the list of events. */
2423gceSTATUS
2424gckEVENT_AddList(
2425 IN gckEVENT Event,
2426 IN gcsHAL_INTERFACE_PTR Interface,
2427 IN gceKERNEL_WHERE FromWhere,
2428 IN gctBOOL AllocateAllowed,
2429 IN gctBOOL FromKernel
2430 );
2431
2432/* Schedule a FreeNonPagedMemory event. */
2433gceSTATUS
2434gckEVENT_FreeNonPagedMemory(
2435 IN gckEVENT Event,
2436 IN gctSIZE_T Bytes,
2437 IN gctPHYS_ADDR Physical,
2438 IN gctPOINTER Logical,
2439 IN gceKERNEL_WHERE FromWhere
2440 );
2441
2442/* Schedule a FreeContiguousMemory event. */
2443gceSTATUS
2444gckEVENT_FreeContiguousMemory(
2445 IN gckEVENT Event,
2446 IN gctSIZE_T Bytes,
2447 IN gctPHYS_ADDR Physical,
2448 IN gctPOINTER Logical,
2449 IN gceKERNEL_WHERE FromWhere
2450 );
2451
2452/* Schedule a FreeVideoMemory event. */
2453gceSTATUS
2454gckEVENT_FreeVideoMemory(
2455 IN gckEVENT Event,
2456 IN gcuVIDMEM_NODE_PTR VideoMemory,
2457 IN gceKERNEL_WHERE FromWhere
2458 );
2459
2460/* Schedule a signal event. */
2461gceSTATUS
2462gckEVENT_Signal(
2463 IN gckEVENT Event,
2464 IN gctSIGNAL Signal,
2465 IN gceKERNEL_WHERE FromWhere
2466 );
2467
2468/* Schedule an Unlock event. */
2469gceSTATUS
2470gckEVENT_Unlock(
2471 IN gckEVENT Event,
2472 IN gceKERNEL_WHERE FromWhere,
2473 IN gctPOINTER Node,
2474 IN gceSURF_TYPE Type
2475 );
2476
2477gceSTATUS
2478gckEVENT_CommitDone(
2479 IN gckEVENT Event,
2480 IN gceKERNEL_WHERE FromWhere
2481 );
2482
2483/* Schedule a FreeVirtualCommandBuffer event. */
2484gceSTATUS
2485gckEVENT_DestroyVirtualCommandBuffer(
2486 IN gckEVENT Event,
2487 IN gctSIZE_T Bytes,
2488 IN gctPHYS_ADDR Physical,
2489 IN gctPOINTER Logical,
2490 IN gceKERNEL_WHERE FromWhere
2491 );
2492
2493gceSTATUS
2494gckEVENT_Submit(
2495 IN gckEVENT Event,
2496 IN gctBOOL Wait,
2497 IN gctBOOL FromPower
2498 );
2499
2500gceSTATUS
2501gckEVENT_Commit(
2502 IN gckEVENT Event,
2503 IN gcsQUEUE_PTR Queue
2504 );
2505
2506/* Schedule a composition event. */
2507gceSTATUS
2508gckEVENT_Compose(
2509 IN gckEVENT Event,
2510 IN gcsHAL_COMPOSE_PTR Info
2511 );
2512
2513/* Event callback routine. */
2514gceSTATUS
2515gckEVENT_Notify(
2516 IN gckEVENT Event,
2517 IN gctUINT32 IDs
2518 );
2519
2520/* Event callback routine. */
2521gceSTATUS
2522gckEVENT_Interrupt(
2523 IN gckEVENT Event,
2524 IN gctUINT32 IDs
2525 );
2526
2527gceSTATUS
2528gckEVENT_Dump(
2529 IN gckEVENT Event
2530 );
2531/******************************************************************************\
2532******************************* gckCOMMAND Object ******************************
2533\******************************************************************************/
2534
2535typedef struct _gckCOMMAND * gckCOMMAND;
2536
2537/* Construct a new gckCOMMAND object. */
2538gceSTATUS
2539gckCOMMAND_Construct(
2540 IN gckKERNEL Kernel,
2541 OUT gckCOMMAND * Command
2542 );
2543
2544/* Destroy an gckCOMMAND object. */
2545gceSTATUS
2546gckCOMMAND_Destroy(
2547 IN gckCOMMAND Command
2548 );
2549
2550/* Acquire command queue synchronization objects. */
2551gceSTATUS
2552gckCOMMAND_EnterCommit(
2553 IN gckCOMMAND Command,
2554 IN gctBOOL FromPower
2555 );
2556
2557/* Release command queue synchronization objects. */
2558gceSTATUS
2559gckCOMMAND_ExitCommit(
2560 IN gckCOMMAND Command,
2561 IN gctBOOL FromPower
2562 );
2563
2564/* Start the command queue. */
2565gceSTATUS
2566gckCOMMAND_Start(
2567 IN gckCOMMAND Command
2568 );
2569
2570/* Stop the command queue. */
2571gceSTATUS
2572gckCOMMAND_Stop(
2573 IN gckCOMMAND Command,
2574 IN gctBOOL FromRecovery
2575 );
2576
2577gceSTATUS
2578gckCOMMAND_Commit(
2579 IN gckCOMMAND Command,
2580 IN gckCONTEXT Context,
2581 IN gcoCMDBUF CommandBuffer,
2582 IN gcsSTATE_DELTA_PTR StateDelta,
2583 IN gcsQUEUE_PTR EventQueue,
2584 IN gctUINT32 ProcessID
2585 );
2586
2587/* Reserve space in the command buffer. */
2588gceSTATUS
2589gckCOMMAND_Reserve(
2590 IN gckCOMMAND Command,
2591 IN gctUINT32 RequestedBytes,
2592 OUT gctPOINTER * Buffer,
2593 OUT gctUINT32 * BufferSize
2594 );
2595
2596/* Execute reserved space in the command buffer. */
2597gceSTATUS
2598gckCOMMAND_Execute(
2599 IN gckCOMMAND Command,
2600 IN gctUINT32 RequstedBytes
2601 );
2602
2603/* Stall the command queue. */
2604gceSTATUS
2605gckCOMMAND_Stall(
2606 IN gckCOMMAND Command,
2607 IN gctBOOL FromPower
2608 );
2609
2610/* Attach user process. */
2611gceSTATUS
2612gckCOMMAND_Attach(
2613 IN gckCOMMAND Command,
2614 OUT gckCONTEXT * Context,
2615 OUT gctSIZE_T * MaxState,
2616 OUT gctUINT32 * NumStates,
2617 IN gctUINT32 ProcessID
2618 );
2619
2620/* Detach user process. */
2621gceSTATUS
2622gckCOMMAND_Detach(
2623 IN gckCOMMAND Command,
2624 IN gckCONTEXT Context
2625 );
2626
2627/* Dump command buffer being executed by GPU. */
2628gceSTATUS
2629gckCOMMAND_DumpExecutingBuffer(
2630 IN gckCOMMAND Command
2631 );
2632
2633/* Whether a kernel command buffer address. */
2634gceSTATUS
2635gckCOMMAND_AddressInKernelCommandBuffer(
2636 IN gckCOMMAND Command,
2637 IN gctUINT32 Address,
2638 OUT gctPOINTER * Pointer
2639 );
2640
2641/******************************************************************************\
2642********************************* gckMMU Object ********************************
2643\******************************************************************************/
2644
2645typedef struct _gckMMU * gckMMU;
2646
2647/* Construct a new gckMMU object. */
2648gceSTATUS
2649gckMMU_Construct(
2650 IN gckKERNEL Kernel,
2651 IN gctSIZE_T MmuSize,
2652 OUT gckMMU * Mmu
2653 );
2654
2655/* Destroy an gckMMU object. */
2656gceSTATUS
2657gckMMU_Destroy(
2658 IN gckMMU Mmu
2659 );
2660
2661/* Allocate pages inside the MMU. */
2662gceSTATUS
2663gckMMU_AllocatePages(
2664 IN gckMMU Mmu,
2665 IN gctSIZE_T PageCount,
2666 OUT gctPOINTER * PageTable,
2667 OUT gctUINT32 * Address
2668 );
2669
2670gceSTATUS
2671gckMMU_AllocatePagesEx(
2672 IN gckMMU Mmu,
2673 IN gctSIZE_T PageCount,
2674 IN gceSURF_TYPE Type,
2675 OUT gctPOINTER * PageTable,
2676 OUT gctUINT32 * Address
2677 );
2678
2679/* Remove a page table from the MMU. */
2680gceSTATUS
2681gckMMU_FreePages(
2682 IN gckMMU Mmu,
2683 IN gctPOINTER PageTable,
2684 IN gctSIZE_T PageCount
2685 );
2686
2687/* Set the MMU page with info. */
2688gceSTATUS
2689gckMMU_SetPage(
2690 IN gckMMU Mmu,
2691 IN gctPHYS_ADDR_T PageAddress,
2692 IN gctUINT32 *PageEntry
2693 );
2694
2695gceSTATUS
2696gckMMU_Flush(
2697 IN gckMMU Mmu,
2698 IN gceSURF_TYPE Type
2699 );
2700
2701gceSTATUS
2702gckMMU_DumpPageTableEntry(
2703 IN gckMMU Mmu,
2704 IN gctUINT32 Address
2705 );
2706
2707
2708#if VIVANTE_PROFILER
2709gceSTATUS
2710gckHARDWARE_QueryProfileRegisters(
2711 IN gckHARDWARE Hardware,
2712 IN gctBOOL Reset,
2713 OUT gcsPROFILER_COUNTERS * Counters
2714 );
2715#endif
2716
2717#if VIVANTE_PROFILER_CONTEXT
2718gceSTATUS
2719gckHARDWARE_QueryContextProfile(
2720 IN gckHARDWARE Hardware,
2721 IN gctBOOL Reset,
2722 IN gckCONTEXT Context,
2723 OUT gcsPROFILER_COUNTERS * Counters
2724 );
2725
2726gceSTATUS
2727gckHARDWARE_UpdateContextProfile(
2728 IN gckHARDWARE Hardware,
2729 IN gckCONTEXT Context
2730 );
2731#endif
2732
2733gceSTATUS
2734gckHARDWARE_InitProfiler(
2735 IN gckHARDWARE Hardware
2736 );
2737
2738gceSTATUS
2739gckOS_SignalQueryHardware(
2740 IN gckOS Os,
2741 IN gctSIGNAL Signal,
2742 OUT gckHARDWARE * Hardware
2743 );
2744
2745gceSTATUS
2746gckOS_SignalSetHardware(
2747 IN gckOS Os,
2748 IN gctSIGNAL Signal,
2749 gckHARDWARE Hardware
2750 );
2751
2752gceSTATUS
2753gckOS_DetectProcessByName(
2754 IN gctCONST_POINTER Name
2755 );
2756
2757void
2758gckOS_DumpParam(
2759 void
2760 );
2761
2762#ifdef __cplusplus
2763}
2764#endif
2765
2766
2767#endif /* __gc_hal_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_base.h b/src/hal/kernel/inc/gc_hal_base.h
new file mode 100755
index 0000000..64410be
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_base.h
@@ -0,0 +1,5347 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_base_h_
57#define __gc_hal_base_h_
58
59#include "gc_hal_enum.h"
60#include "gc_hal_types.h"
61#include "gc_hal_dump.h"
62
63#ifdef __cplusplus
64extern "C" {
65#endif
66
67/******************************************************************************\
68****************************** Object Declarations *****************************
69\******************************************************************************/
70
71typedef struct _gckOS * gckOS;
72typedef struct _gcoHAL * gcoHAL;
73typedef struct _gcoOS * gcoOS;
74typedef struct _gco2D * gco2D;
75typedef struct gcsATOM * gcsATOM_PTR;
76
77
78typedef struct _gcoSURF * gcoSURF;
79typedef struct _gcsSURF_INFO * gcsSURF_INFO_PTR;
80typedef struct _gcsSURF_NODE * gcsSURF_NODE_PTR;
81typedef struct _gcsSURF_FORMAT_INFO * gcsSURF_FORMAT_INFO_PTR;
82typedef struct _gcsPOINT * gcsPOINT_PTR;
83typedef struct _gcsSIZE * gcsSIZE_PTR;
84typedef struct _gcsRECT * gcsRECT_PTR;
85typedef struct _gcsBOUNDARY * gcsBOUNDARY_PTR;
86typedef struct _gcoDUMP * gcoDUMP;
87typedef struct _gcoHARDWARE * gcoHARDWARE;
88typedef union _gcuVIDMEM_NODE * gcuVIDMEM_NODE_PTR;
89typedef struct _gcsVIDMEM_NODE * gckVIDMEM_NODE;
90
91typedef void * gcoVG;
92
93#if gcdGC355_PROFILER
94typedef struct _gcsPROFILERFUNCData * gcsPROFILERFUNCData_PTR;
95typedef struct _gcsPROFILERFUNCNODE * gcsPROFILERFUNCNODE_PTR;
96#endif
97
98#if gcdSYNC
99typedef struct _gcoFENCE * gcoFENCE;
100typedef struct _gcsSYNC_CONTEXT * gcsSYNC_CONTEXT_PTR;
101#endif
102
103typedef struct _gcsUSER_MEMORY_DESC * gcsUSER_MEMORY_DESC_PTR;
104
105/******************************************************************************\
106********************* Share obj lock/unlock macros. ****************************
107\******************************************************************************/
108#define gcmLOCK_SHARE_OBJ(Obj) \
109{ \
110 if(Obj->sharedLock != gcvNULL)\
111 {\
112 (gcoOS_AcquireMutex( \
113 gcvNULL, Obj->sharedLock, gcvINFINITE));\
114 }\
115}
116
117
118#define gcmUNLOCK_SHARE_OBJ(Obj)\
119{\
120 if(Obj->sharedLock != gcvNULL)\
121 {\
122 (gcoOS_ReleaseMutex(gcvNULL, Obj->sharedLock));\
123 }\
124}
125
126#if defined(ANDROID)
127typedef struct _gcoOS_SymbolsList gcoOS_SymbolsList;
128#endif
129
130/******************************************************************************\
131******************************* Process local storage *************************
132\******************************************************************************/
133
134typedef struct _gcsPLS * gcsPLS_PTR;
135
136
137
138typedef void (* gctPLS_DESTRUCTOR) (
139 gcsPLS_PTR
140 );
141
142typedef struct _gcsPLS
143{
144 /* Global objects. */
145 gcoOS os;
146 gcoHAL hal;
147
148 /* Internal memory pool. */
149 gctSIZE_T internalSize;
150 gctPHYS_ADDR internalPhysical;
151 gctPOINTER internalLogical;
152
153 /* External memory pool. */
154 gctSIZE_T externalSize;
155 gctPHYS_ADDR externalPhysical;
156 gctPOINTER externalLogical;
157
158 /* Contiguous memory pool. */
159 gctSIZE_T contiguousSize;
160 gctPHYS_ADDR contiguousPhysical;
161 gctPOINTER contiguousLogical;
162
163 /* EGL-specific process-wide objects. */
164 gctPOINTER eglDisplayInfo;
165 gctPOINTER eglSurfaceInfo;
166 gceSURF_FORMAT eglConfigFormat;
167
168 /* PLS reference count */
169 gcsATOM_PTR reference;
170
171 /* PorcessID of the constrcutor process */
172 gctUINT32 processID;
173
174 /* ThreadID of the constrcutor process. */
175 gctSIZE_T threadID;
176 /* Flag for calling module destructor. */
177 gctBOOL exiting;
178
179 gctBOOL bNeedSupportNP2Texture;
180
181 gctPLS_DESTRUCTOR destructor;
182 /* Mutex to guard PLS access. currently it's for EGL.
183 ** We can use this mutex for every PLS access.
184 */
185 gctPOINTER accessLock;
186}
187gcsPLS;
188
189extern gcsPLS gcPLS;
190
191#define gcPLS_INITIALIZER \
192{ \
193 gcvNULL, /* gcoOS object. */ \
194 gcvNULL, /* gcoHAL object. */ \
195 0, /* internalSize */ \
196 gcvNULL, /* internalPhysical */ \
197 gcvNULL, /* internalLogical */ \
198 0, /* externalSize */ \
199 gcvNULL, /* externalPhysical */ \
200 gcvNULL, /* externalLogical */ \
201 0, /* contiguousSize */ \
202 gcvNULL, /* contiguousPhysical */ \
203 gcvNULL, /* contiguousLogical */ \
204 gcvNULL, /* eglDisplayInfo */ \
205 gcvNULL, /* eglSurfaceInfo */ \
206 gcvSURF_A8R8G8B8,/* eglConfigFormat */ \
207 gcvNULL, /* reference */ \
208 0, /* processID */ \
209 0, /* threadID */ \
210 gcvFALSE, /* exiting */ \
211 gcvFALSE, /* Special flag for NP2 texture. */ \
212 gcvNULL, /* destructor */ \
213 gcvNULL, /* accessLock */ \
214}
215
216/******************************************************************************\
217******************************* Thread local storage *************************
218\******************************************************************************/
219
220typedef struct _gcsTLS * gcsTLS_PTR;
221
222typedef void (* gctTLS_DESTRUCTOR) (
223 gcsTLS_PTR
224 );
225
226typedef struct _gcsTLS
227{
228 gceHARDWARE_TYPE currentType;
229
230 /* Current 3D hardwre of this thread */
231 gcoHARDWARE currentHardware;
232
233 /* Default 3D hardware of this thread */
234 gcoHARDWARE defaultHardware;
235
236 /* Only for separated 3D and 2D */
237 gcoHARDWARE hardware2D;
238 gco2D engine2D;
239
240 /*thread data */
241 gctPOINTER context;
242 /* ES(including es1 and es2) client driver context which is current state */
243 gctPOINTER esClientCtx;
244 gctTLS_DESTRUCTOR destructor;
245
246 gctBOOL copied;
247
248 /* libGAL.so handle */
249 gctHANDLE handle;
250
251 /* If true, do not releas 2d engine and hardware in hal layer */
252 gctBOOL release2DUpper;
253}
254gcsTLS;
255
256/******************************************************************************\
257********************************* Enumerations *********************************
258\******************************************************************************/
259
260typedef enum _gcePLS_VALUE
261{
262 gcePLS_VALUE_EGL_DISPLAY_INFO,
263 gcePLS_VALUE_EGL_SURFACE_INFO,
264 gcePLS_VALUE_EGL_CONFIG_FORMAT_INFO,
265 gcePLS_VALUE_EGL_DESTRUCTOR_INFO,
266}
267gcePLS_VALUE;
268
269/* Video memory pool type. */
270typedef enum _gcePOOL
271{
272 gcvPOOL_UNKNOWN = 0,
273 gcvPOOL_DEFAULT,
274 gcvPOOL_LOCAL,
275 gcvPOOL_LOCAL_INTERNAL,
276 gcvPOOL_LOCAL_EXTERNAL,
277 gcvPOOL_UNIFIED,
278 gcvPOOL_SYSTEM,
279 gcvPOOL_VIRTUAL,
280 gcvPOOL_USER,
281 gcvPOOL_CONTIGUOUS,
282
283 gcvPOOL_NUMBER_OF_POOLS
284}
285gcePOOL;
286
287
288
289
290typedef enum _gceWHERE
291{
292 gcvWHERE_COMMAND,
293 gcvWHERE_RASTER,
294 gcvWHERE_PIXEL,
295}
296gceWHERE;
297
298typedef enum _gceHOW
299{
300 gcvHOW_SEMAPHORE = 0x1,
301 gcvHOW_STALL = 0x2,
302 gcvHOW_SEMAPHORE_STALL = 0x3,
303}
304gceHOW;
305
306typedef enum _gceSignalHandlerType
307{
308 gcvHANDLE_SIGFPE_WHEN_SIGNAL_CODE_IS_0 = 0x1,
309}
310gceSignalHandlerType;
311
312/* gcsHAL_Limits*/
313typedef struct _gcsHAL_LIMITS
314{
315 /* chip info */
316 gceCHIPMODEL chipModel;
317 gctUINT32 chipRevision;
318 gctUINT32 featureCount;
319 gctUINT32 *chipFeatures;
320
321 /* target caps */
322 gctUINT32 maxWidth;
323 gctUINT32 maxHeight;
324 gctUINT32 multiTargetCount;
325 gctUINT32 maxSamples;
326
327}gcsHAL_LIMITS;
328
329/******************************************************************************\
330*********** Generic Memory Allocation Optimization Using Containers ************
331\******************************************************************************/
332
333/* Generic container definition. */
334typedef struct _gcsCONTAINER_LINK * gcsCONTAINER_LINK_PTR;
335typedef struct _gcsCONTAINER_LINK
336{
337 /* Points to the next container. */
338 gcsCONTAINER_LINK_PTR next;
339}
340gcsCONTAINER_LINK;
341
342typedef struct _gcsCONTAINER_RECORD * gcsCONTAINER_RECORD_PTR;
343typedef struct _gcsCONTAINER_RECORD
344{
345 gcsCONTAINER_RECORD_PTR prev;
346 gcsCONTAINER_RECORD_PTR next;
347}
348gcsCONTAINER_RECORD;
349
350typedef struct _gcsCONTAINER * gcsCONTAINER_PTR;
351typedef struct _gcsCONTAINER
352{
353 gctUINT containerSize;
354 gctUINT recordSize;
355 gctUINT recordCount;
356 gcsCONTAINER_LINK_PTR containers;
357 gcsCONTAINER_RECORD freeList;
358 gcsCONTAINER_RECORD allocList;
359}
360gcsCONTAINER;
361
362#if gcdGC355_PROFILER
363/*------------------------GC355_PROFILER function node structure--------------*/
364typedef struct _gcsPROFILERFUNCData
365{
366 gctSTRING funcName;
367 gctSTRING Tag;
368 gctUINT TreeDepth;
369 gctUINT saveLayerTreeDepth;
370 gctUINT varTreeDepth;
371 gctUINT64 elapsedTime;
372 gctUINT64 cpuTime;
373 gctUINT64 gpuTime;
374}gcsPROFILERFUNCData;
375
376
377typedef struct _gcsPROFILERFUNCNODE
378{
379 gcsPROFILERFUNCData_PTR data;
380 gcsPROFILERFUNCNODE_PTR pre;
381 gcsPROFILERFUNCNODE_PTR next;
382}gcsPROFILERFUNCNODE;
383/*----------------------------------------------------------------------------*/
384#endif
385
386
387gceSTATUS
388gcsCONTAINER_Construct(
389 IN gcsCONTAINER_PTR Container,
390 gctUINT RecordsPerContainer,
391 gctUINT RecordSize
392 );
393
394gceSTATUS
395gcsCONTAINER_Destroy(
396 IN gcsCONTAINER_PTR Container
397 );
398
399gceSTATUS
400gcsCONTAINER_AllocateRecord(
401 IN gcsCONTAINER_PTR Container,
402 OUT gctPOINTER * Record
403 );
404
405gceSTATUS
406gcsCONTAINER_FreeRecord(
407 IN gcsCONTAINER_PTR Container,
408 IN gctPOINTER Record
409 );
410
411gceSTATUS
412gcsCONTAINER_FreeAll(
413 IN gcsCONTAINER_PTR Container
414 );
415
416/******************************************************************************\
417********************************* gcoHAL Object *********************************
418\******************************************************************************/
419
420/* Construct a new gcoHAL object. */
421gceSTATUS
422gcoHAL_ConstructEx(
423 IN gctPOINTER Context,
424 IN gcoOS Os,
425 OUT gcoHAL * Hal
426 );
427
428/* Destroy an gcoHAL object. */
429gceSTATUS
430gcoHAL_DestroyEx(
431 IN gcoHAL Hal
432 );
433
434/* Empty function for compatibility. */
435gceSTATUS
436gcoHAL_Construct(
437 IN gctPOINTER Context,
438 IN gcoOS Os,
439 OUT gcoHAL * Hal
440 );
441
442/* Empty function for compatibility. */
443gceSTATUS
444gcoHAL_Destroy(
445 IN gcoHAL Hal
446 );
447
448/* Get HAL options */
449gceSTATUS
450gcoHAL_GetOption(
451 IN gcoHAL Hal,
452 IN gceOPTION Option
453 );
454
455gceSTATUS
456gcoHAL_FrameInfoOps(
457 IN gcoHAL Hal,
458 IN gceFRAMEINFO FrameInfo,
459 IN gceFRAMEINFO_OP Op,
460 IN OUT gctUINT * Val
461 );
462
463
464gceSTATUS
465gcoHAL_GetHardware(
466 IN gcoHAL Hal,
467 OUT gcoHARDWARE* Hw
468 );
469
470/* Get pointer to gco2D object. */
471gceSTATUS
472gcoHAL_Get2DEngine(
473 IN gcoHAL Hal,
474 OUT gco2D * Engine
475 );
476
477
478
479gceSTATUS
480gcoHAL_GetProductName(
481 IN gcoHAL Hal,
482 OUT gctSTRING *ProductName
483 );
484
485gceSTATUS
486gcoHAL_SetFscaleValue(
487 IN gctUINT FscaleValue
488 );
489
490gceSTATUS
491gcoHAL_GetFscaleValue(
492 OUT gctUINT * FscaleValue,
493 OUT gctUINT * MinFscaleValue,
494 OUT gctUINT * MaxFscaleValue
495 );
496
497gceSTATUS
498gcoHAL_SetBltNP2Texture(
499 gctBOOL enable
500 );
501
502gceSTATUS
503gcoHAL_NameVideoMemory(
504 IN gctUINT32 Handle,
505 OUT gctUINT32 * Name
506 );
507
508gceSTATUS
509gcoHAL_ImportVideoMemory(
510 IN gctUINT32 Name,
511 OUT gctUINT32 * Handle
512 );
513
514gceSTATUS
515gcoHAL_GetVideoMemoryFd(
516 IN gctUINT32 Handle,
517 OUT gctINT * Fd
518 );
519
520/* Verify whether the specified feature is available in hardware. */
521gceSTATUS
522gcoHAL_IsFeatureAvailable(
523 IN gcoHAL Hal,
524 IN gceFEATURE Feature
525 );
526
527gceSTATUS
528gcoHAL_IsSwwaNeeded(
529 IN gcoHAL Hal,
530 IN gceSWWA Swwa
531 );
532
533gceSTATUS
534gcoHAL_IsFeatureAvailable1(
535 IN gcoHAL Hal,
536 IN gceFEATURE Feature
537 );
538
539/* Query the identity of the hardware. */
540gceSTATUS
541gcoHAL_QueryChipIdentity(
542 IN gcoHAL Hal,
543 OUT gceCHIPMODEL* ChipModel,
544 OUT gctUINT32* ChipRevision,
545 OUT gctUINT32* ChipFeatures,
546 OUT gctUINT32* ChipMinorFeatures
547 );
548
549/* Query the minor features of the hardware. */
550gceSTATUS gcoHAL_QueryChipMinorFeatures(
551 IN gcoHAL Hal,
552 OUT gctUINT32* NumFeatures,
553 OUT gctUINT32* ChipMinorFeatures
554 );
555
556gctINT32
557gcoOS_EndRecordAllocation(void);
558void
559gcoOS_RecordAllocation(void);
560void
561gcoOS_AddRecordAllocation(gctSIZE_T Size);
562
563/* Query the amount of video memory. */
564gceSTATUS
565gcoHAL_QueryVideoMemory(
566 IN gcoHAL Hal,
567 OUT gctPHYS_ADDR * InternalAddress,
568 OUT gctSIZE_T * InternalSize,
569 OUT gctPHYS_ADDR * ExternalAddress,
570 OUT gctSIZE_T * ExternalSize,
571 OUT gctPHYS_ADDR * ContiguousAddress,
572 OUT gctSIZE_T * ContiguousSize
573 );
574
575/* Map video memory. */
576gceSTATUS
577gcoHAL_MapMemory(
578 IN gcoHAL Hal,
579 IN gctPHYS_ADDR Physical,
580 IN gctSIZE_T NumberOfBytes,
581 OUT gctPOINTER * Logical
582 );
583
584/* Unmap video memory. */
585gceSTATUS
586gcoHAL_UnmapMemory(
587 IN gcoHAL Hal,
588 IN gctPHYS_ADDR Physical,
589 IN gctSIZE_T NumberOfBytes,
590 IN gctPOINTER Logical
591 );
592
593/* Schedule an unmap of a buffer mapped through its physical address. */
594gceSTATUS
595gcoHAL_ScheduleUnmapMemory(
596 IN gcoHAL Hal,
597 IN gctPHYS_ADDR Physical,
598 IN gctSIZE_T NumberOfBytes,
599 IN gctPOINTER Logical
600 );
601
602/* Allocate video memory. */
603gceSTATUS
604gcoOS_AllocateVideoMemory(
605 IN gcoOS Os,
606 IN gctBOOL InUserSpace,
607 IN gctBOOL InCacheable,
608 IN OUT gctSIZE_T * Bytes,
609 OUT gctUINT32 * Physical,
610 OUT gctPOINTER * Logical,
611 OUT gctPOINTER * Handle
612 );
613
614/* Free video memory. */
615gceSTATUS
616gcoOS_FreeVideoMemory(
617 IN gcoOS Os,
618 IN gctPOINTER Handle
619 );
620
621/* Lock video memory. */
622gceSTATUS
623gcoOS_LockVideoMemory(
624 IN gcoOS Os,
625 IN gctPOINTER Handle,
626 IN gctBOOL InUserSpace,
627 IN gctBOOL InCacheable,
628 OUT gctUINT32 * Physical,
629 OUT gctPOINTER * Logical
630 );
631
632/* Map user memory. */
633gceSTATUS
634gcoHAL_MapUserMemory(
635 IN gctPOINTER Logical,
636 IN gctUINT32 Physical,
637 IN gctSIZE_T Size,
638 OUT gctPOINTER * Info,
639 OUT gctUINT32_PTR GPUAddress
640 );
641
642/* Unmap user memory. */
643gceSTATUS
644gcoHAL_UnmapUserMemory(
645 IN gctPOINTER Logical,
646 IN gctSIZE_T Size,
647 IN gctPOINTER Info,
648 IN gctUINT32 GPUAddress
649 );
650
651/* Schedule an unmap of a user buffer using event mechanism. */
652gceSTATUS
653gcoHAL_ScheduleUnmapUserMemory(
654 IN gcoHAL Hal,
655 IN gctPOINTER Info,
656 IN gctSIZE_T Size,
657 IN gctUINT32 Address,
658 IN gctPOINTER Memory
659 );
660
661/* Commit the current command buffer. */
662gceSTATUS
663gcoHAL_Commit(
664 IN gcoHAL Hal,
665 IN gctBOOL Stall
666 );
667
668
669/* Query the tile capabilities. */
670gceSTATUS
671gcoHAL_QueryTiled(
672 IN gcoHAL Hal,
673 OUT gctINT32 * TileWidth2D,
674 OUT gctINT32 * TileHeight2D,
675 OUT gctINT32 * TileWidth3D,
676 OUT gctINT32 * TileHeight3D
677 );
678
679gceSTATUS
680gcoHAL_Compact(
681 IN gcoHAL Hal
682 );
683
684#if VIVANTE_PROFILER
685gceSTATUS
686gcoHAL_ProfileStart(
687 IN gcoHAL Hal
688 );
689
690gceSTATUS
691gcoHAL_ProfileEnd(
692 IN gcoHAL Hal,
693 IN gctCONST_STRING Title
694 );
695#endif
696
697/* Power Management */
698gceSTATUS
699gcoHAL_SetPowerManagementState(
700 IN gcoHAL Hal,
701 IN gceCHIPPOWERSTATE State
702 );
703
704gceSTATUS
705gcoHAL_QueryPowerManagementState(
706 IN gcoHAL Hal,
707 OUT gceCHIPPOWERSTATE *State
708 );
709
710/* Set the filter type for filter blit. */
711gceSTATUS
712gcoHAL_SetFilterType(
713 IN gcoHAL Hal,
714 IN gceFILTER_TYPE FilterType
715 );
716
717gceSTATUS
718gcoHAL_GetDump(
719 IN gcoHAL Hal,
720 OUT gcoDUMP * Dump
721 );
722
723/* Call the kernel HAL layer. */
724gceSTATUS
725gcoHAL_Call(
726 IN gcoHAL Hal,
727 IN OUT gcsHAL_INTERFACE_PTR Interface
728 );
729
730/* Schedule an event. */
731gceSTATUS
732gcoHAL_ScheduleEvent(
733 IN gcoHAL Hal,
734 IN OUT gcsHAL_INTERFACE_PTR Interface
735 );
736
737/* Destroy a surface. */
738gceSTATUS
739gcoHAL_DestroySurface(
740 IN gcoHAL Hal,
741 IN gcoSURF Surface
742 );
743
744/* Request a start/stop timestamp. */
745gceSTATUS
746gcoHAL_SetTimer(
747 IN gcoHAL Hal,
748 IN gctUINT32 Index,
749 IN gctBOOL Start
750 );
751
752/* Get Time delta from a Timer in microseconds. */
753gceSTATUS
754gcoHAL_GetTimerTime(
755 IN gcoHAL Hal,
756 IN gctUINT32 Timer,
757 OUT gctINT32_PTR TimeDelta
758 );
759
760/* set timeout value. */
761gceSTATUS
762gcoHAL_SetTimeOut(
763 IN gcoHAL Hal,
764 IN gctUINT32 timeOut
765 );
766
767gceSTATUS
768gcoHAL_SetHardwareType(
769 IN gcoHAL Hal,
770 IN gceHARDWARE_TYPE HardwardType
771 );
772
773gceSTATUS
774gcoHAL_GetHardwareType(
775 IN gcoHAL Hal,
776 OUT gceHARDWARE_TYPE * HardwardType
777 );
778
779gceSTATUS
780gcoHAL_QueryChipCount(
781 IN gcoHAL Hal,
782 OUT gctINT32 * Count
783 );
784
785gceSTATUS
786gcoHAL_Query3DCoreCount(
787 IN gcoHAL Hal,
788 OUT gctUINT32 *Count
789 );
790
791gceSTATUS
792gcoHAL_QuerySeparated2D(
793 IN gcoHAL Hal
794 );
795
796gceSTATUS
797gcoHAL_Is3DAvailable(
798 IN gcoHAL Hal
799 );
800
801/* Get pointer to gcoVG object. */
802gceSTATUS
803gcoHAL_GetVGEngine(
804 IN gcoHAL Hal,
805 OUT gcoVG * Engine
806 );
807
808gceSTATUS
809gcoHAL_QueryChipLimits(
810 IN gcoHAL Hal,
811 IN gctINT32 Chip,
812 IN gctINT32 Mask,
813 OUT gcsHAL_LIMITS *Limits);
814
815gceSTATUS
816gcoHAL_QueryChipFeature(
817 IN gcoHAL Hal,
818 IN gctINT32 Chip,
819 IN gctINT32 Mask,
820 IN gceFEATURE Feature);
821
822/*----------------------------------------------------------------------------*/
823/*----- Shared Buffer --------------------------------------------------------*/
824
825/* Create shared buffer. */
826gceSTATUS
827gcoHAL_CreateShBuffer(
828 IN gctUINT32 Size,
829 OUT gctSHBUF * ShBuf
830 );
831
832/* Destroy shared buffer. */
833gceSTATUS
834gcoHAL_DestroyShBuffer(
835 IN gctSHBUF ShBuf
836 );
837
838/* Map shared buffer to current process. */
839gceSTATUS
840gcoHAL_MapShBuffer(
841 IN gctSHBUF ShBuf
842 );
843
844/* Write user data to shared buffer. */
845gceSTATUS
846gcoHAL_WriteShBuffer(
847 IN gctSHBUF ShBuf,
848 IN gctCONST_POINTER Data,
849 IN gctUINT32 ByteCount
850 );
851
852/* Read user data from shared buffer. */
853gceSTATUS
854gcoHAL_ReadShBuffer(
855 IN gctSHBUF ShBuf,
856 IN gctPOINTER Data,
857 IN gctUINT32 BytesCount,
858 OUT gctUINT32 * BytesRead
859 );
860
861/* Config power management to be enabled or disabled. */
862gceSTATUS
863gcoHAL_ConfigPowerManagement(
864 IN gctBOOL Enable
865 );
866
867gceSTATUS
868gcoHAL_AllocateVideoMemory(
869 IN gctUINT Alignment,
870 IN gceSURF_TYPE Type,
871 IN gctUINT32 Flag,
872 IN gcePOOL Pool,
873 IN OUT gctSIZE_T * Bytes,
874 OUT gctUINT32_PTR Node
875 );
876
877gceSTATUS
878gcoHAL_LockVideoMemory(
879 IN gctUINT32 Node,
880 IN gctBOOL Cacheable,
881 OUT gctUINT32 * Physical,
882 OUT gctPOINTER * Logical
883 );
884
885gceSTATUS
886gcoHAL_UnlockVideoMemory(
887 IN gctUINT32 Node,
888 IN gceSURF_TYPE Type
889 );
890
891gceSTATUS
892 gcoHAL_ReleaseVideoMemory(
893 IN gctUINT32 Node
894 );
895
896
897gceSTATUS
898gcoHAL_WrapUserMemory(
899 IN gcsUSER_MEMORY_DESC_PTR UserMemoryDesc,
900 OUT gctUINT32_PTR Node
901 );
902
903/******************************************************************************\
904********************************** gcoOS Object *********************************
905\******************************************************************************/
906/* Lock PLS access */
907gceSTATUS
908gcoOS_LockPLS(
909 void
910 );
911
912/* Unlock PLS access */
913gceSTATUS
914gcoOS_UnLockPLS(
915 void
916 );
917
918/* Get PLS value for given key */
919gctPOINTER
920gcoOS_GetPLSValue(
921 IN gcePLS_VALUE key
922 );
923
924/* Set PLS value of a given key */
925void
926gcoOS_SetPLSValue(
927 IN gcePLS_VALUE key,
928 OUT gctPOINTER value
929 );
930
931/* Get access to the thread local storage. */
932gceSTATUS
933gcoOS_GetTLS(
934 OUT gcsTLS_PTR * TLS
935 );
936
937 /* Copy the TLS from a source thread. */
938 gceSTATUS gcoOS_CopyTLS(IN gcsTLS_PTR Source);
939
940/* Destroy the objects associated with the current thread. */
941void
942gcoOS_FreeThreadData(
943 void
944 );
945
946/* Empty function for compatibility. */
947gceSTATUS
948gcoOS_Construct(
949 IN gctPOINTER Context,
950 OUT gcoOS * Os
951 );
952
953/* Empty function for compatibility. */
954gceSTATUS
955gcoOS_Destroy(
956 IN gcoOS Os
957 );
958
959/* Get the base address for the physical memory. */
960gceSTATUS
961gcoOS_GetBaseAddress(
962 IN gcoOS Os,
963 OUT gctUINT32_PTR BaseAddress
964 );
965
966/* Allocate memory from the heap. */
967gceSTATUS
968gcoOS_Allocate(
969 IN gcoOS Os,
970 IN gctSIZE_T Bytes,
971 OUT gctPOINTER * Memory
972 );
973
974/* Get allocated memory size. */
975gceSTATUS
976gcoOS_GetMemorySize(
977 IN gcoOS Os,
978 IN gctPOINTER Memory,
979 OUT gctSIZE_T_PTR MemorySize
980 );
981
982/* Free allocated memory. */
983gceSTATUS
984gcoOS_Free(
985 IN gcoOS Os,
986 IN gctPOINTER Memory
987 );
988
989/* Allocate memory. */
990gceSTATUS
991gcoOS_AllocateSharedMemory(
992 IN gcoOS Os,
993 IN gctSIZE_T Bytes,
994 OUT gctPOINTER * Memory
995 );
996
997/* Free memory. */
998gceSTATUS
999gcoOS_FreeSharedMemory(
1000 IN gcoOS Os,
1001 IN gctPOINTER Memory
1002 );
1003
1004/* Allocate memory. */
1005gceSTATUS
1006gcoOS_AllocateMemory(
1007 IN gcoOS Os,
1008 IN gctSIZE_T Bytes,
1009 OUT gctPOINTER * Memory
1010 );
1011
1012/* Free memory. */
1013gceSTATUS
1014gcoOS_FreeMemory(
1015 IN gcoOS Os,
1016 IN gctPOINTER Memory
1017 );
1018
1019/* Allocate contiguous memory. */
1020gceSTATUS
1021gcoOS_AllocateContiguous(
1022 IN gcoOS Os,
1023 IN gctBOOL InUserSpace,
1024 IN OUT gctSIZE_T * Bytes,
1025 OUT gctPHYS_ADDR * Physical,
1026 OUT gctPOINTER * Logical
1027 );
1028
1029/* Free contiguous memory. */
1030gceSTATUS
1031gcoOS_FreeContiguous(
1032 IN gcoOS Os,
1033 IN gctPHYS_ADDR Physical,
1034 IN gctPOINTER Logical,
1035 IN gctSIZE_T Bytes
1036 );
1037
1038/* Map user memory. */
1039gceSTATUS
1040gcoOS_MapUserMemory(
1041 IN gcoOS Os,
1042 IN gctPOINTER Memory,
1043 IN gctSIZE_T Size,
1044 OUT gctPOINTER * Info,
1045 OUT gctUINT32_PTR Address
1046 );
1047
1048/* Map user memory. */
1049gceSTATUS
1050gcoOS_MapUserMemoryEx(
1051 IN gcoOS Os,
1052 IN gctPOINTER Memory,
1053 IN gctUINT32 Physical,
1054 IN gctSIZE_T Size,
1055 OUT gctPOINTER * Info,
1056 OUT gctUINT32_PTR Address
1057 );
1058
1059/* Unmap user memory. */
1060gceSTATUS
1061gcoOS_UnmapUserMemory(
1062 IN gcoOS Os,
1063 IN gctPOINTER Memory,
1064 IN gctSIZE_T Size,
1065 IN gctPOINTER Info,
1066 IN gctUINT32 Address
1067 );
1068
1069/* Device I/O Control call to the kernel HAL layer. */
1070gceSTATUS
1071gcoOS_DeviceControl(
1072 IN gcoOS Os,
1073 IN gctUINT32 IoControlCode,
1074 IN gctPOINTER InputBuffer,
1075 IN gctSIZE_T InputBufferSize,
1076 IN gctPOINTER OutputBuffer,
1077 IN gctSIZE_T OutputBufferSize
1078 );
1079
1080/* Allocate non paged memory. */
1081gceSTATUS
1082gcoOS_AllocateNonPagedMemory(
1083 IN gcoOS Os,
1084 IN gctBOOL InUserSpace,
1085 IN OUT gctSIZE_T * Bytes,
1086 OUT gctPHYS_ADDR * Physical,
1087 OUT gctPOINTER * Logical
1088 );
1089
1090/* Free non paged memory. */
1091gceSTATUS
1092gcoOS_FreeNonPagedMemory(
1093 IN gcoOS Os,
1094 IN gctSIZE_T Bytes,
1095 IN gctPHYS_ADDR Physical,
1096 IN gctPOINTER Logical
1097 );
1098
1099#define gcmOS_SAFE_FREE(os, mem) \
1100 gcoOS_Free(os, mem); \
1101 mem = gcvNULL
1102
1103#define gcmOS_SAFE_FREE_SHARED_MEMORY(os, mem) \
1104 gcoOS_FreeSharedMemory(os, mem); \
1105 mem = gcvNULL
1106
1107#define gcmkOS_SAFE_FREE(os, mem) \
1108 gckOS_Free(os, mem); \
1109 mem = gcvNULL
1110
1111#define gcdMAX_PATH 512
1112
1113typedef enum _gceFILE_MODE
1114{
1115 gcvFILE_CREATE = 0,
1116 gcvFILE_APPEND,
1117 gcvFILE_READ,
1118 gcvFILE_CREATETEXT,
1119 gcvFILE_APPENDTEXT,
1120 gcvFILE_READTEXT,
1121}
1122gceFILE_MODE;
1123
1124/* Open a file. */
1125gceSTATUS
1126gcoOS_Open(
1127 IN gcoOS Os,
1128 IN gctCONST_STRING FileName,
1129 IN gceFILE_MODE Mode,
1130 OUT gctFILE * File
1131 );
1132
1133/* Close a file. */
1134gceSTATUS
1135gcoOS_Close(
1136 IN gcoOS Os,
1137 IN gctFILE File
1138 );
1139
1140/* Read data from a file. */
1141gceSTATUS
1142gcoOS_Read(
1143 IN gcoOS Os,
1144 IN gctFILE File,
1145 IN gctSIZE_T ByteCount,
1146 IN gctPOINTER Data,
1147 OUT gctSIZE_T * ByteRead
1148 );
1149
1150/* Write data to a file. */
1151gceSTATUS
1152gcoOS_Write(
1153 IN gcoOS Os,
1154 IN gctFILE File,
1155 IN gctSIZE_T ByteCount,
1156 IN gctCONST_POINTER Data
1157 );
1158
1159/* Flush data to a file. */
1160gceSTATUS
1161gcoOS_Flush(
1162 IN gcoOS Os,
1163 IN gctFILE File
1164 );
1165
1166/* Close a file descriptor. */
1167gceSTATUS
1168gcoOS_CloseFD(
1169 IN gcoOS Os,
1170 IN gctINT FD
1171 );
1172
1173/* Scan a file. */
1174gceSTATUS
1175gcoOS_FscanfI(
1176 IN gcoOS Os,
1177 IN gctFILE File,
1178 IN gctCONST_STRING Format,
1179 OUT gctUINT *result
1180 );
1181
1182/* Dup file descriptor to another. */
1183gceSTATUS
1184gcoOS_DupFD(
1185 IN gcoOS Os,
1186 IN gctINT FD,
1187 OUT gctINT * FD2
1188 );
1189
1190/* Create an endpoint for communication. */
1191gceSTATUS
1192gcoOS_Socket(
1193 IN gcoOS Os,
1194 IN gctINT Domain,
1195 IN gctINT Type,
1196 IN gctINT Protocol,
1197 OUT gctINT *SockFd
1198 );
1199
1200/* Close a socket. */
1201gceSTATUS
1202gcoOS_CloseSocket(
1203 IN gcoOS Os,
1204 IN gctINT SockFd
1205 );
1206
1207/* Initiate a connection on a socket. */
1208gceSTATUS
1209gcoOS_Connect(
1210 IN gcoOS Os,
1211 IN gctINT SockFd,
1212 IN gctCONST_POINTER HostName,
1213 IN gctUINT Port);
1214
1215/* Shut down part of connection on a socket. */
1216gceSTATUS
1217gcoOS_Shutdown(
1218 IN gcoOS Os,
1219 IN gctINT SockFd,
1220 IN gctINT How
1221 );
1222
1223/* Send a message on a socket. */
1224gceSTATUS
1225gcoOS_Send(
1226 IN gcoOS Os,
1227 IN gctINT SockFd,
1228 IN gctSIZE_T ByteCount,
1229 IN gctCONST_POINTER Data,
1230 IN gctINT Flags
1231 );
1232
1233/* Initiate a connection on a socket. */
1234gceSTATUS
1235gcoOS_WaitForSend(
1236 IN gcoOS Os,
1237 IN gctINT SockFd,
1238 IN gctINT Seconds,
1239 IN gctINT MicroSeconds);
1240
1241/* Get environment variable value. */
1242gceSTATUS
1243gcoOS_GetEnv(
1244 IN gcoOS Os,
1245 IN gctCONST_STRING VarName,
1246 OUT gctSTRING * Value
1247 );
1248
1249/* Set environment variable value. */
1250gceSTATUS
1251gcoOS_SetEnv(
1252 IN gcoOS Os,
1253 IN gctCONST_STRING VarName,
1254 IN gctSTRING Value
1255 );
1256
1257/* Get current working directory. */
1258gceSTATUS
1259gcoOS_GetCwd(
1260 IN gcoOS Os,
1261 IN gctINT SizeInBytes,
1262 OUT gctSTRING Buffer
1263 );
1264
1265/* Get file status info. */
1266gceSTATUS
1267gcoOS_Stat(
1268 IN gcoOS Os,
1269 IN gctCONST_STRING FileName,
1270 OUT gctPOINTER Buffer
1271 );
1272
1273typedef enum _gceFILE_WHENCE
1274{
1275 gcvFILE_SEEK_SET,
1276 gcvFILE_SEEK_CUR,
1277 gcvFILE_SEEK_END
1278}
1279gceFILE_WHENCE;
1280
1281/* Set the current position of a file. */
1282gceSTATUS
1283gcoOS_Seek(
1284 IN gcoOS Os,
1285 IN gctFILE File,
1286 IN gctUINT32 Offset,
1287 IN gceFILE_WHENCE Whence
1288 );
1289
1290/* Set the current position of a file. */
1291gceSTATUS
1292gcoOS_SetPos(
1293 IN gcoOS Os,
1294 IN gctFILE File,
1295 IN gctUINT32 Position
1296 );
1297
1298/* Get the current position of a file. */
1299gceSTATUS
1300gcoOS_GetPos(
1301 IN gcoOS Os,
1302 IN gctFILE File,
1303 OUT gctUINT32 * Position
1304 );
1305
1306/* Same as strstr. */
1307gceSTATUS
1308gcoOS_StrStr(
1309 IN gctCONST_STRING String,
1310 IN gctCONST_STRING SubString,
1311 OUT gctSTRING * Output
1312 );
1313
1314/* Find the last occurance of a character inside a string. */
1315gceSTATUS
1316gcoOS_StrFindReverse(
1317 IN gctCONST_STRING String,
1318 IN gctINT8 Character,
1319 OUT gctSTRING * Output
1320 );
1321
1322gceSTATUS
1323gcoOS_StrDup(
1324 IN gcoOS Os,
1325 IN gctCONST_STRING String,
1326 OUT gctSTRING * Target
1327 );
1328
1329/* Copy a string. */
1330gceSTATUS
1331gcoOS_StrCopySafe(
1332 IN gctSTRING Destination,
1333 IN gctSIZE_T DestinationSize,
1334 IN gctCONST_STRING Source
1335 );
1336
1337/* Append a string. */
1338gceSTATUS
1339gcoOS_StrCatSafe(
1340 IN gctSTRING Destination,
1341 IN gctSIZE_T DestinationSize,
1342 IN gctCONST_STRING Source
1343 );
1344
1345/* Compare two strings. */
1346gceSTATUS
1347gcoOS_StrCmp(
1348 IN gctCONST_STRING String1,
1349 IN gctCONST_STRING String2
1350 );
1351
1352/* Compare characters of two strings. */
1353gceSTATUS
1354gcoOS_StrNCmp(
1355 IN gctCONST_STRING String1,
1356 IN gctCONST_STRING String2,
1357 IN gctSIZE_T Count
1358 );
1359
1360/* Convert string to float. */
1361gceSTATUS
1362gcoOS_StrToFloat(
1363 IN gctCONST_STRING String,
1364 OUT gctFLOAT * Float
1365 );
1366
1367/* Convert hex string to integer. */
1368gceSTATUS gcoOS_HexStrToInt(
1369 IN gctCONST_STRING String,
1370 OUT gctINT * Int
1371 );
1372
1373/* Convert hex string to float. */
1374gceSTATUS
1375gcoOS_HexStrToFloat(
1376 IN gctCONST_STRING String,
1377 OUT gctFLOAT * Float
1378 );
1379
1380/* Convert string to integer. */
1381gceSTATUS
1382gcoOS_StrToInt(
1383 IN gctCONST_STRING String,
1384 OUT gctINT * Int
1385 );
1386
1387gceSTATUS
1388gcoOS_MemCmp(
1389 IN gctCONST_POINTER Memory1,
1390 IN gctCONST_POINTER Memory2,
1391 IN gctSIZE_T Bytes
1392 );
1393
1394gceSTATUS
1395gcoOS_PrintStrSafe(
1396 OUT gctSTRING String,
1397 IN gctSIZE_T StringSize,
1398 IN OUT gctUINT * Offset,
1399 IN gctCONST_STRING Format,
1400 ...
1401 );
1402
1403gceSTATUS
1404gcoOS_LoadLibrary(
1405 IN gcoOS Os,
1406 IN gctCONST_STRING Library,
1407 OUT gctHANDLE * Handle
1408 );
1409
1410gceSTATUS
1411gcoOS_FreeLibrary(
1412 IN gcoOS Os,
1413 IN gctHANDLE Handle
1414 );
1415
1416gceSTATUS
1417gcoOS_GetProcAddress(
1418 IN gcoOS Os,
1419 IN gctHANDLE Handle,
1420 IN gctCONST_STRING Name,
1421 OUT gctPOINTER * Function
1422 );
1423
1424gceSTATUS
1425gcoOS_Compact(
1426 IN gcoOS Os
1427 );
1428
1429gceSTATUS
1430gcoOS_AddSignalHandler (
1431 IN gceSignalHandlerType SignalHandlerType
1432 );
1433
1434#if VIVANTE_PROFILER
1435gceSTATUS
1436gcoOS_ProfileStart(
1437 IN gcoOS Os
1438 );
1439
1440gceSTATUS
1441gcoOS_ProfileEnd(
1442 IN gcoOS Os,
1443 IN gctCONST_STRING Title
1444 );
1445
1446gceSTATUS
1447gcoOS_SetProfileSetting(
1448 IN gcoOS Os,
1449 IN gctBOOL Enable,
1450 IN gctCONST_STRING FileName
1451 );
1452#endif
1453
1454/* Query the video memory. */
1455gceSTATUS
1456gcoOS_QueryVideoMemory(
1457 IN gcoOS Os,
1458 OUT gctPHYS_ADDR * InternalAddress,
1459 OUT gctSIZE_T * InternalSize,
1460 OUT gctPHYS_ADDR * ExternalAddress,
1461 OUT gctSIZE_T * ExternalSize,
1462 OUT gctPHYS_ADDR * ContiguousAddress,
1463 OUT gctSIZE_T * ContiguousSize
1464 );
1465
1466gceSTATUS
1467gcoOS_QueryCurrentProcessName(
1468 OUT gctSTRING Name,
1469 IN gctSIZE_T Size
1470 );
1471
1472/* Detect if the current process is the executable specified. */
1473gceSTATUS
1474gcoOS_DetectProcessByName(
1475 IN gctCONST_STRING Name
1476 );
1477
1478gceSTATUS
1479gcoOS_DetectProcessByEncryptedName(
1480 IN gctCONST_STRING Name
1481 );
1482
1483#if defined(ANDROID)
1484gceSTATUS
1485gcoOS_DetectProgrameByEncryptedSymbols(
1486 IN gcoOS_SymbolsList Symbols
1487 );
1488#endif
1489
1490/*----------------------------------------------------------------------------*/
1491/*----- Atoms ----------------------------------------------------------------*/
1492
1493/* Construct an atom. */
1494gceSTATUS
1495gcoOS_AtomConstruct(
1496 IN gcoOS Os,
1497 OUT gcsATOM_PTR * Atom
1498 );
1499
1500/* Destroy an atom. */
1501gceSTATUS
1502gcoOS_AtomDestroy(
1503 IN gcoOS Os,
1504 IN gcsATOM_PTR Atom
1505 );
1506
1507/* Get the 32-bit value protected by an atom. */
1508gceSTATUS
1509gcoOS_AtomGet(
1510 IN gcoOS Os,
1511 IN gcsATOM_PTR Atom,
1512 OUT gctINT32_PTR Value
1513 );
1514
1515/* Set the 32-bit value protected by an atom. */
1516gceSTATUS
1517gcoOS_AtomSet(
1518 IN gcoOS Os,
1519 IN gcsATOM_PTR Atom,
1520 IN gctINT32 Value
1521 );
1522
1523/* Increment an atom. */
1524gceSTATUS
1525gcoOS_AtomIncrement(
1526 IN gcoOS Os,
1527 IN gcsATOM_PTR Atom,
1528 OUT gctINT32_PTR OldValue
1529 );
1530
1531/* Decrement an atom. */
1532gceSTATUS
1533gcoOS_AtomDecrement(
1534 IN gcoOS Os,
1535 IN gcsATOM_PTR Atom,
1536 OUT gctINT32_PTR OldValue
1537 );
1538
1539gctHANDLE
1540gcoOS_GetCurrentProcessID(
1541 void
1542 );
1543
1544gctHANDLE
1545gcoOS_GetCurrentThreadID(
1546 void
1547 );
1548
1549/*----------------------------------------------------------------------------*/
1550/*----- Time -----------------------------------------------------------------*/
1551
1552/* Get the number of milliseconds since the system started. */
1553gctUINT32
1554gcoOS_GetTicks(
1555 void
1556 );
1557
1558/* Get time in microseconds. */
1559gceSTATUS
1560gcoOS_GetTime(
1561 gctUINT64_PTR Time
1562 );
1563
1564/* Get CPU usage in microseconds. */
1565gceSTATUS
1566gcoOS_GetCPUTime(
1567 gctUINT64_PTR CPUTime
1568 );
1569
1570/* Get memory usage. */
1571gceSTATUS
1572gcoOS_GetMemoryUsage(
1573 gctUINT32_PTR MaxRSS,
1574 gctUINT32_PTR IxRSS,
1575 gctUINT32_PTR IdRSS,
1576 gctUINT32_PTR IsRSS
1577 );
1578
1579/* Delay a number of microseconds. */
1580gceSTATUS
1581gcoOS_Delay(
1582 IN gcoOS Os,
1583 IN gctUINT32 Delay
1584 );
1585
1586/*----------------------------------------------------------------------------*/
1587/*----- Threads --------------------------------------------------------------*/
1588
1589#ifdef _WIN32
1590/* Cannot include windows.h here becuase "near" and "far"
1591 * which are used in gcsDEPTH_INFO, are defined to nothing in WinDef.h.
1592 * So, use the real value of DWORD and WINAPI, instead.
1593 * DWORD is unsigned long, and WINAPI is __stdcall.
1594 * If these two are change in WinDef.h, the following two typdefs
1595 * need to be changed, too.
1596 */
1597typedef unsigned long gctTHREAD_RETURN;
1598typedef unsigned long (__stdcall * gcTHREAD_ROUTINE)(void * Argument);
1599#else
1600typedef void * gctTHREAD_RETURN;
1601typedef void * (* gcTHREAD_ROUTINE)(void *);
1602#endif
1603
1604/* Create a new thread. */
1605gceSTATUS
1606gcoOS_CreateThread(
1607 IN gcoOS Os,
1608 IN gcTHREAD_ROUTINE Worker,
1609 IN gctPOINTER Argument,
1610 OUT gctPOINTER * Thread
1611 );
1612
1613/* Close a thread. */
1614gceSTATUS
1615gcoOS_CloseThread(
1616 IN gcoOS Os,
1617 IN gctPOINTER Thread
1618 );
1619
1620/*----------------------------------------------------------------------------*/
1621/*----- Mutexes --------------------------------------------------------------*/
1622
1623/* Create a new mutex. */
1624gceSTATUS
1625gcoOS_CreateMutex(
1626 IN gcoOS Os,
1627 OUT gctPOINTER * Mutex
1628 );
1629
1630/* Delete a mutex. */
1631gceSTATUS
1632gcoOS_DeleteMutex(
1633 IN gcoOS Os,
1634 IN gctPOINTER Mutex
1635 );
1636
1637/* Acquire a mutex. */
1638gceSTATUS
1639gcoOS_AcquireMutex(
1640 IN gcoOS Os,
1641 IN gctPOINTER Mutex,
1642 IN gctUINT32 Timeout
1643 );
1644
1645/* Release a mutex. */
1646gceSTATUS
1647gcoOS_ReleaseMutex(
1648 IN gcoOS Os,
1649 IN gctPOINTER Mutex
1650 );
1651
1652/*----------------------------------------------------------------------------*/
1653/*----- Signals --------------------------------------------------------------*/
1654
1655/* Create a signal. */
1656gceSTATUS
1657gcoOS_CreateSignal(
1658 IN gcoOS Os,
1659 IN gctBOOL ManualReset,
1660 OUT gctSIGNAL * Signal
1661 );
1662
1663/* Destroy a signal. */
1664gceSTATUS
1665gcoOS_DestroySignal(
1666 IN gcoOS Os,
1667 IN gctSIGNAL Signal
1668 );
1669
1670/* Signal a signal. */
1671gceSTATUS
1672gcoOS_Signal(
1673 IN gcoOS Os,
1674 IN gctSIGNAL Signal,
1675 IN gctBOOL State
1676 );
1677
1678/* Wait for a signal. */
1679gceSTATUS
1680gcoOS_WaitSignal(
1681 IN gcoOS Os,
1682 IN gctSIGNAL Signal,
1683 IN gctUINT32 Wait
1684 );
1685
1686/* Map a signal from another process */
1687gceSTATUS
1688gcoOS_MapSignal(
1689 IN gctSIGNAL RemoteSignal,
1690 OUT gctSIGNAL * LocalSignal
1691 );
1692
1693/* Unmap a signal mapped from another process */
1694gceSTATUS
1695gcoOS_UnmapSignal(
1696 IN gctSIGNAL Signal
1697 );
1698
1699/*----------------------------------------------------------------------------*/
1700/*----- Android Native Fence -------------------------------------------------*/
1701
1702/* Create sync point. */
1703gceSTATUS
1704gcoOS_CreateSyncPoint(
1705 IN gcoOS Os,
1706 OUT gctSYNC_POINT * SyncPoint
1707 );
1708
1709/* Destroy sync point. */
1710gceSTATUS
1711gcoOS_DestroySyncPoint(
1712 IN gcoOS Os,
1713 IN gctSYNC_POINT SyncPoint
1714 );
1715
1716/* Create native fence. */
1717gceSTATUS
1718gcoOS_CreateNativeFence(
1719 IN gcoOS Os,
1720 IN gctSYNC_POINT SyncPoint,
1721 OUT gctINT * FenceFD
1722 );
1723
1724/* (CPU) Wait on native fence. */
1725gceSTATUS
1726gcoOS_ClientWaitNativeFence(
1727 IN gcoOS Os,
1728 IN gctINT FenceFD,
1729 IN gctUINT32 Timeout
1730 );
1731
1732/* (GPU) Wait on native fence. */
1733gceSTATUS
1734gcoOS_WaitNativeFence(
1735 IN gcoOS Os,
1736 IN gctINT FenceFD,
1737 IN gctUINT32 Timeout
1738 );
1739
1740/*----------------------------------------------------------------------------*/
1741/*----- Memory Access and Cache ----------------------------------------------*/
1742
1743/* Write a register. */
1744gceSTATUS
1745gcoOS_WriteRegister(
1746 IN gcoOS Os,
1747 IN gctUINT32 Address,
1748 IN gctUINT32 Data
1749 );
1750
1751/* Read a register. */
1752gceSTATUS
1753gcoOS_ReadRegister(
1754 IN gcoOS Os,
1755 IN gctUINT32 Address,
1756 OUT gctUINT32 * Data
1757 );
1758
1759gceSTATUS
1760gcoOS_CacheClean(
1761 IN gcoOS Os,
1762 IN gctUINT32 Node,
1763 IN gctPOINTER Logical,
1764 IN gctSIZE_T Bytes
1765 );
1766
1767gceSTATUS
1768gcoOS_CacheFlush(
1769 IN gcoOS Os,
1770 IN gctUINT32 Node,
1771 IN gctPOINTER Logical,
1772 IN gctSIZE_T Bytes
1773 );
1774
1775gceSTATUS
1776gcoOS_CacheInvalidate(
1777 IN gcoOS Os,
1778 IN gctUINT32 Node,
1779 IN gctPOINTER Logical,
1780 IN gctSIZE_T Bytes
1781 );
1782
1783gceSTATUS
1784gcoOS_MemoryBarrier(
1785 IN gcoOS Os,
1786 IN gctPOINTER Logical
1787 );
1788
1789gceSTATUS
1790gcoOS_CPUPhysicalToGPUPhysical(
1791 IN gctUINT32 CPUPhysical,
1792 OUT gctUINT32_PTR GPUPhysical
1793 );
1794
1795/*----------------------------------------------------------------------------*/
1796/*----- Profile --------------------------------------------------------------*/
1797
1798gceSTATUS
1799gckOS_GetProfileTick(
1800 OUT gctUINT64_PTR Tick
1801 );
1802
1803gceSTATUS
1804gckOS_QueryProfileTickRate(
1805 OUT gctUINT64_PTR TickRate
1806 );
1807
1808gctUINT32
1809gckOS_ProfileToMS(
1810 IN gctUINT64 Ticks
1811 );
1812
1813gceSTATUS
1814gcoOS_GetProfileTick(
1815 OUT gctUINT64_PTR Tick
1816 );
1817
1818gceSTATUS
1819gcoOS_QueryProfileTickRate(
1820 OUT gctUINT64_PTR TickRate
1821 );
1822
1823#define _gcmPROFILE_INIT(prefix, freq, start) \
1824 do { \
1825 prefix ## OS_QueryProfileTickRate(&(freq)); \
1826 prefix ## OS_GetProfileTick(&(start)); \
1827 } while (gcvFALSE)
1828
1829#define _gcmPROFILE_QUERY(prefix, start, ticks) \
1830 do { \
1831 prefix ## OS_GetProfileTick(&(ticks)); \
1832 (ticks) = ((ticks) > (start)) ? ((ticks) - (start)) \
1833 : (~0ull - (start) + (ticks) + 1); \
1834 } while (gcvFALSE)
1835
1836#if gcdENABLE_PROFILING
1837# define gcmkPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gck, freq, start)
1838# define gcmkPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gck, start, ticks)
1839# define gcmPROFILE_INIT(freq, start) _gcmPROFILE_INIT(gco, freq, start)
1840# define gcmPROFILE_QUERY(start, ticks) _gcmPROFILE_QUERY(gco, start, ticks)
1841# define gcmPROFILE_ONLY(x) x
1842# define gcmPROFILE_ELSE(x) do { } while (gcvFALSE)
1843# define gcmPROFILE_DECLARE_ONLY(x) x
1844# define gcmPROFILE_DECLARE_ELSE(x) typedef x
1845#else
1846# define gcmkPROFILE_INIT(start, freq) do { } while (gcvFALSE)
1847# define gcmkPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
1848# define gcmPROFILE_INIT(start, freq) do { } while (gcvFALSE)
1849# define gcmPROFILE_QUERY(start, ticks) do { } while (gcvFALSE)
1850# define gcmPROFILE_ONLY(x) do { } while (gcvFALSE)
1851# define gcmPROFILE_ELSE(x) x
1852# define gcmPROFILE_DECLARE_ONLY(x) do { } while (gcvFALSE)
1853# define gcmPROFILE_DECLARE_ELSE(x) x
1854#endif
1855
1856/*******************************************************************************
1857** gcoMATH object
1858*/
1859
1860#define gcdPI 3.14159265358979323846f
1861
1862/* Kernel. */
1863gctINT
1864gckMATH_ModuloInt(
1865 IN gctINT X,
1866 IN gctINT Y
1867 );
1868
1869/* User. */
1870gctUINT32
1871gcoMATH_Log2in5dot5(
1872 IN gctINT X
1873 );
1874
1875
1876gctFLOAT
1877gcoMATH_UIntAsFloat(
1878 IN gctUINT32 X
1879 );
1880
1881gctUINT32
1882gcoMATH_FloatAsUInt(
1883 IN gctFLOAT X
1884 );
1885
1886gctBOOL
1887gcoMATH_CompareEqualF(
1888 IN gctFLOAT X,
1889 IN gctFLOAT Y
1890 );
1891
1892gctUINT16
1893gcoMATH_UInt8AsFloat16(
1894 IN gctUINT8 X
1895 );
1896
1897gctUINT32
1898gcoMATH_Float16ToFloat(
1899 IN gctUINT16 In
1900 );
1901
1902gctUINT16
1903gcoMATH_FloatToFloat16(
1904 IN gctUINT32 In
1905 );
1906
1907gctUINT32
1908gcoMATH_Float11ToFloat(
1909 IN gctUINT32 In
1910 );
1911
1912gctUINT16
1913gcoMATH_FloatToFloat11(
1914 IN gctUINT32 In
1915 );
1916
1917gctUINT32
1918gcoMATH_Float10ToFloat(
1919 IN gctUINT32 In
1920 );
1921
1922gctUINT16
1923gcoMATH_FloatToFloat10(
1924 IN gctUINT32 In
1925 );
1926
1927gctUINT32
1928gcoMATH_Float14ToFloat(
1929 IN gctUINT16 In
1930 );
1931
1932/******************************************************************************\
1933**************************** Coordinate Structures *****************************
1934\******************************************************************************/
1935
1936typedef struct _gcsPOINT
1937{
1938 gctINT32 x;
1939 gctINT32 y;
1940}
1941gcsPOINT;
1942
1943typedef struct _gcsSIZE
1944{
1945 gctINT32 width;
1946 gctINT32 height;
1947}
1948gcsSIZE;
1949
1950typedef struct _gcsRECT
1951{
1952 gctINT32 left;
1953 gctINT32 top;
1954 gctINT32 right;
1955 gctINT32 bottom;
1956}
1957gcsRECT;
1958
1959typedef union _gcsPIXEL
1960{
1961 struct
1962 {
1963 gctFLOAT r, g, b, a;
1964 gctFLOAT d, s;
1965 } pf;
1966
1967 struct
1968 {
1969 gctINT32 r, g, b, a;
1970 gctINT32 d, s;
1971 } pi;
1972
1973 struct
1974 {
1975 gctUINT32 r, g, b, a;
1976 gctUINT32 d, s;
1977 } pui;
1978
1979} gcsPIXEL;
1980
1981/******************************************************************************\
1982********************************* gcoSURF Object ********************************
1983\******************************************************************************/
1984
1985/*----------------------------------------------------------------------------*/
1986/*------------------------------- gcoSURF Common ------------------------------*/
1987
1988/* Color format classes. */
1989typedef enum _gceFORMAT_CLASS
1990{
1991 gcvFORMAT_CLASS_RGBA = 4500,
1992 gcvFORMAT_CLASS_YUV,
1993 gcvFORMAT_CLASS_INDEX,
1994 gcvFORMAT_CLASS_LUMINANCE,
1995 gcvFORMAT_CLASS_BUMP,
1996 gcvFORMAT_CLASS_DEPTH,
1997 gcvFORMAT_CLASS_ASTC,
1998 gcvFORMAT_CLASS_OTHER
1999}
2000gceFORMAT_CLASS;
2001
2002/* Color format data type */
2003typedef enum _gceFORMAT_DATATYPE
2004{
2005 gcvFORMAT_DATATYPE_UNSIGNED_NORMALIZED,
2006 gcvFORMAT_DATATYPE_SIGNED_NORMALIZED,
2007 gcvFORMAT_DATATYPE_UNSIGNED_INTEGER,
2008 gcvFORMAT_DATATYPE_SIGNED_INTEGER,
2009 gcvFORMAT_DATATYPE_FLOAT16,
2010 gcvFORMAT_DATATYPE_FLOAT32,
2011 gcvFORMAT_DATATYPE_FLOAT_E5B9G9R9,
2012 gcvFORMAT_DATATYPE_FLOAT_B10G11R11F,
2013 gcvFORMAT_DATATYPE_INDEX,
2014 gcvFORMAT_DATATYPE_SRGB,
2015 gcvFORMAT_DATATYPE_FLOAT32_UINT,
2016}
2017gceFORMAT_DATATYPE;
2018
2019/* Special enums for width field in gcsFORMAT_COMPONENT. */
2020typedef enum _gceCOMPONENT_CONTROL
2021{
2022 gcvCOMPONENT_NOTPRESENT = 0x00,
2023 gcvCOMPONENT_DONTCARE = 0x80,
2024 gcvCOMPONENT_WIDTHMASK = 0x7F,
2025 gcvCOMPONENT_ODD = 0x80
2026}
2027gceCOMPONENT_CONTROL;
2028
2029/* Color format component parameters. */
2030typedef struct _gcsFORMAT_COMPONENT
2031{
2032 gctUINT8 start;
2033 gctUINT8 width;
2034}
2035gcsFORMAT_COMPONENT;
2036
2037/* RGBA color format class. */
2038typedef struct _gcsFORMAT_CLASS_TYPE_RGBA
2039{
2040 gcsFORMAT_COMPONENT alpha;
2041 gcsFORMAT_COMPONENT red;
2042 gcsFORMAT_COMPONENT green;
2043 gcsFORMAT_COMPONENT blue;
2044}
2045gcsFORMAT_CLASS_TYPE_RGBA;
2046
2047/* YUV color format class. */
2048typedef struct _gcsFORMAT_CLASS_TYPE_YUV
2049{
2050 gcsFORMAT_COMPONENT y;
2051 gcsFORMAT_COMPONENT u;
2052 gcsFORMAT_COMPONENT v;
2053}
2054gcsFORMAT_CLASS_TYPE_YUV;
2055
2056/* Index color format class. */
2057typedef struct _gcsFORMAT_CLASS_TYPE_INDEX
2058{
2059 gcsFORMAT_COMPONENT value;
2060}
2061gcsFORMAT_CLASS_TYPE_INDEX;
2062
2063/* Luminance color format class. */
2064typedef struct _gcsFORMAT_CLASS_TYPE_LUMINANCE
2065{
2066 gcsFORMAT_COMPONENT alpha;
2067 gcsFORMAT_COMPONENT value;
2068}
2069gcsFORMAT_CLASS_TYPE_LUMINANCE;
2070
2071/* Bump map color format class. */
2072typedef struct _gcsFORMAT_CLASS_TYPE_BUMP
2073{
2074 gcsFORMAT_COMPONENT alpha;
2075 gcsFORMAT_COMPONENT l;
2076 gcsFORMAT_COMPONENT v;
2077 gcsFORMAT_COMPONENT u;
2078 gcsFORMAT_COMPONENT q;
2079 gcsFORMAT_COMPONENT w;
2080}
2081gcsFORMAT_CLASS_TYPE_BUMP;
2082
2083/* Depth and stencil format class. */
2084typedef struct _gcsFORMAT_CLASS_TYPE_DEPTH
2085{
2086 gcsFORMAT_COMPONENT depth;
2087 gcsFORMAT_COMPONENT stencil;
2088}
2089gcsFORMAT_CLASS_TYPE_DEPTH;
2090
2091typedef union _gcuPIXEL_FORMAT_CLASS
2092{
2093 gcsFORMAT_CLASS_TYPE_BUMP bump;
2094 gcsFORMAT_CLASS_TYPE_RGBA rgba;
2095 gcsFORMAT_CLASS_TYPE_YUV yuv;
2096 gcsFORMAT_CLASS_TYPE_LUMINANCE lum;
2097 gcsFORMAT_CLASS_TYPE_INDEX index;
2098 gcsFORMAT_CLASS_TYPE_DEPTH depth;
2099}
2100gcuPIXEL_FORMAT_CLASS;
2101
2102/* Format parameters. */
2103typedef struct _gcsSURF_FORMAT_INFO
2104{
2105 /* Name of the format */
2106 gctCONST_STRING formatName;
2107
2108 /* Format code and class. */
2109 gceSURF_FORMAT format;
2110 gceFORMAT_CLASS fmtClass;
2111
2112 /* Format data type */
2113 gceFORMAT_DATATYPE fmtDataType;
2114
2115 /* The size of one pixel in bits. */
2116 gctUINT8 bitsPerPixel;
2117
2118 /* Pixel block dimensions. */
2119 gctUINT blockWidth;
2120 gctUINT blockHeight;
2121
2122 /* Pixel block size in bits. */
2123 gctUINT blockSize;
2124
2125 /* Some formats are larger than what the GPU can support. */
2126 /* These formats are read in the number of layers specified. */
2127 gctUINT8 layers;
2128
2129 /* The format is faked and software will interpret it differently
2130 ** with HW. Most of them can't be blendable(PE) or filterable(TX).
2131 */
2132 gctBOOL fakedFormat;
2133
2134 /* Some formats have two neighbour pixels interleaved together. */
2135 /* To describe such format, set the flag to 1 and add another */
2136 /* like this one describing the odd pixel format. */
2137 gctBOOL interleaved;
2138
2139 /* sRGB format. */
2140 gctBOOL sRGB;
2141
2142 /* Format components. */
2143 gcuPIXEL_FORMAT_CLASS u;
2144
2145 /* Format components. */
2146 gcuPIXEL_FORMAT_CLASS uOdd;
2147
2148 /* Render format. */
2149 gceSURF_FORMAT closestRenderFormat;
2150 /*gctCLOSEST_FORMAT dynamicClosestRenderFormat;*/
2151 gctUINT renderFormat;
2152 const gceTEXTURE_SWIZZLE * pixelSwizzle;
2153
2154 /* Texture format. */
2155 gceSURF_FORMAT closestTXFormat;
2156 gctUINT txFormat;
2157 const gceTEXTURE_SWIZZLE * txSwizzle;
2158 gctBOOL txIntFilter;
2159}
2160gcsSURF_FORMAT_INFO;
2161
2162/* Frame buffer information. */
2163typedef struct _gcsSURF_FRAMEBUFFER
2164{
2165 gctPOINTER logical;
2166 gctUINT width, height;
2167 gctINT stride;
2168 gceSURF_FORMAT format;
2169}
2170gcsSURF_FRAMEBUFFER;
2171
2172/* Generic pixel component descriptors. */
2173extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XXX8;
2174extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_XX8X;
2175extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_X8XX;
2176extern gcsFORMAT_COMPONENT gcvPIXEL_COMP_8XXX;
2177
2178typedef enum _gceORIENTATION
2179{
2180 gcvORIENTATION_TOP_BOTTOM,
2181 gcvORIENTATION_BOTTOM_TOP,
2182}
2183gceORIENTATION;
2184
2185
2186/* Construct a new gcoSURF object. */
2187gceSTATUS
2188gcoSURF_Construct(
2189 IN gcoHAL Hal,
2190 IN gctUINT Width,
2191 IN gctUINT Height,
2192 IN gctUINT Depth,
2193 IN gceSURF_TYPE Type,
2194 IN gceSURF_FORMAT Format,
2195 IN gcePOOL Pool,
2196 OUT gcoSURF * Surface
2197 );
2198
2199/* Destroy an gcoSURF object. */
2200gceSTATUS
2201gcoSURF_Destroy(
2202 IN gcoSURF Surface
2203 );
2204
2205/* Map user-allocated surface. */
2206gceSTATUS
2207gcoSURF_MapUserSurface(
2208 IN gcoSURF Surface,
2209 IN gctUINT Alignment,
2210 IN gctPOINTER Logical,
2211 IN gctUINT32 Physical
2212 );
2213
2214/* Wrapp surface with known logical/GPU address */
2215gceSTATUS
2216gcoSURF_WrapSurface(
2217 IN gcoSURF Surface,
2218 IN gctUINT Alignment,
2219 IN gctPOINTER Logical,
2220 IN gctUINT32 Physical
2221 );
2222
2223
2224/* Query vid mem node info. */
2225gceSTATUS
2226gcoSURF_QueryVidMemNode(
2227 IN gcoSURF Surface,
2228 OUT gctUINT32 * Node,
2229 OUT gcePOOL * Pool,
2230 OUT gctSIZE_T_PTR Bytes
2231 );
2232
2233/* Set the color type of the surface. */
2234gceSTATUS
2235gcoSURF_SetColorType(
2236 IN gcoSURF Surface,
2237 IN gceSURF_COLOR_TYPE ColorType
2238 );
2239
2240/* Get the color type of the surface. */
2241gceSTATUS
2242gcoSURF_GetColorType(
2243 IN gcoSURF Surface,
2244 OUT gceSURF_COLOR_TYPE *ColorType
2245 );
2246
2247/* Set the color space of the surface. */
2248gceSTATUS
2249gcoSURF_SetColorSpace(
2250 IN gcoSURF Surface,
2251 IN gceSURF_COLOR_SPACE ColorSpace
2252 );
2253
2254/* Get the color space of the surface. */
2255gceSTATUS
2256gcoSURF_GetColorSpace(
2257 IN gcoSURF Surface,
2258 OUT gceSURF_COLOR_SPACE *ColorSpace
2259 );
2260
2261
2262/* Set the surface ration angle. */
2263gceSTATUS
2264gcoSURF_SetRotation(
2265 IN gcoSURF Surface,
2266 IN gceSURF_ROTATION Rotation
2267 );
2268
2269gceSTATUS
2270gcoSURF_IsValid(
2271 IN gcoSURF Surface
2272 );
2273
2274
2275/* Get surface size. */
2276gceSTATUS
2277gcoSURF_GetSize(
2278 IN gcoSURF Surface,
2279 OUT gctUINT * Width,
2280 OUT gctUINT * Height,
2281 OUT gctUINT * Depth
2282 );
2283
2284/* Get surface aligned sizes. */
2285gceSTATUS
2286gcoSURF_GetAlignedSize(
2287 IN gcoSURF Surface,
2288 OUT gctUINT * Width,
2289 OUT gctUINT * Height,
2290 OUT gctINT * Stride
2291 );
2292
2293/* Get alignments. */
2294gceSTATUS
2295gcoSURF_GetAlignment(
2296 IN gceSURF_TYPE Type,
2297 IN gceSURF_FORMAT Format,
2298 OUT gctUINT * AddressAlignment,
2299 OUT gctUINT * XAlignment,
2300 OUT gctUINT * YAlignment
2301 );
2302
2303gceSTATUS
2304gcoSURF_AlignResolveRect(
2305 IN gcoSURF Surf,
2306 IN gcsPOINT_PTR RectOrigin,
2307 IN gcsPOINT_PTR RectSize,
2308 OUT gcsPOINT_PTR AlignedOrigin,
2309 OUT gcsPOINT_PTR AlignedSize
2310 );
2311
2312/* Get surface type and format. */
2313gceSTATUS
2314gcoSURF_GetFormat(
2315 IN gcoSURF Surface,
2316 OUT OPTIONAL gceSURF_TYPE * Type,
2317 OUT OPTIONAL gceSURF_FORMAT * Format
2318 );
2319
2320/* Get surface information */
2321gceSTATUS
2322gcoSURF_GetFormatInfo(
2323 IN gcoSURF Surface,
2324 OUT gcsSURF_FORMAT_INFO_PTR * formatInfo
2325 );
2326
2327/* Get Surface pack format */
2328gceSTATUS
2329gcoSURF_GetPackedFormat(
2330 IN gcoSURF Surface,
2331 OUT gceSURF_FORMAT * Format
2332 );
2333
2334/* Get surface tiling. */
2335gceSTATUS
2336gcoSURF_GetTiling(
2337 IN gcoSURF Surface,
2338 OUT gceTILING * Tiling
2339 );
2340
2341/* Get flip bitmap offset bytes. */
2342gceSTATUS
2343gcoSURF_GetFlipBitmapOffset(
2344 IN gcoSURF Surface,
2345 OUT gctUINT_PTR FlipBitmapOffset
2346 );
2347
2348/* Get bottom buffer offset bytes. */
2349gceSTATUS
2350gcoSURF_GetBottomBufferOffset(
2351 IN gcoSURF Surface,
2352 OUT gctUINT_PTR BottomBufferOffset
2353 );
2354
2355/* Lock the surface. */
2356gceSTATUS
2357gcoSURF_Lock(
2358 IN gcoSURF Surface,
2359 IN OUT gctUINT32 * Address,
2360 IN OUT gctPOINTER * Memory
2361 );
2362
2363/* Unlock the surface. */
2364gceSTATUS
2365gcoSURF_Unlock(
2366 IN gcoSURF Surface,
2367 IN gctPOINTER Memory
2368 );
2369
2370/*. Query surface flags.*/
2371gceSTATUS
2372gcoSURF_QueryFlags(
2373 IN gcoSURF Surface,
2374 IN gceSURF_FLAG Flag
2375 );
2376
2377/* Return pixel format parameters; Info is required to be a pointer to an
2378 * array of at least two items because some formats have up to two records
2379 * of description. */
2380gceSTATUS
2381gcoSURF_QueryFormat(
2382 IN gceSURF_FORMAT Format,
2383 OUT gcsSURF_FORMAT_INFO_PTR * Info
2384 );
2385
2386/* Compute the color pixel mask. */
2387gceSTATUS
2388gcoSURF_ComputeColorMask(
2389 IN gcsSURF_FORMAT_INFO_PTR Format,
2390 OUT gctUINT32_PTR ColorMask
2391 );
2392
2393/* Flush the surface. */
2394gceSTATUS
2395gcoSURF_Flush(
2396 IN gcoSURF Surface
2397 );
2398
2399/* Fill surface from it's tile status buffer. */
2400gceSTATUS
2401gcoSURF_FillFromTile(
2402 IN gcoSURF Surface
2403 );
2404
2405/* Fill surface with a value. */
2406gceSTATUS
2407gcoSURF_Fill(
2408 IN gcoSURF Surface,
2409 IN gcsPOINT_PTR Origin,
2410 IN gcsSIZE_PTR Size,
2411 IN gctUINT32 Value,
2412 IN gctUINT32 Mask
2413 );
2414
2415/* Alpha blend two surfaces together. */
2416gceSTATUS
2417gcoSURF_Blend(
2418 IN gcoSURF SrcSurface,
2419 IN gcoSURF DestSurface,
2420 IN gcsPOINT_PTR SrcOrig,
2421 IN gcsPOINT_PTR DestOrigin,
2422 IN gcsSIZE_PTR Size,
2423 IN gceSURF_BLEND_MODE Mode
2424 );
2425
2426/* Create a new gcoSURF wrapper object. */
2427gceSTATUS
2428gcoSURF_ConstructWrapper(
2429 IN gcoHAL Hal,
2430 OUT gcoSURF * Surface
2431 );
2432
2433/* Set surface flags.*/
2434gceSTATUS
2435gcoSURF_SetFlags(
2436 IN gcoSURF Surface,
2437 IN gceSURF_FLAG Flag,
2438 IN gctBOOL Value
2439 );
2440
2441/* Set the underlying buffer for the surface wrapper. */
2442gceSTATUS
2443gcoSURF_SetBuffer(
2444 IN gcoSURF Surface,
2445 IN gceSURF_TYPE Type,
2446 IN gceSURF_FORMAT Format,
2447 IN gctUINT Stride,
2448 IN gctPOINTER Logical,
2449 IN gctUINT32 Physical
2450 );
2451
2452/* Set the size of the surface in pixels and map the underlying buffer. */
2453gceSTATUS
2454gcoSURF_SetWindow(
2455 IN gcoSURF Surface,
2456 IN gctUINT X,
2457 IN gctUINT Y,
2458 IN gctUINT Width,
2459 IN gctUINT Height
2460 );
2461
2462/* Set width/height alignment of the surface directly and calculate stride/size. This is only for dri backend now. Please be careful before use. */
2463gceSTATUS
2464gcoSURF_SetAlignment(
2465 IN gcoSURF Surface,
2466 IN gctUINT Width,
2467 IN gctUINT Height
2468 );
2469
2470/* Increase reference count of the surface. */
2471gceSTATUS
2472gcoSURF_ReferenceSurface(
2473 IN gcoSURF Surface
2474 );
2475
2476/* Get surface reference count. */
2477gceSTATUS
2478gcoSURF_QueryReferenceCount(
2479 IN gcoSURF Surface,
2480 OUT gctINT32 * ReferenceCount
2481 );
2482
2483/* Set surface orientation. */
2484gceSTATUS
2485gcoSURF_SetOrientation(
2486 IN gcoSURF Surface,
2487 IN gceORIENTATION Orientation
2488 );
2489
2490/* Query surface orientation. */
2491gceSTATUS
2492gcoSURF_QueryOrientation(
2493 IN gcoSURF Surface,
2494 OUT gceORIENTATION * Orientation
2495 );
2496
2497gceSTATUS
2498gcoSURF_SetOffset(
2499 IN gcoSURF Surface,
2500 IN gctSIZE_T Offset
2501 );
2502
2503gceSTATUS
2504gcoSURF_NODE_Cache(
2505 IN gcsSURF_NODE_PTR Node,
2506 IN gctPOINTER Logical,
2507 IN gctSIZE_T Bytes,
2508 IN gceCACHEOPERATION Operation
2509 );
2510
2511/* Lock and unlock surface node */
2512gceSTATUS
2513gcoSURF_LockNode(
2514 IN gcsSURF_NODE_PTR Node,
2515 OUT gctUINT32 * Address,
2516 OUT gctPOINTER * Memory
2517 );
2518
2519gceSTATUS
2520gcoSURF_UnLockNode(
2521 IN gcsSURF_NODE_PTR Node,
2522 IN gceSURF_TYPE Type
2523 );
2524
2525/* Perform CPU cache operation on surface node */
2526gceSTATUS
2527gcoSURF_NODE_CPUCacheOperation(
2528 IN gcsSURF_NODE_PTR Node,
2529 IN gceSURF_TYPE Type,
2530 IN gctSIZE_T Offset,
2531 IN gctSIZE_T Length,
2532 IN gceCACHEOPERATION Operation
2533 );
2534
2535/* Perform CPU cache operation on surface */
2536gceSTATUS
2537gcoSURF_CPUCacheOperation(
2538 IN gcoSURF Surface,
2539 IN gceCACHEOPERATION Operation
2540 );
2541
2542gceSTATUS
2543gcoSURF_WrapUserMultiBuffer(
2544 IN gcoHAL Hal,
2545 IN gctUINT Width,
2546 IN gctUINT Height,
2547 IN gceSURF_TYPE Type,
2548 IN gceSURF_FORMAT Format,
2549 IN gctUINT Stride[3],
2550 IN gctUINT32 Handle[3],
2551 IN gctUINT BufferOffset[3],
2552 IN gctUINT32 Flag,
2553 OUT gcoSURF * Surface
2554 );
2555
2556gceSTATUS
2557gcoSURF_Swap(
2558 IN gcoSURF Surface1,
2559 IN gcoSURF Surface2
2560 );
2561
2562gceSTATUS
2563gcoSURF_ResetSurWH(
2564 IN gcoSURF Surface,
2565 IN gctUINT oriw,
2566 IN gctUINT orih,
2567 IN gctUINT alignw,
2568 IN gctUINT alignh,
2569 IN gceSURF_FORMAT fmt
2570);
2571
2572/* Update surface timestamp. */
2573gceSTATUS
2574gcoSURF_UpdateTimeStamp(
2575 IN gcoSURF Surface
2576 );
2577
2578/* Query surface current timestamp. */
2579gceSTATUS
2580gcoSURF_QueryTimeStamp(
2581 IN gcoSURF Surface,
2582 OUT gctUINT64 * TimeStamp
2583 );
2584
2585/*
2586 * Allocate shared buffer for this surface, so that
2587 * surface states can be shared across processes.
2588 */
2589gceSTATUS
2590gcoSURF_AllocShBuffer(
2591 IN gcoSURF Surface,
2592 OUT gctSHBUF * ShBuf
2593 );
2594
2595/* Bind shared buffer to this surface */
2596gceSTATUS
2597gcoSURF_BindShBuffer(
2598 IN gcoSURF Surface,
2599 IN gctSHBUF ShBuf
2600 );
2601
2602/* Push surface shared states to shared buffer. */
2603gceSTATUS
2604gcoSURF_PushSharedInfo(
2605 IN gcoSURF Surface
2606 );
2607
2608/* Pop shared states from shared buffer. */
2609gceSTATUS
2610gcoSURF_PopSharedInfo(
2611 IN gcoSURF Surface
2612 );
2613
2614
2615gceSTATUS
2616gcoSURF_WrapUserMemory(
2617 IN gcoHAL Hal,
2618 IN gctUINT Width,
2619 IN gctUINT Height,
2620 IN gctUINT Stride,
2621 IN gctUINT Depth,
2622 IN gceSURF_TYPE Type,
2623 IN gceSURF_FORMAT Format,
2624 IN gctUINT32 Handle,
2625 IN gctUINT32 Flag,
2626 OUT gcoSURF * Surface
2627 );
2628
2629/******************************************************************************\
2630********************************* gcoDUMP Object ********************************
2631\******************************************************************************/
2632
2633/* Construct a new gcoDUMP object. */
2634gceSTATUS
2635gcoDUMP_Construct(
2636 IN gcoOS Os,
2637 IN gcoHAL Hal,
2638 OUT gcoDUMP * Dump
2639 );
2640
2641/* Destroy a gcoDUMP object. */
2642gceSTATUS
2643gcoDUMP_Destroy(
2644 IN gcoDUMP Dump
2645 );
2646
2647/* Enable/disable dumping. */
2648gceSTATUS
2649gcoDUMP_Control(
2650 IN gcoDUMP Dump,
2651 IN gctSTRING FileName
2652 );
2653
2654gceSTATUS
2655gcoDUMP_IsEnabled(
2656 IN gcoDUMP Dump,
2657 OUT gctBOOL * Enabled
2658 );
2659
2660/* Add surface. */
2661gceSTATUS
2662gcoDUMP_AddSurface(
2663 IN gcoDUMP Dump,
2664 IN gctINT32 Width,
2665 IN gctINT32 Height,
2666 IN gceSURF_FORMAT PixelFormat,
2667 IN gctUINT32 Address,
2668 IN gctSIZE_T ByteCount
2669 );
2670
2671/* Mark the beginning of a frame. */
2672gceSTATUS
2673gcoDUMP_FrameBegin(
2674 IN gcoDUMP Dump
2675 );
2676
2677/* Mark the end of a frame. */
2678gceSTATUS
2679gcoDUMP_FrameEnd(
2680 IN gcoDUMP Dump
2681 );
2682
2683/* Dump data. */
2684gceSTATUS
2685gcoDUMP_DumpData(
2686 IN gcoDUMP Dump,
2687 IN gceDUMP_TAG Type,
2688 IN gctUINT32 Address,
2689 IN gctSIZE_T ByteCount,
2690 IN gctCONST_POINTER Data
2691 );
2692
2693/* Delete an address. */
2694gceSTATUS
2695gcoDUMP_Delete(
2696 IN gcoDUMP Dump,
2697 IN gctUINT32 Address
2698 );
2699
2700/* Enable dump or not. */
2701gceSTATUS
2702gcoDUMP_SetDumpFlag(
2703 IN gctBOOL DumpState
2704 );
2705
2706/******************************************************************************\
2707******************************* gcsRECT Structure ******************************
2708\******************************************************************************/
2709
2710/* Initialize rectangle structure. */
2711gceSTATUS
2712gcsRECT_Set(
2713 OUT gcsRECT_PTR Rect,
2714 IN gctINT32 Left,
2715 IN gctINT32 Top,
2716 IN gctINT32 Right,
2717 IN gctINT32 Bottom
2718 );
2719
2720/* Return the width of the rectangle. */
2721gceSTATUS
2722gcsRECT_Width(
2723 IN gcsRECT_PTR Rect,
2724 OUT gctINT32 * Width
2725 );
2726
2727/* Return the height of the rectangle. */
2728gceSTATUS
2729gcsRECT_Height(
2730 IN gcsRECT_PTR Rect,
2731 OUT gctINT32 * Height
2732 );
2733
2734/* Ensure that top left corner is to the left and above the right bottom. */
2735gceSTATUS
2736gcsRECT_Normalize(
2737 IN OUT gcsRECT_PTR Rect
2738 );
2739
2740/* Compare two rectangles. */
2741gceSTATUS
2742gcsRECT_IsEqual(
2743 IN gcsRECT_PTR Rect1,
2744 IN gcsRECT_PTR Rect2,
2745 OUT gctBOOL * Equal
2746 );
2747
2748/* Compare the sizes of two rectangles. */
2749gceSTATUS
2750gcsRECT_IsOfEqualSize(
2751 IN gcsRECT_PTR Rect1,
2752 IN gcsRECT_PTR Rect2,
2753 OUT gctBOOL * EqualSize
2754 );
2755
2756gceSTATUS
2757gcsRECT_RelativeRotation(
2758 IN gceSURF_ROTATION Orientation,
2759 IN OUT gceSURF_ROTATION *Relation);
2760
2761gceSTATUS
2762
2763gcsRECT_Rotate(
2764
2765 IN OUT gcsRECT_PTR Rect,
2766
2767 IN gceSURF_ROTATION Rotation,
2768
2769 IN gceSURF_ROTATION toRotation,
2770
2771 IN gctINT32 SurfaceWidth,
2772
2773 IN gctINT32 SurfaceHeight
2774
2775 );
2776
2777/******************************************************************************\
2778**************************** gcsBOUNDARY Structure *****************************
2779\******************************************************************************/
2780
2781typedef struct _gcsBOUNDARY
2782{
2783 gctINT x;
2784 gctINT y;
2785 gctINT width;
2786 gctINT height;
2787}
2788gcsBOUNDARY;
2789
2790/******************************************************************************\
2791********************************* gcoHEAP Object ********************************
2792\******************************************************************************/
2793
2794typedef struct _gcoHEAP * gcoHEAP;
2795
2796/* Construct a new gcoHEAP object. */
2797gceSTATUS
2798gcoHEAP_Construct(
2799 IN gcoOS Os,
2800 IN gctSIZE_T AllocationSize,
2801 OUT gcoHEAP * Heap
2802 );
2803
2804/* Destroy an gcoHEAP object. */
2805gceSTATUS
2806gcoHEAP_Destroy(
2807 IN gcoHEAP Heap
2808 );
2809
2810/* Allocate memory. */
2811gceSTATUS
2812gcoHEAP_Allocate(
2813 IN gcoHEAP Heap,
2814 IN gctSIZE_T Bytes,
2815 OUT gctPOINTER * Node
2816 );
2817
2818gceSTATUS
2819gcoHEAP_GetMemorySize(
2820 IN gcoHEAP Heap,
2821 IN gctPOINTER Memory,
2822 OUT gctSIZE_T_PTR MemorySize
2823 );
2824
2825/* Free memory. */
2826gceSTATUS
2827gcoHEAP_Free(
2828 IN gcoHEAP Heap,
2829 IN gctPOINTER Node
2830 );
2831
2832#if (VIVANTE_PROFILER || gcdDEBUG)
2833/* Profile the heap. */
2834gceSTATUS
2835gcoHEAP_ProfileStart(
2836 IN gcoHEAP Heap
2837 );
2838
2839gceSTATUS
2840gcoHEAP_ProfileEnd(
2841 IN gcoHEAP Heap,
2842 IN gctCONST_STRING Title
2843 );
2844#endif
2845
2846
2847/******************************************************************************\
2848******************************* Debugging Macros *******************************
2849\******************************************************************************/
2850
2851void
2852gcoOS_SetDebugLevel(
2853 IN gctUINT32 Level
2854 );
2855
2856void
2857gcoOS_GetDebugLevel(
2858 OUT gctUINT32_PTR DebugLevel
2859 );
2860
2861void
2862gcoOS_SetDebugZone(
2863 IN gctUINT32 Zone
2864 );
2865
2866void
2867gcoOS_GetDebugZone(
2868 IN gctUINT32 Zone,
2869 OUT gctUINT32_PTR DebugZone
2870 );
2871
2872void
2873gcoOS_SetDebugLevelZone(
2874 IN gctUINT32 Level,
2875 IN gctUINT32 Zone
2876 );
2877
2878void
2879gcoOS_SetDebugZones(
2880 IN gctUINT32 Zones,
2881 IN gctBOOL Enable
2882 );
2883
2884void
2885gcoOS_SetDebugFile(
2886 IN gctCONST_STRING FileName
2887 );
2888
2889gctFILE
2890gcoOS_ReplaceDebugFile(
2891 IN gctFILE fp
2892 );
2893
2894void
2895gcoOS_SysTraceBegin(
2896 IN gctCONST_STRING FuncName
2897 );
2898
2899void
2900gcoOS_SysTraceEnd(
2901 IN void);
2902
2903/*******************************************************************************
2904**
2905** gcmFATAL
2906**
2907** Print a message to the debugger and execute a break point.
2908**
2909** ARGUMENTS:
2910**
2911** message Message.
2912** ... Optional arguments.
2913*/
2914
2915void
2916gckOS_DebugFatal(
2917 IN gctCONST_STRING Message,
2918 ...
2919 );
2920
2921void
2922gcoOS_DebugFatal(
2923 IN gctCONST_STRING Message,
2924 ...
2925 );
2926
2927#if gcmIS_DEBUG(gcdDEBUG_FATAL)
2928# define gcmFATAL gcoOS_DebugFatal
2929# define gcmkFATAL gckOS_DebugFatal
2930#elif gcdHAS_ELLIPSIS
2931# define gcmFATAL(...)
2932# define gcmkFATAL(...)
2933#else
2934 gcmINLINE static void
2935 __dummy_fatal(
2936 IN gctCONST_STRING Message,
2937 ...
2938 )
2939 {
2940 }
2941# define gcmFATAL __dummy_fatal
2942# define gcmkFATAL __dummy_fatal
2943#endif
2944
2945#define gcmENUM2TEXT(e) case e: return #e
2946
2947/*******************************************************************************
2948**
2949** gcmTRACE
2950**
2951** Print a message to the debugfer if the correct level has been set. In
2952** retail mode this macro does nothing.
2953**
2954** ARGUMENTS:
2955**
2956** level Level of message.
2957** message Message.
2958** ... Optional arguments.
2959*/
2960#define gcvLEVEL_NONE -1
2961#define gcvLEVEL_ERROR 0
2962#define gcvLEVEL_WARNING 1
2963#define gcvLEVEL_INFO 2
2964#define gcvLEVEL_VERBOSE 3
2965
2966void
2967gckOS_DebugTrace(
2968 IN gctUINT32 Level,
2969 IN gctCONST_STRING Message,
2970 ...
2971 );
2972
2973void
2974gckOS_DebugTraceN(
2975 IN gctUINT32 Level,
2976 IN gctUINT ArgumentSize,
2977 IN gctCONST_STRING Message,
2978 ...
2979 );
2980
2981void
2982gcoOS_DebugTrace(
2983 IN gctUINT32 Level,
2984 IN gctCONST_STRING Message,
2985 ...
2986 );
2987
2988#if gcmIS_DEBUG(gcdDEBUG_TRACE)
2989# define gcmTRACE gcoOS_DebugTrace
2990# define gcmkTRACE gckOS_DebugTrace
2991# define gcmkTRACE_N gckOS_DebugTraceN
2992#elif gcdHAS_ELLIPSIS
2993# define gcmTRACE(...)
2994# define gcmkTRACE(...)
2995# define gcmkTRACE_N(...)
2996#else
2997 gcmINLINE static void
2998 __dummy_trace(
2999 IN gctUINT32 Level,
3000 IN gctCONST_STRING Message,
3001 ...
3002 )
3003 {
3004 }
3005
3006 gcmINLINE static void
3007 __dummy_trace_n(
3008 IN gctUINT32 Level,
3009 IN gctUINT ArgumentSize,
3010 IN gctCONST_STRING Message,
3011 ...
3012 )
3013 {
3014 }
3015
3016# define gcmTRACE __dummy_trace
3017# define gcmkTRACE __dummy_trace
3018# define gcmkTRACE_N __dummy_trace_n
3019#endif
3020
3021/* Zones common for kernel and user. */
3022#define gcvZONE_OS (1 << 0)
3023#define gcvZONE_HARDWARE (1 << 1)
3024#define gcvZONE_HEAP (1 << 2)
3025#define gcvZONE_SIGNAL (1 << 27)
3026
3027/* Kernel zones. */
3028#define gcvZONE_KERNEL (1 << 3)
3029#define gcvZONE_VIDMEM (1 << 4)
3030#define gcvZONE_COMMAND (1 << 5)
3031#define gcvZONE_DRIVER (1 << 6)
3032#define gcvZONE_CMODEL (1 << 7)
3033#define gcvZONE_MMU (1 << 8)
3034#define gcvZONE_EVENT (1 << 9)
3035#define gcvZONE_DEVICE (1 << 10)
3036#define gcvZONE_DATABASE (1 << 11)
3037#define gcvZONE_INTERRUPT (1 << 12)
3038#define gcvZONE_POWER (1 << 13)
3039#define gcvZONE_ALLOCATOR (1 << 14)
3040
3041/* User zones. */
3042#define gcvZONE_HAL (1 << 3)
3043#define gcvZONE_BUFFER (1 << 4)
3044#define gcvZONE_CONTEXT (1 << 5)
3045#define gcvZONE_SURFACE (1 << 6)
3046#define gcvZONE_INDEX (1 << 7)
3047#define gcvZONE_STREAM (1 << 8)
3048#define gcvZONE_TEXTURE (1 << 9)
3049#define gcvZONE_2D (1 << 10)
3050#define gcvZONE_3D (1 << 11)
3051#define gcvZONE_COMPILER (1 << 12)
3052#define gcvZONE_MEMORY (1 << 13)
3053#define gcvZONE_STATE (1 << 14)
3054#define gcvZONE_AUX (1 << 15)
3055#define gcvZONE_VERTEX (1 << 16)
3056#define gcvZONE_CL (1 << 17)
3057#define gcvZONE_COMPOSITION (1 << 17)
3058#define gcvZONE_VG (1 << 18)
3059#define gcvZONE_IMAGE (1 << 19)
3060#define gcvZONE_UTILITY (1 << 20)
3061#define gcvZONE_PARAMETERS (1 << 21)
3062#define gcvZONE_BUFOBJ (1 << 22)
3063#define gcvZONE_SHADER (1 << 23)
3064#define gcvZONE_STREAM_OUT (1 << 24)
3065
3066/* API definitions. */
3067#define gcvZONE_API_HAL (1 << 28)
3068#define gcvZONE_API_EGL (2 << 28)
3069#define gcvZONE_API_ES11 (3 << 28)
3070#define gcvZONE_API_ES20 (4 << 28)
3071#define gcvZONE_API_VG11 (5 << 28)
3072#define gcvZONE_API_GL (6 << 28)
3073#define gcvZONE_API_DFB (7 << 28)
3074#define gcvZONE_API_GDI ((gctUINT32)8 << 28)
3075#define gcvZONE_API_D3D ((gctUINT32)9 << 28)
3076#define gcvZONE_API_ES30 ((gctUINT32)10 << 28)
3077
3078
3079#define gcmZONE_GET_API(zone) ((zone) >> 28)
3080/*Set gcdZONE_MASE like 0x0 | gcvZONE_API_EGL
3081will enable print EGL module debug info*/
3082#define gcdZONE_MASK 0x0FFFFFFF
3083
3084/* Handy zones. */
3085#define gcvZONE_NONE 0
3086#define gcvZONE_ALL 0x0FFFFFFF
3087
3088/*Dump API depth set 1 for API, 2 for API and API behavior*/
3089#define gcvDUMP_API_DEPTH 1
3090
3091/*******************************************************************************
3092**
3093** gcmTRACE_ZONE
3094**
3095** Print a message to the debugger if the correct level and zone has been
3096** set. In retail mode this macro does nothing.
3097**
3098** ARGUMENTS:
3099**
3100** Level Level of message.
3101** Zone Zone of message.
3102** Message Message.
3103** ... Optional arguments.
3104*/
3105
3106void
3107gckOS_DebugTraceZone(
3108 IN gctUINT32 Level,
3109 IN gctUINT32 Zone,
3110 IN gctCONST_STRING Message,
3111 ...
3112 );
3113
3114void
3115gckOS_DebugTraceZoneN(
3116 IN gctUINT32 Level,
3117 IN gctUINT32 Zone,
3118 IN gctUINT ArgumentSize,
3119 IN gctCONST_STRING Message,
3120 ...
3121 );
3122
3123void
3124gcoOS_DebugTraceZone(
3125 IN gctUINT32 Level,
3126 IN gctUINT32 Zone,
3127 IN gctCONST_STRING Message,
3128 ...
3129 );
3130
3131#if gcmIS_DEBUG(gcdDEBUG_TRACE)
3132# define gcmTRACE_ZONE gcoOS_DebugTraceZone
3133# define gcmkTRACE_ZONE gckOS_DebugTraceZone
3134# define gcmkTRACE_ZONE_N gckOS_DebugTraceZoneN
3135#elif gcdHAS_ELLIPSIS
3136# define gcmTRACE_ZONE(...)
3137# define gcmkTRACE_ZONE(...)
3138# define gcmkTRACE_ZONE_N(...)
3139#else
3140 gcmINLINE static void
3141 __dummy_trace_zone(
3142 IN gctUINT32 Level,
3143 IN gctUINT32 Zone,
3144 IN gctCONST_STRING Message,
3145 ...
3146 )
3147 {
3148 }
3149
3150 gcmINLINE static void
3151 __dummy_trace_zone_n(
3152 IN gctUINT32 Level,
3153 IN gctUINT32 Zone,
3154 IN gctUINT ArgumentSize,
3155 IN gctCONST_STRING Message,
3156 ...
3157 )
3158 {
3159 }
3160
3161# define gcmTRACE_ZONE __dummy_trace_zone
3162# define gcmkTRACE_ZONE __dummy_trace_zone
3163# define gcmkTRACE_ZONE_N __dummy_trace_zone_n
3164#endif
3165
3166/*******************************************************************************
3167**
3168** gcmDEBUG_ONLY
3169**
3170** Execute a statement or function only in DEBUG mode.
3171**
3172** ARGUMENTS:
3173**
3174** f Statement or function to execute.
3175*/
3176#if gcmIS_DEBUG(gcdDEBUG_CODE)
3177# define gcmDEBUG_ONLY(f) f
3178#else
3179# define gcmDEBUG_ONLY(f)
3180#endif
3181
3182/*******************************************************************************
3183**
3184** gcmSTACK_PUSH
3185** gcmSTACK_POP
3186** gcmSTACK_DUMP
3187**
3188** Push or pop a function with entry arguments on the trace stack.
3189**
3190** ARGUMENTS:
3191**
3192** Function Name of function.
3193** Line Line number.
3194** Text Optional text.
3195** ... Optional arguments for text.
3196*/
3197#if gcmIS_DEBUG(gcdDEBUG_STACK)
3198 void gcoOS_StackPush(IN gctINT8_PTR Identity, IN gctCONST_STRING Function, IN gctINT Line, IN gctCONST_STRING Text, ...);
3199 void gcoOS_StackPop(IN gctINT8_PTR Identity, IN gctCONST_STRING Function);
3200 void gcoOS_StackDump(void);
3201 void gcoOS_StackRemove(IN gctHANDLE Thread);
3202
3203# define gcmSTACK_PUSH gcoOS_StackPush
3204# define gcmSTACK_POP gcoOS_StackPop
3205# define gcmSTACK_DUMP gcoOS_StackDump
3206# define gcmSTACK_REMOVE gcoOS_StackRemove
3207#elif gcdHAS_ELLIPSIS
3208# define gcmSTACK_PUSH(...) do { } while (0)
3209# define gcmSTACK_POP(...) do { } while (0)
3210# define gcmSTACK_DUMP() do { } while (0)
3211# define gcmSTACK_REMOVE(...) do { } while (0)
3212#else
3213 gcmINLINE static void
3214 __dummy_stack_push(
3215 IN gctCONST_STRING Function,
3216 IN gctINT Line,
3217 IN gctCONST_STRING Text, ...
3218 )
3219 {
3220 }
3221# define gcmSTACK_PUSH __dummy_stack_push
3222# define gcmSTACK_POP(a,b) do { } while (0)
3223# define gcmSTACK_DUMP() do { } while (0)
3224# define gcmSTACK_REMOVE(a) do { } while (0)
3225#endif
3226
3227/******************************************************************************\
3228******************************** Binary Trace **********************************
3229\******************************************************************************/
3230typedef struct _gcsBINARY_TRACE_MESSAGE * gcsBINARY_TRACE_MESSAGE_PTR;
3231typedef struct _gcsBINARY_TRACE_MESSAGE
3232{
3233 gctUINT32 signature;
3234 gctUINT32 pid;
3235 gctUINT32 tid;
3236 gctUINT32 line;
3237 gctUINT32 numArguments;
3238 gctUINT8 payload;
3239}
3240gcsBINARY_TRACE_MESSAGE;
3241
3242#define gcdBINARY_TRACE_MESSAGE_SIZE 240
3243
3244#if gcdBINARY_TRACE
3245 void
3246 gcoOS_BinaryTrace(
3247 IN gctCONST_STRING Function,
3248 IN gctINT Line,
3249 IN gctCONST_STRING Text OPTIONAL,
3250 ...
3251 );
3252
3253 void
3254 gckOS_BinaryTrace(
3255 IN gctCONST_STRING Function,
3256 IN gctINT Line,
3257 IN gctCONST_STRING Text OPTIONAL,
3258 ...
3259 );
3260
3261# define gcmBINARY_TRACE gcoOS_BinaryTrace
3262# define gcmkBINARY_TRACE gckOS_BinaryTrace
3263#elif gcdHAS_ELLIPSIS
3264# define gcmBINARY_TRACE(Function, Line, Text, ...)
3265# define gcmkBINARY_TRACE(Function, Line, Text, ...)
3266#else
3267 gcmINLINE static void
3268 __dummy_binary_trace(
3269 IN gctCONST_STRING Function,
3270 IN gctINT Line,
3271 IN gctCONST_STRING Text,
3272 )
3273 {
3274 }
3275
3276# define gcmBINARY_TRACE __dummy_binary_trace
3277# define gcmkBINARY_TRACE __dummy_binary_trace
3278#endif
3279
3280/******************************************************************************\
3281******************************** Logging Macros ********************************
3282\******************************************************************************/
3283
3284#define gcdHEADER_LEVEL gcvLEVEL_VERBOSE
3285
3286#ifndef gcdEMPTY_HEADER_FOOTER
3287#define gcdEMPTY_HEADER_FOOTER 0
3288#endif
3289
3290#if gcdENABLE_PROFILING
3291void
3292gcoOS_ProfileDB(
3293 IN gctCONST_STRING Function,
3294 IN OUT gctBOOL_PTR Initialized
3295 );
3296
3297#define gcmHEADER() \
3298 gctINT8 __user__ = 1; \
3299 static gctBOOL __profile__initialized__ = gcvFALSE; \
3300 gcmSTACK_PUSH(&__user__, __FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3301 gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
3302#define gcmHEADER_ARG(...) \
3303 gctINT8 __user__ = 1; \
3304 static gctBOOL __profile__initialized__ = gcvFALSE; \
3305 gcmSTACK_PUSH(&__user__, __FUNCTION__, __LINE__, Text, __VA_ARGS__); \
3306 gcoOS_ProfileDB(__FUNCTION__, &__profile__initialized__)
3307#define gcmFOOTER() \
3308 gcmSTACK_POP(&__user__, __FUNCTION__); \
3309 gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
3310#define gcmFOOTER_NO() \
3311 gcmSTACK_POP(&__user__, __FUNCTION__); \
3312 gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
3313#define gcmFOOTER_ARG(...) \
3314 gcmSTACK_POP(&__user__, __FUNCTION__); \
3315 gcoOS_ProfileDB(__FUNCTION__, gcvNULL)
3316#define gcmFOOTER_KILL() \
3317 gcmSTACK_POP(&__user__, __FUNCTION__); \
3318 gcoOS_ProfileDB(gcvNULL, gcvNULL)
3319
3320#else /* gcdENABLE_PROFILING */
3321
3322#if gcdEMPTY_HEADER_FOOTER
3323# define gcmHEADER()
3324#elif gcdHAS_ELLIPSIS
3325#define gcmHEADER() \
3326 gctINT8 __user__ = 1; \
3327 gctINT8_PTR __user_ptr__ = &__user__; \
3328 gcmSTACK_PUSH(__user_ptr__, __FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3329 gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3330 gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3331 "++%s(%d)", __FUNCTION__, __LINE__)
3332#else
3333 gcmINLINE static void
3334 __dummy_header(void)
3335 {
3336 }
3337# define gcmHEADER __dummy_header
3338#endif
3339
3340#if gcdHAS_ELLIPSIS
3341#if gcdEMPTY_HEADER_FOOTER
3342# define gcmHEADER_ARG(Text, ...)
3343#else
3344# define gcmHEADER_ARG(Text, ...) \
3345 gctINT8 __user__ = 1; \
3346 gctINT8_PTR __user_ptr__ = &__user__; \
3347 gcmSTACK_PUSH(__user_ptr__, __FUNCTION__, __LINE__, Text, __VA_ARGS__); \
3348 gcmBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
3349 gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3350 "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
3351#endif
3352#else
3353 gcmINLINE static void
3354 __dummy_header_arg(
3355 IN gctCONST_STRING Text,
3356 ...
3357 )
3358 {
3359 }
3360# define gcmHEADER_ARG __dummy_header_arg
3361#endif
3362
3363#if gcdEMPTY_HEADER_FOOTER
3364# define gcmFOOTER()
3365#elif gcdHAS_ELLIPSIS
3366# define gcmFOOTER() \
3367 gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
3368 gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3369 gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3370 "--%s(%d): status=%d(%s)", \
3371 __FUNCTION__, __LINE__, \
3372 status, gcoOS_DebugStatus2Name(status)); \
3373 *__user_ptr__ -= 1
3374#else
3375 gcmINLINE static void
3376 __dummy_footer(void)
3377 {
3378 }
3379# define gcmFOOTER __dummy_footer
3380#endif
3381
3382#if gcdEMPTY_HEADER_FOOTER
3383# define gcmFOOTER_NO()
3384#elif gcdHAS_ELLIPSIS
3385#define gcmFOOTER_NO() \
3386 gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
3387 gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3388 gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3389 "--%s(%d)", __FUNCTION__, __LINE__); \
3390 *__user_ptr__ -= 1
3391#else
3392 gcmINLINE static void
3393 __dummy_footer_no(void)
3394 {
3395 }
3396# define gcmFOOTER_NO __dummy_footer_no
3397#endif
3398
3399#if gcdEMPTY_HEADER_FOOTER
3400# define gcmFOOTER_KILL()
3401#elif gcdHAS_ELLIPSIS
3402#define gcmFOOTER_KILL() \
3403 gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
3404 gcmBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3405 gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3406 "--%s(%d)", __FUNCTION__, __LINE__); \
3407 *__user_ptr__ -= 1
3408#else
3409 gcmINLINE static void
3410 __dummy_footer_kill(void)
3411 {
3412 }
3413# define gcmFOOTER_KILL __dummy_footer_kill
3414#endif
3415
3416#if gcdHAS_ELLIPSIS
3417#if gcdEMPTY_HEADER_FOOTER
3418# define gcmFOOTER_ARG(Text, ...)
3419#else
3420# define gcmFOOTER_ARG(Text, ...) \
3421 gcmSTACK_POP(__user_ptr__, __FUNCTION__); \
3422 gcmBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
3423 gcmTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3424 "--%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__); \
3425 *__user_ptr__ -= 1
3426#endif
3427#else
3428 gcmINLINE static void
3429 __dummy_footer_arg(
3430 IN gctCONST_STRING Text,
3431 ...
3432 )
3433 {
3434 }
3435# define gcmFOOTER_ARG __dummy_footer_arg
3436#endif
3437
3438#endif /* gcdENABLE_PROFILING */
3439
3440#if gcdHAS_ELLIPSIS
3441#define gcmkHEADER() \
3442 gctINT8 __kernel__ = 1; \
3443 gctINT8_PTR __kernel_ptr__ = &__kernel__; \
3444 gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3445 gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3446 "++%s(%d)", __FUNCTION__, __LINE__)
3447#else
3448 gcmINLINE static void
3449 __dummy_kheader(void)
3450 {
3451 }
3452# define gcmkHEADER __dummy_kheader
3453#endif
3454
3455#if gcdHAS_ELLIPSIS
3456# define gcmkHEADER_ARG(Text, ...) \
3457 gctINT8 __kernel__ = 1; \
3458 gctINT8_PTR __kernel_ptr__ = &__kernel__; \
3459 gcmkBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
3460 gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3461 "++%s(%d): " Text, __FUNCTION__, __LINE__, __VA_ARGS__)
3462#else
3463 gcmINLINE static void
3464 __dummy_kheader_arg(
3465 IN gctCONST_STRING Text,
3466 ...
3467 )
3468 {
3469 }
3470# define gcmkHEADER_ARG __dummy_kheader_arg
3471#endif
3472
3473#if gcdHAS_ELLIPSIS
3474#define gcmkFOOTER() \
3475 gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, status); \
3476 gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3477 "--%s(%d): status=%d(%s)", \
3478 __FUNCTION__, __LINE__, status, gckOS_DebugStatus2Name(status)); \
3479 *__kernel_ptr__ -= 1
3480#else
3481 gcmINLINE static void
3482 __dummy_kfooter(void)
3483 {
3484 }
3485# define gcmkFOOTER __dummy_kfooter
3486#endif
3487
3488#if gcdHAS_ELLIPSIS
3489#define gcmkFOOTER_NO() \
3490 gcmkBINARY_TRACE(__FUNCTION__, __LINE__, gcvNULL, gcvNULL); \
3491 gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3492 "--%s(%d)", __FUNCTION__, __LINE__); \
3493 *__kernel_ptr__ -= 1
3494#else
3495 gcmINLINE static void
3496 __dummy_kfooter_no(void)
3497 {
3498 }
3499# define gcmkFOOTER_NO __dummy_kfooter_no
3500#endif
3501
3502#if gcdHAS_ELLIPSIS
3503# define gcmkFOOTER_ARG(Text, ...) \
3504 gcmkBINARY_TRACE(__FUNCTION__, __LINE__, Text, __VA_ARGS__); \
3505 gcmkTRACE_ZONE(gcdHEADER_LEVEL, _GC_OBJ_ZONE, \
3506 "--%s(%d): " Text, \
3507 __FUNCTION__, __LINE__, __VA_ARGS__); \
3508 *__kernel_ptr__ -= 1
3509#else
3510 gcmINLINE static void
3511 __dummy_kfooter_arg(
3512 IN gctCONST_STRING Text,
3513 ...
3514 )
3515 {
3516 }
3517# define gcmkFOOTER_ARG __dummy_kfooter_arg
3518#endif
3519
3520#define gcmOPT_VALUE(ptr) (((ptr) == gcvNULL) ? 0 : *(ptr))
3521#define gcmOPT_VALUE_INDEX(ptr, index) (((ptr) == gcvNULL) ? 0 : ptr[index])
3522#define gcmOPT_POINTER(ptr) (((ptr) == gcvNULL) ? gcvNULL : *(ptr))
3523#define gcmOPT_STRING(ptr) (((ptr) == gcvNULL) ? "(nil)" : (ptr))
3524
3525void
3526gckOS_Print(
3527 IN gctCONST_STRING Message,
3528 ...
3529 );
3530
3531void
3532gckOS_PrintN(
3533 IN gctUINT ArgumentSize,
3534 IN gctCONST_STRING Message,
3535 ...
3536 );
3537
3538void
3539gckOS_CopyPrint(
3540 IN gctCONST_STRING Message,
3541 ...
3542 );
3543
3544void
3545gcoOS_Print(
3546 IN gctCONST_STRING Message,
3547 ...
3548 );
3549
3550#define gcmPRINT gcoOS_Print
3551#define gcmkPRINT gckOS_Print
3552#define gcmkPRINT_N gckOS_PrintN
3553
3554#if gcdPRINT_VERSION
3555# define gcmPRINT_VERSION() do { \
3556 _gcmPRINT_VERSION(gcm); \
3557 gcmSTACK_DUMP(); \
3558 } while (0)
3559# define gcmkPRINT_VERSION() _gcmPRINT_VERSION(gcmk)
3560# define _gcmPRINT_VERSION(prefix) \
3561 prefix##TRACE(gcvLEVEL_ERROR, \
3562 "Vivante HAL version %d.%d.%d build %d", \
3563 gcvVERSION_MAJOR, gcvVERSION_MINOR, \
3564 gcvVERSION_PATCH, gcvVERSION_BUILD)
3565#else
3566# define gcmPRINT_VERSION() do { gcmSTACK_DUMP(); } while (gcvFALSE)
3567# define gcmkPRINT_VERSION() do { } while (gcvFALSE)
3568#endif
3569
3570typedef enum _gceDUMP_BUFFER
3571{
3572 gceDUMP_BUFFER_CONTEXT,
3573 gceDUMP_BUFFER_USER,
3574 gceDUMP_BUFFER_KERNEL,
3575 gceDUMP_BUFFER_LINK,
3576 gceDUMP_BUFFER_WAITLINK,
3577 gceDUMP_BUFFER_FROM_USER,
3578}
3579gceDUMP_BUFFER;
3580
3581void
3582gckOS_DumpBuffer(
3583 IN gckOS Os,
3584 IN gctPOINTER Buffer,
3585 IN gctUINT Size,
3586 IN gceDUMP_BUFFER Type,
3587 IN gctBOOL CopyMessage
3588 );
3589
3590#define gcmkDUMPBUFFER gckOS_DumpBuffer
3591
3592#if gcdDUMP_COMMAND
3593# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage) \
3594 gcmkDUMPBUFFER(Os, Buffer, Size, Type, CopyMessage)
3595#else
3596# define gcmkDUMPCOMMAND(Os, Buffer, Size, Type, CopyMessage)
3597#endif
3598
3599#if gcmIS_DEBUG(gcdDEBUG_CODE)
3600
3601void
3602gckOS_DebugFlush(
3603 gctCONST_STRING CallerName,
3604 gctUINT LineNumber,
3605 gctUINT32 DmaAddress
3606 );
3607
3608# define gcmkDEBUGFLUSH(DmaAddress) \
3609 gckOS_DebugFlush(__FUNCTION__, __LINE__, DmaAddress)
3610#else
3611# define gcmkDEBUGFLUSH(DmaAddress)
3612#endif
3613
3614/*******************************************************************************
3615**
3616** gcmDUMP_FRAMERATE
3617**
3618** Print average frame rate
3619**
3620*/
3621#if gcdDUMP_FRAMERATE
3622 gceSTATUS
3623 gcfDumpFrameRate(
3624 void
3625 );
3626# define gcmDUMP_FRAMERATE gcfDumpFrameRate
3627#elif gcdHAS_ELLIPSIS
3628# define gcmDUMP_FRAMERATE(...)
3629#else
3630 gcmINLINE static void
3631 __dummy_dump_frame_rate(
3632 void
3633 )
3634 {
3635 }
3636# define gcmDUMP_FRAMERATE __dummy_dump_frame_rate
3637#endif
3638
3639
3640/*******************************************************************************
3641**
3642** gcmDUMP
3643**
3644** Print a dump message.
3645**
3646** ARGUMENTS:
3647**
3648** gctSTRING Message.
3649**
3650** ... Optional arguments.
3651*/
3652#if gcdDUMP
3653 gceSTATUS
3654 gcfDump(
3655 IN gcoOS Os,
3656 IN gctCONST_STRING String,
3657 ...
3658 );
3659# define gcmDUMP gcfDump
3660#elif gcdHAS_ELLIPSIS
3661# define gcmDUMP(...)
3662#else
3663 gcmINLINE static void
3664 __dummy_dump(
3665 IN gcoOS Os,
3666 IN gctCONST_STRING Message,
3667 ...
3668 )
3669 {
3670 }
3671# define gcmDUMP __dummy_dump
3672#endif
3673
3674/*******************************************************************************
3675**
3676** gcmDUMP_DATA
3677**
3678** Add data to the dump.
3679**
3680** ARGUMENTS:
3681**
3682** gctSTRING Tag
3683** Tag for dump.
3684**
3685** gctPOINTER Logical
3686** Logical address of buffer.
3687**
3688** gctSIZE_T Bytes
3689** Number of bytes.
3690*/
3691
3692#if gcdDUMP || gcdDUMP_COMMAND
3693 gceSTATUS
3694 gcfDumpData(
3695 IN gcoOS Os,
3696 IN gctSTRING Tag,
3697 IN gctPOINTER Logical,
3698 IN gctSIZE_T Bytes
3699 );
3700# define gcmDUMP_DATA gcfDumpData
3701#elif gcdHAS_ELLIPSIS
3702# define gcmDUMP_DATA(...)
3703#else
3704 gcmINLINE static void
3705 __dummy_dump_data(
3706 IN gcoOS Os,
3707 IN gctSTRING Tag,
3708 IN gctPOINTER Logical,
3709 IN gctSIZE_T Bytes
3710 )
3711 {
3712 }
3713# define gcmDUMP_DATA __dummy_dump_data
3714#endif
3715
3716/*******************************************************************************
3717**
3718** gcmDUMP_BUFFER
3719**
3720** Print a buffer to the dump.
3721**
3722** ARGUMENTS:
3723**
3724** gctSTRING Tag
3725** Tag for dump.
3726**
3727** gctUINT32 Physical
3728** Physical address of buffer.
3729**
3730** gctPOINTER Logical
3731** Logical address of buffer.
3732**
3733** gctUINT32 Offset
3734** Offset into buffer.
3735**
3736** gctSIZE_T Bytes
3737** Number of bytes.
3738*/
3739
3740#if gcdDUMP || gcdDUMP_COMMAND
3741gceSTATUS
3742gcfDumpBuffer(
3743 IN gcoOS Os,
3744 IN gctSTRING Tag,
3745 IN gctUINT32 Physical,
3746 IN gctPOINTER Logical,
3747 IN gctUINT32 Offset,
3748 IN gctSIZE_T Bytes
3749 );
3750# define gcmDUMP_BUFFER gcfDumpBuffer
3751#elif gcdHAS_ELLIPSIS
3752# define gcmDUMP_BUFFER(...)
3753#else
3754 gcmINLINE static void
3755 __dummy_dump_buffer(
3756 IN gcoOS Os,
3757 IN gctSTRING Tag,
3758 IN gctUINT32 Physical,
3759 IN gctPOINTER Logical,
3760 IN gctUINT32 Offset,
3761 IN gctSIZE_T Bytes
3762 )
3763 {
3764 }
3765# define gcmDUMP_BUFFER __dummy_dump_buffer
3766#endif
3767
3768/*******************************************************************************
3769**
3770** gcmDUMP_API
3771**
3772** Print a dump message for a high level API prefixed by the function name.
3773**
3774** ARGUMENTS:
3775**
3776** gctSTRING Message.
3777**
3778** ... Optional arguments.
3779*/
3780gceSTATUS gcfDumpApi(IN gctCONST_STRING String, ...);
3781#if gcdDUMP_API
3782# define gcmDUMP_API gcfDumpApi
3783#elif gcdHAS_ELLIPSIS
3784# define gcmDUMP_API(...)
3785#else
3786 gcmINLINE static void
3787 __dummy_dump_api(
3788 IN gctCONST_STRING Message,
3789 ...
3790 )
3791 {
3792 }
3793# define gcmDUMP_API __dummy_dump_api
3794#endif
3795
3796/*******************************************************************************
3797**
3798** gcmDUMP_API_ARRAY
3799**
3800** Print an array of data.
3801**
3802** ARGUMENTS:
3803**
3804** gctUINT32_PTR Pointer to array.
3805** gctUINT32 Size.
3806*/
3807gceSTATUS gcfDumpArray(IN gctCONST_POINTER Data, IN gctUINT32 Size);
3808#if gcdDUMP_API
3809# define gcmDUMP_API_ARRAY gcfDumpArray
3810#elif gcdHAS_ELLIPSIS
3811# define gcmDUMP_API_ARRAY(...)
3812#else
3813 gcmINLINE static void
3814 __dummy_dump_api_array(
3815 IN gctCONST_POINTER Data,
3816 IN gctUINT32 Size
3817 )
3818 {
3819 }
3820# define gcmDUMP_API_ARRAY __dummy_dump_api_array
3821#endif
3822
3823/*******************************************************************************
3824**
3825** gcmDUMP_API_ARRAY_TOKEN
3826**
3827** Print an array of data terminated by a token.
3828**
3829** ARGUMENTS:
3830**
3831** gctUINT32_PTR Pointer to array.
3832** gctUINT32 Termination.
3833*/
3834gceSTATUS gcfDumpArrayToken(IN gctCONST_POINTER Data, IN gctUINT32 Termination);
3835#if gcdDUMP_API
3836# define gcmDUMP_API_ARRAY_TOKEN gcfDumpArrayToken
3837#elif gcdHAS_ELLIPSIS
3838# define gcmDUMP_API_ARRAY_TOKEN(...)
3839#else
3840 gcmINLINE static void
3841 __dummy_dump_api_array_token(
3842 IN gctCONST_POINTER Data,
3843 IN gctUINT32 Termination
3844 )
3845 {
3846 }
3847# define gcmDUMP_API_ARRAY_TOKEN __dummy_dump_api_array_token
3848#endif
3849
3850/*******************************************************************************
3851**
3852** gcmDUMP_API_DATA
3853**
3854** Print an array of bytes.
3855**
3856** ARGUMENTS:
3857**
3858** gctCONST_POINTER Pointer to array.
3859** gctSIZE_T Size.
3860*/
3861gceSTATUS gcfDumpApiData(IN gctCONST_POINTER Data, IN gctSIZE_T Size);
3862#if gcdDUMP_API
3863# define gcmDUMP_API_DATA gcfDumpApiData
3864#elif gcdHAS_ELLIPSIS
3865# define gcmDUMP_API_DATA(...)
3866#else
3867 gcmINLINE static void
3868 __dummy_dump_api_data(
3869 IN gctCONST_POINTER Data,
3870 IN gctSIZE_T Size
3871 )
3872 {
3873 }
3874# define gcmDUMP_API_DATA __dummy_dump_api_data
3875#endif
3876
3877/*******************************************************************************
3878** gcmDUMP_2D_COMMAND
3879**
3880** Print the 2D command buffer.
3881**
3882** ARGUMENTS:
3883**
3884** gctUINT32_PTR Pointer to the command buffer.
3885** gctUINT32 Command buffer size.
3886*/
3887gceSTATUS gcfDump2DCommand(IN gctUINT32_PTR Command, IN gctUINT32 Size);
3888#if gcdDUMP_2D
3889# define gcmDUMP_2D_COMMAND gcfDump2DCommand
3890#elif gcdHAS_ELLIPSIS
3891# define gcmDUMP_2D_COMMAND(...)
3892#else
3893 gcmINLINE static void
3894 __dummy_dump_2d_command(
3895 IN gctUINT32_PTR Command,
3896 IN gctUINT32 Size
3897 )
3898 {
3899 }
3900# define gcmDUMP_2D_COMMAND __dummy_dump_2d_command
3901#endif
3902
3903/*******************************************************************************
3904** gcmDUMP_2D_SURFACE
3905**
3906** Print the 2D surface memory.
3907**
3908** ARGUMENTS:
3909**
3910** gctBOOL Src.
3911** gctUINT32 Address.
3912*/
3913gceSTATUS gcfDump2DSurface(IN gctBOOL Src, IN gctUINT32 Address);
3914#if gcdDUMP_2D
3915# define gcmDUMP_2D_SURFACE gcfDump2DSurface
3916#elif gcdHAS_ELLIPSIS
3917# define gcmDUMP_2D_SURFACE(...)
3918#else
3919 gcmINLINE static void
3920 __dummy_dump_2d_surface(
3921 IN gctBOOL Src,
3922 IN gctUINT32 Address
3923 )
3924 {
3925 }
3926# define gcmDUMP_2D_SURFACE __dummy_dump_2d_surface
3927#endif
3928
3929/*******************************************************************************
3930** gcmDUMP_ADD_MEMORY_INFO
3931**
3932** Record the memory info.
3933**
3934** ARGUMENTS:
3935**
3936** gctUINT32 Address.
3937** gctSIZE_T Size.
3938*/
3939gceSTATUS gcfAddMemoryInfo(IN gctUINT32 GPUAddress, IN gctPOINTER Logical, IN gctUINT32 Physical, IN gctUINT32 Size);
3940#if gcdDUMP_2D
3941# define gcmDUMP_ADD_MEMORY_INFO gcfAddMemoryInfo
3942#elif gcdHAS_ELLIPSIS
3943# define gcmDUMP_ADD_MEMORY_INFO(...)
3944#else
3945 gcmINLINE static void
3946 __dummy_dump_add_memory_info(
3947 IN gctUINT32 GPUAddress,
3948 IN gctPOINTER Logical,
3949 IN gctUINT32 Physical,
3950 IN gctUINT32 Size
3951 )
3952 {
3953 }
3954# define gcmDUMP_ADD_MEMORY_INFO __dummy_dump_add_memory_info
3955#endif
3956
3957/*******************************************************************************
3958** gcmDUMP_DEL_MEMORY_INFO
3959**
3960** Record the memory info.
3961**
3962** ARGUMENTS:
3963**
3964** gctUINT32 Address.
3965*/
3966gceSTATUS gcfDelMemoryInfo(IN gctUINT32 Address);
3967#if gcdDUMP_2D
3968# define gcmDUMP_DEL_MEMORY_INFO gcfDelMemoryInfo
3969#elif gcdHAS_ELLIPSIS
3970# define gcmDUMP_DEL_MEMORY_INFO(...)
3971#else
3972 gcmINLINE static void
3973 __dummy_dump_del_memory_info(
3974 IN gctUINT32 Address
3975 )
3976 {
3977 }
3978# define gcmDUMP_DEL_MEMORY_INFO __dummy_dump_del_memory_info
3979#endif
3980
3981#if gcdDUMP_2D
3982extern gctPOINTER dumpMemInfoListMutex;
3983extern gctBOOL dump2DFlag;
3984#endif
3985
3986/*******************************************************************************
3987**
3988** gcmTRACE_RELEASE
3989**
3990** Print a message to the shader debugger.
3991**
3992** ARGUMENTS:
3993**
3994** message Message.
3995** ... Optional arguments.
3996*/
3997
3998#define gcmTRACE_RELEASE gcoOS_DebugShaderTrace
3999
4000void
4001gcoOS_DebugShaderTrace(
4002 IN gctCONST_STRING Message,
4003 ...
4004 );
4005
4006void
4007gcoOS_SetDebugShaderFiles(
4008 IN gctCONST_STRING VSFileName,
4009 IN gctCONST_STRING FSFileName
4010 );
4011
4012void
4013gcoOS_SetDebugShaderFileType(
4014 IN gctUINT32 ShaderType
4015 );
4016
4017void
4018gcoOS_EnableDebugBuffer(
4019 IN gctBOOL Enable
4020 );
4021
4022/*******************************************************************************
4023**
4024** gcmBREAK
4025**
4026** Break into the debugger. In retail mode this macro does nothing.
4027**
4028** ARGUMENTS:
4029**
4030** None.
4031*/
4032
4033void
4034gcoOS_DebugBreak(
4035 void
4036 );
4037
4038void
4039gckOS_DebugBreak(
4040 void
4041 );
4042
4043#if gcmIS_DEBUG(gcdDEBUG_BREAK)
4044# define gcmBREAK gcoOS_DebugBreak
4045# define gcmkBREAK gckOS_DebugBreak
4046#else
4047# define gcmBREAK()
4048# define gcmkBREAK()
4049#endif
4050
4051/*******************************************************************************
4052**
4053** gcmASSERT
4054**
4055** Evaluate an expression and break into the debugger if the expression
4056** evaluates to false. In retail mode this macro does nothing.
4057**
4058** ARGUMENTS:
4059**
4060** exp Expression to evaluate.
4061*/
4062#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
4063# define _gcmASSERT(prefix, exp) \
4064 do \
4065 { \
4066 if (!(exp)) \
4067 { \
4068 prefix##TRACE(gcvLEVEL_ERROR, \
4069 #prefix "ASSERT at %s(%d)", \
4070 __FUNCTION__, __LINE__); \
4071 prefix##TRACE(gcvLEVEL_ERROR, \
4072 "(%s)", #exp); \
4073 prefix##BREAK(); \
4074 } \
4075 } \
4076 while (gcvFALSE)
4077# define gcmASSERT(exp) _gcmASSERT(gcm, exp)
4078# define gcmkASSERT(exp) _gcmASSERT(gcmk, exp)
4079#else
4080# define gcmASSERT(exp)
4081# define gcmkASSERT(exp)
4082#endif
4083
4084/*******************************************************************************
4085**
4086** gcmVERIFY
4087**
4088** Verify if an expression returns true. If the expression does not
4089** evaluates to true, an assertion will happen in debug mode.
4090**
4091** ARGUMENTS:
4092**
4093** exp Expression to evaluate.
4094*/
4095#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
4096# define gcmVERIFY(exp) gcmASSERT(exp)
4097# define gcmkVERIFY(exp) gcmkASSERT(exp)
4098#else
4099# define gcmVERIFY(exp) exp
4100# define gcmkVERIFY(exp) exp
4101#endif
4102
4103/*******************************************************************************
4104**
4105** gcmVERIFY_OK
4106**
4107** Verify a fucntion returns gcvSTATUS_OK. If the function does not return
4108** gcvSTATUS_OK, an assertion will happen in debug mode.
4109**
4110** ARGUMENTS:
4111**
4112** func Function to evaluate.
4113*/
4114
4115void
4116gcoOS_Verify(
4117 IN gceSTATUS status
4118 );
4119
4120void
4121gckOS_Verify(
4122 IN gceSTATUS status
4123 );
4124
4125#if gcmIS_DEBUG(gcdDEBUG_ASSERT)
4126# define gcmVERIFY_OK(func) \
4127 do \
4128 { \
4129 gceSTATUS verifyStatus = func; \
4130 gcoOS_Verify(verifyStatus); \
4131 if (verifyStatus != gcvSTATUS_OK) \
4132 { \
4133 gcmTRACE( \
4134 gcvLEVEL_ERROR, \
4135 "gcmVERIFY_OK(%d): function returned %d", \
4136 __LINE__, verifyStatus \
4137 ); \
4138 } \
4139 gcmASSERT(verifyStatus == gcvSTATUS_OK); \
4140 } \
4141 while (gcvFALSE)
4142# define gcmkVERIFY_OK(func) \
4143 do \
4144 { \
4145 gceSTATUS verifyStatus = func; \
4146 if (verifyStatus != gcvSTATUS_OK) \
4147 { \
4148 gcmkTRACE( \
4149 gcvLEVEL_ERROR, \
4150 "gcmkVERIFY_OK(%d): function returned %d", \
4151 __LINE__, verifyStatus \
4152 ); \
4153 } \
4154 gckOS_Verify(verifyStatus); \
4155 gcmkASSERT(verifyStatus == gcvSTATUS_OK); \
4156 } \
4157 while (gcvFALSE)
4158#else
4159# define gcmVERIFY_OK(func) func
4160# define gcmkVERIFY_OK(func) func
4161#endif
4162
4163gctCONST_STRING
4164gcoOS_DebugStatus2Name(
4165 gceSTATUS status
4166 );
4167
4168gctCONST_STRING
4169gckOS_DebugStatus2Name(
4170 gceSTATUS status
4171 );
4172
4173/*******************************************************************************
4174**
4175** gcmERR_BREAK
4176**
4177** Executes a break statement on error.
4178**
4179** ASSUMPTIONS:
4180**
4181** 'status' variable of gceSTATUS type must be defined.
4182**
4183** ARGUMENTS:
4184**
4185** func Function to evaluate.
4186*/
4187#define _gcmERR_BREAK(prefix, func) \
4188 status = func; \
4189 if (gcmIS_ERROR(status)) \
4190 { \
4191 prefix##PRINT_VERSION(); \
4192 prefix##TRACE(gcvLEVEL_ERROR, \
4193 #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
4194 status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
4195 break; \
4196 } \
4197 do { } while (gcvFALSE)
4198#define _gcmkERR_BREAK(prefix, func) \
4199 status = func; \
4200 if (gcmIS_ERROR(status)) \
4201 { \
4202 prefix##PRINT_VERSION(); \
4203 prefix##TRACE(gcvLEVEL_ERROR, \
4204 #prefix "ERR_BREAK: status=%d(%s) @ %s(%d)", \
4205 status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
4206 break; \
4207 } \
4208 do { } while (gcvFALSE)
4209#define gcmERR_BREAK(func) _gcmERR_BREAK(gcm, func)
4210#define gcmkERR_BREAK(func) _gcmkERR_BREAK(gcmk, func)
4211
4212/*******************************************************************************
4213**
4214** gcmERR_RETURN
4215**
4216** Executes a return on error.
4217**
4218** ASSUMPTIONS:
4219**
4220** 'status' variable of gceSTATUS type must be defined.
4221**
4222** ARGUMENTS:
4223**
4224** func Function to evaluate.
4225*/
4226#define _gcmERR_RETURN(prefix, func) \
4227 status = func; \
4228 if (gcmIS_ERROR(status)) \
4229 { \
4230 prefix##PRINT_VERSION(); \
4231 prefix##TRACE(gcvLEVEL_ERROR, \
4232 #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
4233 status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
4234 prefix##FOOTER(); \
4235 return status; \
4236 } \
4237 do { } while (gcvFALSE)
4238#define _gcmkERR_RETURN(prefix, func) \
4239 status = func; \
4240 if (gcmIS_ERROR(status)) \
4241 { \
4242 prefix##PRINT_VERSION(); \
4243 prefix##TRACE(gcvLEVEL_ERROR, \
4244 #prefix "ERR_RETURN: status=%d(%s) @ %s(%d)", \
4245 status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
4246 prefix##FOOTER(); \
4247 return status; \
4248 } \
4249 do { } while (gcvFALSE)
4250#define gcmERR_RETURN(func) _gcmERR_RETURN(gcm, func)
4251#define gcmkERR_RETURN(func) _gcmkERR_RETURN(gcmk, func)
4252
4253
4254/*******************************************************************************
4255**
4256** gcmONERROR
4257**
4258** Jump to the error handler in case there is an error.
4259**
4260** ASSUMPTIONS:
4261**
4262** 'status' variable of gceSTATUS type must be defined.
4263**
4264** ARGUMENTS:
4265**
4266** func Function to evaluate.
4267*/
4268#define _gcmONERROR(prefix, func) \
4269 do \
4270 { \
4271 status = func; \
4272 if (gcmIS_ERROR(status)) \
4273 { \
4274 prefix##PRINT_VERSION(); \
4275 prefix##TRACE(gcvLEVEL_ERROR, \
4276 #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
4277 status, gcoOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
4278 goto OnError; \
4279 } \
4280 } \
4281 while (gcvFALSE)
4282#define _gcmkONERROR(prefix, func) \
4283 do \
4284 { \
4285 status = func; \
4286 if (gcmIS_ERROR(status)) \
4287 { \
4288 prefix##PRINT_VERSION(); \
4289 prefix##TRACE(gcvLEVEL_ERROR, \
4290 #prefix "ONERROR: status=%d(%s) @ %s(%d)", \
4291 status, gckOS_DebugStatus2Name(status), __FUNCTION__, __LINE__); \
4292 goto OnError; \
4293 } \
4294 } \
4295 while (gcvFALSE)
4296#define gcmONERROR(func) _gcmONERROR(gcm, func)
4297#define gcmkONERROR(func) _gcmkONERROR(gcmk, func)
4298
4299/*******************************************************************************
4300**
4301** gcmkSAFECASTSIZET
4302**
4303** Check wether value of a gctSIZE_T varible beyond the capability
4304** of 32bits GPU hardware.
4305**
4306** ASSUMPTIONS:
4307**
4308**
4309**
4310** ARGUMENTS:
4311**
4312** x A gctUINT32 variable
4313** y A gctSIZE_T variable
4314*/
4315#define gcmkSAFECASTSIZET(x, y) \
4316 do \
4317 { \
4318 gctUINT32 tmp = (gctUINT32)(y); \
4319 if (gcmSIZEOF(gctSIZE_T) > gcmSIZEOF(gctUINT32)) \
4320 { \
4321 gcmkASSERT(tmp <= gcvMAXUINT32); \
4322 } \
4323 (x) = tmp; \
4324 } \
4325 while (gcvFALSE)
4326
4327#define gcmSAFECASTSIZET(x, y) \
4328 do \
4329 { \
4330 gctUINT32 tmp = (gctUINT32)(y); \
4331 if (gcmSIZEOF(gctSIZE_T) > gcmSIZEOF(gctUINT32)) \
4332 { \
4333 gcmASSERT(tmp <= gcvMAXUINT32); \
4334 } \
4335 (x) = tmp; \
4336 } \
4337 while (gcvFALSE)
4338
4339/*******************************************************************************
4340**
4341** gcmkSAFECASTPHYSADDRT
4342**
4343** Check whether value of a gctPHYS_ADDR_T variable beyond the capability
4344** of 32bits GPU hardware.
4345**
4346** ASSUMPTIONS:
4347**
4348**
4349**
4350** ARGUMENTS:
4351**
4352** x A gctUINT32 variable
4353** y A gctSIZE_T variable
4354*/
4355#define gcmkSAFECASTPHYSADDRT(x, y) \
4356 do \
4357 { \
4358 gctUINT32 tmp = (gctUINT32)(y); \
4359 if (gcmSIZEOF(gctPHYS_ADDR_T) > gcmSIZEOF(gctUINT32)) \
4360 { \
4361 gcmkASSERT(tmp <= gcvMAXUINT32); \
4362 } \
4363 (x) = tmp; \
4364 } \
4365 while (gcvFALSE)
4366
4367/*******************************************************************************
4368**
4369** gcmVERIFY_LOCK
4370**
4371** Verifies whether the surface is locked.
4372**
4373** ARGUMENTS:
4374**
4375** surfaceInfo Pointer to the surface iniformational structure.
4376*/
4377#define gcmVERIFY_LOCK(surfaceInfo) \
4378 if (!surfaceInfo->node.valid) \
4379 { \
4380 gcmONERROR(gcvSTATUS_MEMORY_UNLOCKED); \
4381 } \
4382
4383/*******************************************************************************
4384**
4385** gcmVERIFY_NODE_LOCK
4386**
4387** Verifies whether the surface node is locked.
4388**
4389** ARGUMENTS:
4390**
4391** surfaceInfo Pointer to the surface iniformational structure.
4392*/
4393#define gcmVERIFY_NODE_LOCK(surfaceNode) \
4394 if (!(surfaceNode)->valid) \
4395 { \
4396 status = gcvSTATUS_MEMORY_UNLOCKED; \
4397 break; \
4398 } \
4399 do { } while (gcvFALSE)
4400
4401/*******************************************************************************
4402**
4403** gcmBADOBJECT_BREAK
4404**
4405** Executes a break statement on bad object.
4406**
4407** ARGUMENTS:
4408**
4409** obj Object to test.
4410** t Expected type of the object.
4411*/
4412#define gcmBADOBJECT_BREAK(obj, t) \
4413 if ((obj == gcvNULL) \
4414 || (((gcsOBJECT *)(obj))->type != t) \
4415 ) \
4416 { \
4417 status = gcvSTATUS_INVALID_OBJECT; \
4418 break; \
4419 } \
4420 do { } while (gcvFALSE)
4421
4422/*******************************************************************************
4423**
4424** gcmCHECK_STATUS
4425**
4426** Executes a break statement on error.
4427**
4428** ASSUMPTIONS:
4429**
4430** 'status' variable of gceSTATUS type must be defined.
4431**
4432** ARGUMENTS:
4433**
4434** func Function to evaluate.
4435*/
4436#define _gcmCHECK_STATUS(prefix, func) \
4437 do \
4438 { \
4439 last = func; \
4440 if (gcmIS_ERROR(last)) \
4441 { \
4442 prefix##TRACE(gcvLEVEL_ERROR, \
4443 #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
4444 last, gcoOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
4445 status = last; \
4446 } \
4447 } \
4448 while (gcvFALSE)
4449#define _gcmkCHECK_STATUS(prefix, func) \
4450 do \
4451 { \
4452 last = func; \
4453 if (gcmIS_ERROR(last)) \
4454 { \
4455 prefix##TRACE(gcvLEVEL_ERROR, \
4456 #prefix "CHECK_STATUS: status=%d(%s) @ %s(%d)", \
4457 last, gckOS_DebugStatus2Name(last), __FUNCTION__, __LINE__); \
4458 status = last; \
4459 } \
4460 } \
4461 while (gcvFALSE)
4462#define gcmCHECK_STATUS(func) _gcmCHECK_STATUS(gcm, func)
4463#define gcmkCHECK_STATUS(func) _gcmkCHECK_STATUS(gcmk, func)
4464
4465/*******************************************************************************
4466**
4467** gcmVERIFY_ARGUMENT
4468**
4469** Assert if an argument does not apply to the specified expression. If
4470** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
4471** returned from the current function. In retail mode this macro does
4472** nothing.
4473**
4474** ARGUMENTS:
4475**
4476** arg Argument to evaluate.
4477*/
4478# define _gcmVERIFY_ARGUMENT(prefix, arg) \
4479 do \
4480 { \
4481 if (!(arg)) \
4482 { \
4483 prefix##TRACE(gcvLEVEL_ERROR, #prefix "VERIFY_ARGUMENT failed:"); \
4484 prefix##ASSERT(arg); \
4485 prefix##FOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT); \
4486 return gcvSTATUS_INVALID_ARGUMENT; \
4487 } \
4488 } \
4489 while (gcvFALSE)
4490# define gcmVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
4491# define gcmkVERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcmk, arg)
4492
4493/*******************************************************************************
4494**
4495** gcmDEBUG_VERIFY_ARGUMENT
4496**
4497** Works just like gcmVERIFY_ARGUMENT, but is only valid in debug mode.
4498** Use this to verify arguments inside non-public API functions.
4499*/
4500#if gcdDEBUG
4501# define gcmDEBUG_VERIFY_ARGUMENT(arg) _gcmVERIFY_ARGUMENT(gcm, arg)
4502# define gcmkDEBUG_VERIFY_ARGUMENT(arg) _gcmkVERIFY_ARGUMENT(gcm, arg)
4503#else
4504# define gcmDEBUG_VERIFY_ARGUMENT(arg)
4505# define gcmkDEBUG_VERIFY_ARGUMENT(arg)
4506#endif
4507
4508/*******************************************************************************
4509**
4510** gcmVERIFY_ARGUMENT_RETURN
4511**
4512** Assert if an argument does not apply to the specified expression. If
4513** the argument evaluates to false, gcvSTATUS_INVALID_ARGUMENT will be
4514** returned from the current function. In retail mode this macro does
4515** nothing.
4516**
4517** ARGUMENTS:
4518**
4519** arg Argument to evaluate.
4520*/
4521# define _gcmVERIFY_ARGUMENT_RETURN(prefix, arg, value) \
4522 do \
4523 { \
4524 if (!(arg)) \
4525 { \
4526 prefix##TRACE(gcvLEVEL_ERROR, \
4527 #prefix "gcmVERIFY_ARGUMENT_RETURN failed:"); \
4528 prefix##ASSERT(arg); \
4529 prefix##FOOTER_ARG("value=%d", value); \
4530 return value; \
4531 } \
4532 } \
4533 while (gcvFALSE)
4534# define gcmVERIFY_ARGUMENT_RETURN(arg, value) \
4535 _gcmVERIFY_ARGUMENT_RETURN(gcm, arg, value)
4536# define gcmkVERIFY_ARGUMENT_RETURN(arg, value) \
4537 _gcmVERIFY_ARGUMENT_RETURN(gcmk, arg, value)
4538
4539#define MAX_LOOP_COUNT 0x7FFFFFFF
4540
4541/******************************************************************************\
4542****************************** User Debug Option ******************************
4543\******************************************************************************/
4544
4545/* User option. */
4546typedef enum _gceDEBUG_MSG
4547{
4548 gcvDEBUG_MSG_NONE,
4549 gcvDEBUG_MSG_ERROR,
4550 gcvDEBUG_MSG_WARNING
4551}
4552gceDEBUG_MSG;
4553
4554typedef struct _gcsUSER_DEBUG_OPTION
4555{
4556 gceDEBUG_MSG debugMsg;
4557}
4558gcsUSER_DEBUG_OPTION;
4559
4560gcsUSER_DEBUG_OPTION *
4561gcGetUserDebugOption(
4562 void
4563 );
4564
4565#if defined(ANDROID)
4566struct _gcoOS_SymbolsList
4567{
4568 const char * symList[10];
4569};
4570#endif
4571
4572#if gcdHAS_ELLIPSIS
4573#define gcmUSER_DEBUG_MSG(level, ...) \
4574 do \
4575 { \
4576 if (level <= gcGetUserDebugOption()->debugMsg) \
4577 { \
4578 gcoOS_Print(__VA_ARGS__); \
4579 } \
4580 } while (gcvFALSE)
4581
4582#define gcmUSER_DEBUG_ERROR_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_ERROR, "Error: " __VA_ARGS__)
4583#define gcmUSER_DEBUG_WARNING_MSG(...) gcmUSER_DEBUG_MSG(gcvDEBUG_MSG_WARNING, "Warring: " __VA_ARGS__)
4584#else
4585#define gcmUSER_DEBUG_MSG
4586#define gcmUSER_DEBUG_ERROR_MSG
4587#define gcmUSER_DEBUG_WARNING_MSG
4588#endif
4589
4590/*******************************************************************************
4591**
4592** A set of macros to aid state loading.
4593**
4594** ARGUMENTS:
4595**
4596** CommandBuffer Pointer to a gcoCMDBUF object.
4597** StateDelta Pointer to a gcsSTATE_DELTA state delta structure.
4598** Memory Destination memory pointer of gctUINT32_PTR type.
4599** PartOfContext Whether or not the state is a part of the context.
4600** FixedPoint Whether or not the state is of the fixed point format.
4601** Count Number of consecutive states to be loaded.
4602** Address State address.
4603** Data Data to be set to the state.
4604*/
4605
4606/*----------------------------------------------------------------------------*/
4607
4608#if gcmIS_DEBUG(gcdDEBUG_CODE)
4609
4610# define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count) \
4611 CommandBuffer->lastLoadStatePtr = gcmPTR_TO_UINT64(Memory); \
4612 CommandBuffer->lastLoadStateAddress = Address; \
4613 CommandBuffer->lastLoadStateCount = Count
4614
4615# define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address) \
4616 gcmASSERT( \
4617 (gctUINT) (Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastLoadStatePtr, gctUINT32_PTR) - 1) \
4618 == \
4619 (gctUINT) (Address - CommandBuffer->lastLoadStateAddress) \
4620 ); \
4621 \
4622 gcmASSERT(CommandBuffer->lastLoadStateCount > 0); \
4623 \
4624 CommandBuffer->lastLoadStateCount -= 1
4625
4626# define gcmVERIFYLOADSTATEDONE(CommandBuffer) \
4627 gcmASSERT(CommandBuffer->lastLoadStateCount == 0);
4628
4629# define gcmDEFINELOADSTATEBASE() \
4630 gctUINT32_PTR LoadStateBase;
4631
4632# define gcmSETLOADSTATEBASE(CommandBuffer, OutSide) \
4633 if (OutSide) \
4634 {\
4635 LoadStateBase = (gctUINT32_PTR)*OutSide; \
4636 }\
4637 else\
4638 {\
4639 LoadStateBase = (gctUINT_PTR)CommandBuffer->buffer;\
4640 }
4641
4642
4643# define gcmVERIFYLOADSTATEALIGNED(CommandBuffer, Memory) \
4644 gcmASSERT(((Memory - LoadStateBase) & 1) == 0);
4645
4646# define gcmUNSETLOADSTATEBASE() \
4647 LoadStateBase = LoadStateBase;
4648
4649#else
4650
4651# define gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count)
4652# define gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address)
4653# define gcmVERIFYLOADSTATEDONE(CommandBuffer)
4654
4655# define gcmDEFINELOADSTATEBASE()
4656# define gcmSETLOADSTATEBASE(CommandBuffer, OutSide)
4657# define gcmVERIFYLOADSTATEALIGNED(CommandBuffer, Memory)
4658# define gcmUNSETLOADSTATEBASE()
4659
4660#endif
4661
4662#if gcdSECURE_USER
4663
4664# define gcmDEFINESECUREUSER() \
4665 gctUINT __secure_user_offset__; \
4666 gctUINT32_PTR __secure_user_hintArray__;
4667
4668# define gcmBEGINSECUREUSER() \
4669 __secure_user_offset__ = reserve->lastOffset; \
4670 \
4671 __secure_user_hintArray__ = gcmUINT64_TO_PTR(reserve->hintArrayTail)
4672
4673# define gcmENDSECUREUSER() \
4674 reserve->hintArrayTail = gcmPTR_TO_UINT64(__secure_user_hintArray__)
4675
4676# define gcmSKIPSECUREUSER() \
4677 __secure_user_offset__ += gcmSIZEOF(gctUINT32)
4678
4679# define gcmUPDATESECUREUSER() \
4680 *__secure_user_hintArray__ = __secure_user_offset__; \
4681 \
4682 __secure_user_offset__ += gcmSIZEOF(gctUINT32); \
4683 __secure_user_hintArray__ += 1
4684
4685#else
4686
4687# define gcmDEFINESECUREUSER()
4688# define gcmBEGINSECUREUSER()
4689# define gcmENDSECUREUSER()
4690# define gcmSKIPSECUREUSER()
4691# define gcmUPDATESECUREUSER()
4692
4693#endif
4694
4695/*----------------------------------------------------------------------------*/
4696
4697#if gcdDUMP
4698# define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data) \
4699 if (FixedPoint) \
4700 { \
4701 gcmDUMP(gcvNULL, "#[state.x 0x%04X 0x%08X]", \
4702 Address, Data \
4703 ); \
4704 } \
4705 else \
4706 { \
4707 gcmDUMP(gcvNULL, "#[state 0x%04X 0x%08X]", \
4708 Address, Data \
4709 ); \
4710 }
4711#else
4712# define gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, Data)
4713#endif
4714
4715#define gcmDEFINESTATEBUFFER(CommandBuffer, StateDelta, Memory, ReserveSize) \
4716 gcmDEFINESECUREUSER() \
4717 gctSIZE_T ReserveSize; \
4718 gcoCMDBUF CommandBuffer; \
4719 gctUINT32_PTR Memory; \
4720 gcsSTATE_DELTA_PTR StateDelta
4721
4722#define gcmBEGINSTATEBUFFER(Hardware, CommandBuffer, StateDelta, Memory, ReserveSize) \
4723{ \
4724 gcmONERROR(gcoBUFFER_Reserve( \
4725 Hardware->buffer, ReserveSize, gcvTRUE, gcvCOMMAND_3D, &CommandBuffer \
4726 )); \
4727 \
4728 Memory = (gctUINT32_PTR) gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
4729 \
4730 StateDelta = Hardware->delta; \
4731 \
4732 gcmBEGINSECUREUSER(); \
4733}
4734
4735#define gcmENDSTATEBUFFER(Hardware, CommandBuffer, Memory, ReserveSize) \
4736{ \
4737 gcmENDSECUREUSER(); \
4738 \
4739 gcmASSERT( \
4740 gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT8_PTR) + ReserveSize \
4741 == \
4742 (gctUINT8_PTR) Memory \
4743 ); \
4744}
4745
4746/*----------------------------------------------------------------------------*/
4747
4748#define gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, Count) \
4749{ \
4750 gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
4751 gcmASSERT((gctUINT32)Count <= 1024); \
4752 \
4753 gcmVERIFYLOADSTATEDONE(CommandBuffer); \
4754 \
4755 gcmSTORELOADSTATE(CommandBuffer, Memory, Address, Count); \
4756 \
4757 *Memory++ \
4758 = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
4759 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT, FixedPoint) \
4760 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, Count) \
4761 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
4762 \
4763 gcmSKIPSECUREUSER(); \
4764}
4765
4766#define gcmENDSTATEBATCH(CommandBuffer, Memory) \
4767{ \
4768 gcmVERIFYLOADSTATEDONE(CommandBuffer); \
4769 \
4770 gcmASSERT(((Memory - gcmUINT64_TO_TYPE(CommandBuffer->lastReserve, gctUINT32_PTR)) & 1) == 0); \
4771}
4772
4773/*----------------------------------------------------------------------------*/
4774
4775#define gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
4776 Address, Data) \
4777{ \
4778 gctUINT32 __temp_data32__; \
4779 \
4780 gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
4781 \
4782 gcmSAFECASTSIZET(__temp_data32__, Data); \
4783 \
4784 *Memory++ = __temp_data32__; \
4785 \
4786 gcoHARDWARE_UpdateDelta( \
4787 StateDelta, Address, 0, __temp_data32__ \
4788 ); \
4789 \
4790 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
4791 \
4792 gcmUPDATESECUREUSER(); \
4793}
4794
4795#define gcmSETSTATEDATAWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
4796 Address, Mask, Data) \
4797{ \
4798 gctUINT32 __temp_data32__; \
4799 \
4800 gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
4801 \
4802 __temp_data32__ = Data; \
4803 \
4804 *Memory++ = __temp_data32__; \
4805 \
4806 gcoHARDWARE_UpdateDelta( \
4807 StateDelta, Address, Mask, __temp_data32__ \
4808 ); \
4809 \
4810 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
4811 \
4812 gcmUPDATESECUREUSER(); \
4813}
4814
4815
4816#define gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data) \
4817{ \
4818 gctUINT32 __temp_data32__; \
4819 \
4820 gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
4821 \
4822 __temp_data32__ = Data; \
4823 \
4824 *Memory++ = __temp_data32__; \
4825 \
4826 gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
4827 \
4828 gcmSKIPSECUREUSER(); \
4829}
4830
4831#define gcmSETFILLER(CommandBuffer, Memory) \
4832{ \
4833 gcmVERIFYLOADSTATEDONE(CommandBuffer); \
4834 \
4835 Memory += 1; \
4836 \
4837 gcmSKIPSECUREUSER(); \
4838}
4839
4840/*----------------------------------------------------------------------------*/
4841
4842#define gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
4843 Address, Data) \
4844{ \
4845 gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
4846 gcmSETSTATEDATA(StateDelta, CommandBuffer, Memory, FixedPoint, \
4847 Address, Data); \
4848 gcmENDSTATEBATCH(CommandBuffer, Memory); \
4849}
4850
4851#define gcmSETSINGLESTATEWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
4852 Address, Mask, Data) \
4853{ \
4854 gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
4855 gcmSETSTATEDATAWITHMASK(StateDelta, CommandBuffer, Memory, FixedPoint, \
4856 Address, Mask, Data); \
4857 gcmENDSTATEBATCH(CommandBuffer, Memory); \
4858}
4859
4860
4861#define gcmSETSINGLECTRLSTATE(StateDelta, CommandBuffer, Memory, FixedPoint, \
4862 Address, Data) \
4863{ \
4864 gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
4865 gcmSETCTRLSTATE(StateDelta, CommandBuffer, Memory, Address, Data); \
4866 gcmENDSTATEBATCH(CommandBuffer, Memory); \
4867}
4868
4869
4870
4871#define gcmSETSEMASTALLPIPE(StateDelta, CommandBuffer, Memory, Data) \
4872{ \
4873 gcmSETSINGLESTATE(StateDelta, CommandBuffer, Memory, gcvFALSE, AQSemaphoreRegAddrs, Data); \
4874 \
4875 *Memory++ = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
4876 \
4877 *Memory++ = Data; \
4878 \
4879 gcmDUMP(gcvNULL, "#[stall 0x%08X 0x%08X]", \
4880 gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END), \
4881 gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE)); \
4882 \
4883 gcmSKIPSECUREUSER(); \
4884}
4885
4886/*******************************************************************************
4887**
4888** gcmSETSTARTDECOMMAND
4889**
4890** Form a START_DE command.
4891**
4892** ARGUMENTS:
4893**
4894** Memory Destination memory pointer of gctUINT32_PTR type.
4895** Count Number of the rectangles.
4896*/
4897
4898#define gcmSETSTARTDECOMMAND(Memory, Count) \
4899{ \
4900 *Memory++ \
4901 = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE, START_DE) \
4902 | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, COUNT, Count) \
4903 | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
4904 \
4905 *Memory++ = 0xDEADDEED; \
4906}
4907
4908/*****************************************
4909** Temp command buffer macro
4910*/
4911#define gcmDEFINESTATEBUFFER_NEW(CommandBuffer, StateDelta, Memory) \
4912 gcmDEFINESECUREUSER() \
4913 gcmDEFINELOADSTATEBASE() \
4914 gcsTEMPCMDBUF CommandBuffer = gcvNULL; \
4915 gctUINT32_PTR Memory; \
4916 gcsSTATE_DELTA_PTR StateDelta
4917
4918
4919#define gcmBEGINSTATEBUFFER_NEW(Hardware, CommandBuffer, StateDelta, Memory, OutSide) \
4920{ \
4921 if (OutSide) \
4922 {\
4923 Memory = (gctUINT32_PTR)*OutSide; \
4924 }\
4925 else \
4926 {\
4927 gcmONERROR(gcoBUFFER_StartTEMPCMDBUF( \
4928 Hardware->buffer, &CommandBuffer \
4929 ));\
4930 \
4931 Memory = (gctUINT32_PTR)(CommandBuffer->buffer); \
4932 \
4933 }\
4934 StateDelta = Hardware->delta; \
4935 \
4936 gcmBEGINSECUREUSER(); \
4937 gcmSETLOADSTATEBASE(CommandBuffer,OutSide);\
4938}
4939
4940#define gcmENDSTATEBUFFER_NEW(Hardware, CommandBuffer, Memory, OutSide) \
4941{ \
4942 gcmENDSECUREUSER(); \
4943 \
4944 if (OutSide) \
4945 {\
4946 *OutSide = Memory; \
4947 }\
4948 else \
4949 {\
4950 CommandBuffer->currentByteSize = (gctUINT32)((gctUINT8_PTR)Memory - \
4951 (gctUINT8_PTR)CommandBuffer->buffer); \
4952 \
4953 gcmONERROR(gcoBUFFER_EndTEMPCMDBUF(Hardware->buffer));\
4954 }\
4955 gcmUNSETLOADSTATEBASE()\
4956}
4957
4958/*----------------------------------------------------------------------------*/
4959
4960#define gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, Count) \
4961{ \
4962 gcmVERIFYLOADSTATEALIGNED(CommandBuffer,Memory);\
4963 gcmASSERT((gctUINT32)Count <= 1024); \
4964 \
4965 *Memory++ \
4966 = gcmSETFIELDVALUE(0, AQ_COMMAND_LOAD_STATE_COMMAND, OPCODE, LOAD_STATE) \
4967 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, FLOAT, FixedPoint) \
4968 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, COUNT, Count) \
4969 | gcmSETFIELD (0, AQ_COMMAND_LOAD_STATE_COMMAND, ADDRESS, Address); \
4970 \
4971 gcmSKIPSECUREUSER(); \
4972}
4973
4974#define gcmENDSTATEBATCH_NEW(CommandBuffer, Memory) \
4975 gcmVERIFYLOADSTATEALIGNED(CommandBuffer,Memory);
4976
4977/*----------------------------------------------------------------------------*/
4978
4979#define gcmSETSTATEDATA_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
4980 Address, Data) \
4981{ \
4982 gctUINT32 __temp_data32__; \
4983 \
4984 __temp_data32__ = Data; \
4985 \
4986 *Memory++ = __temp_data32__; \
4987 \
4988 gcoHARDWARE_UpdateDelta( \
4989 StateDelta, Address, 0, __temp_data32__ \
4990 ); \
4991 \
4992 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
4993 \
4994 gcmUPDATESECUREUSER(); \
4995}
4996
4997#define gcmSETSTATEDATAWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
4998 Address, Mask, Data) \
4999{ \
5000 gctUINT32 __temp_data32__; \
5001 \
5002 __temp_data32__ = Data; \
5003 \
5004 *Memory++ = __temp_data32__; \
5005 \
5006 gcoHARDWARE_UpdateDelta( \
5007 StateDelta, Address, Mask, __temp_data32__ \
5008 ); \
5009 \
5010 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
5011 \
5012 gcmUPDATESECUREUSER(); \
5013}
5014
5015
5016#define gcmSETCTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, Address, Data) \
5017{ \
5018 gctUINT32 __temp_data32__; \
5019 \
5020 __temp_data32__ = Data; \
5021 \
5022 *Memory++ = __temp_data32__; \
5023 \
5024 gcmDUMPSTATEDATA(StateDelta, gcvFALSE, Address, __temp_data32__); \
5025 \
5026 gcmSKIPSECUREUSER(); \
5027}
5028
5029#define gcmSETFILLER_NEW(CommandBuffer, Memory) \
5030{ \
5031 Memory += 1; \
5032 \
5033 gcmSKIPSECUREUSER(); \
5034}
5035
5036/*----------------------------------------------------------------------------*/
5037
5038#define gcmSETSINGLESTATE_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
5039 Address, Data) \
5040{ \
5041 gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
5042 gcmSETSTATEDATA_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
5043 Address, Data); \
5044 gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
5045}
5046
5047#define gcmSETSINGLESTATEWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
5048 Address, Mask, Data) \
5049{ \
5050 gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
5051 gcmSETSTATEDATAWITHMASK_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
5052 Address, Mask, Data); \
5053 gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
5054}
5055
5056
5057#define gcmSETSINGLECTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, FixedPoint, \
5058 Address, Data) \
5059{ \
5060 gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
5061 gcmSETCTRLSTATE_NEW(StateDelta, CommandBuffer, Memory, Address, Data); \
5062 gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
5063}
5064
5065
5066
5067#define gcmSETSEMASTALLPIPE_NEW(StateDelta, CommandBuffer, Memory, Data) \
5068{ \
5069 gcmSETSINGLESTATE_NEW(StateDelta, CommandBuffer, Memory, gcvFALSE, AQSemaphoreRegAddrs, Data); \
5070 \
5071 *Memory++ = gcmSETFIELDVALUE(0, STALL_COMMAND, OPCODE, STALL); \
5072 \
5073 *Memory++ = Data; \
5074 \
5075 gcmDUMP(gcvNULL, "#[stall 0x%08X 0x%08X]", \
5076 gcmSETFIELDVALUE(0, AQ_SEMAPHORE, SOURCE, FRONT_END), \
5077 gcmSETFIELDVALUE(0, AQ_SEMAPHORE, DESTINATION, PIXEL_ENGINE)); \
5078 \
5079 gcmSKIPSECUREUSER(); \
5080}
5081
5082#define gcmSETSTARTDECOMMAND_NEW(CommandBuffer, Memory, Count) \
5083{ \
5084 *Memory++ \
5085 = gcmSETFIELDVALUE(0, AQ_COMMAND_START_DE_COMMAND, OPCODE, START_DE) \
5086 | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, COUNT, Count) \
5087 | gcmSETFIELD (0, AQ_COMMAND_START_DE_COMMAND, DATA_COUNT, 0); \
5088 \
5089 *Memory++ = 0xDEADDEED; \
5090 \
5091}
5092
5093#define gcmSETSTATEDATA_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5094 Address, Data) \
5095{ \
5096 gctUINT32 __temp_data32__; \
5097 \
5098 __temp_data32__ = Data; \
5099 \
5100 *Memory++ = __temp_data32__; \
5101 \
5102 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
5103 \
5104 gcmUPDATESECUREUSER(); \
5105}
5106
5107#define gcmSETSTATEDATAWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5108 Address, Mask, Data) \
5109{ \
5110 gctUINT32 __temp_data32__; \
5111 \
5112 __temp_data32__ = Data; \
5113 \
5114 *Memory++ = __temp_data32__; \
5115 \
5116 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
5117 \
5118 gcmUPDATESECUREUSER(); \
5119}
5120
5121#define gcmSETSINGLESTATE_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5122 Address, Data) \
5123{ \
5124 gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
5125 gcmSETSTATEDATA_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5126 Address, Data); \
5127 gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
5128}
5129
5130#define gcmSETSINGLESTATEWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5131 Address, Mask, Data) \
5132{ \
5133 gcmBEGINSTATEBATCH_NEW(CommandBuffer, Memory, FixedPoint, Address, 1); \
5134 gcmSETSTATEDATAWITHMASK_NEW_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5135 Address, Mask, Data); \
5136 gcmENDSTATEBATCH_NEW(CommandBuffer, Memory); \
5137}
5138
5139#define gcmSETSTATEDATA_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5140 Address, Data) \
5141{ \
5142 gctUINT32 __temp_data32__; \
5143 \
5144 gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
5145 \
5146 gcmSAFECASTSIZET(__temp_data32__, Data); \
5147 \
5148 *Memory++ = __temp_data32__; \
5149 \
5150 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
5151 \
5152 gcmUPDATESECUREUSER(); \
5153}
5154
5155#define gcmSETSTATEDATAWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5156 Address, Mask, Data) \
5157{ \
5158 gctUINT32 __temp_data32__; \
5159 \
5160 gcmVERIFYLOADSTATE(CommandBuffer, Memory, Address); \
5161 \
5162 __temp_data32__ = Data; \
5163 \
5164 *Memory++ = __temp_data32__; \
5165 \
5166 gcmDUMPSTATEDATA(StateDelta, FixedPoint, Address, __temp_data32__); \
5167 \
5168 gcmUPDATESECUREUSER(); \
5169}
5170
5171#define gcmSETSINGLESTATE_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5172 Address, Data) \
5173{ \
5174 gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
5175 gcmSETSTATEDATA_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5176 Address, Data); \
5177 gcmENDSTATEBATCH(CommandBuffer, Memory); \
5178}
5179
5180#define gcmSETSINGLESTATEWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5181 Address, Mask, Data) \
5182{ \
5183 gcmBEGINSTATEBATCH(CommandBuffer, Memory, FixedPoint, Address, 1); \
5184 gcmSETSTATEDATAWITHMASK_FAST(StateDelta, CommandBuffer, Memory, FixedPoint, \
5185 Address, Mask, Data); \
5186 gcmENDSTATEBATCH(CommandBuffer, Memory); \
5187}
5188
5189#define gcmDEFINESTATEBUFFER_NEW_FAST(CommandBuffer, Memory) \
5190 gcmDEFINESECUREUSER() \
5191 gcmDEFINELOADSTATEBASE() \
5192 gcsTEMPCMDBUF CommandBuffer = gcvNULL; \
5193 gctUINT32_PTR Memory;
5194
5195#define gcmDEFINESTATEBUFFER_FAST(CommandBuffer, Memory, ReserveSize) \
5196 gcmDEFINESECUREUSER() \
5197 gctSIZE_T ReserveSize; \
5198 gcoCMDBUF CommandBuffer; \
5199 gctUINT32_PTR Memory;
5200
5201#define gcmBEGINSTATEBUFFER_FAST(Hardware, CommandBuffer, Memory, ReserveSize) \
5202{ \
5203 gcmONERROR(gcoBUFFER_Reserve( \
5204 Hardware->buffer, ReserveSize, gcvTRUE, &CommandBuffer \
5205 )); \
5206 \
5207 Memory = (gctUINT32_PTR) gcmUINT64_TO_PTR(CommandBuffer->lastReserve); \
5208 \
5209 gcmBEGINSECUREUSER(); \
5210}
5211
5212#define gcmBEGINSTATEBUFFER_NEW_FAST(Hardware, CommandBuffer, Memory, OutSide) \
5213{ \
5214 if (OutSide) \
5215 {\
5216 Memory = (gctUINT32_PTR)*OutSide; \
5217 }\
5218 else \
5219 {\
5220 gcmONERROR(gcoBUFFER_StartTEMPCMDBUF( \
5221 Hardware->buffer, &CommandBuffer \
5222 ));\
5223 \
5224 Memory = (gctUINT32_PTR)(CommandBuffer->buffer); \
5225 \
5226 }\
5227 \
5228 gcmBEGINSECUREUSER(); \
5229 gcmSETLOADSTATEBASE(CommandBuffer,OutSide);\
5230}
5231/*******************************************************************************
5232**
5233** gcmCONFIGUREUNIFORMS
5234**
5235** Configure uniforms according to chip and numConstants.
5236*/
5237#if !gcdENABLE_UNIFIED_CONSTANT
5238#define gcmCONFIGUREUNIFORMS(ChipModel, ChipRevision, NumConstants, \
5239 UnifiedConst, VsConstBase, PsConstBase, VsConstMax, PsConstMax, ConstMax) \
5240{ \
5241 if (ChipModel == gcv2000 && ChipRevision == 0x5118) \
5242 { \
5243 UnifiedConst = gcvFALSE; \
5244 VsConstBase = AQVertexShaderConstRegAddrs; \
5245 PsConstBase = AQPixelShaderConstRegAddrs; \
5246 VsConstMax = 256; \
5247 PsConstMax = 64; \
5248 ConstMax = 320; \
5249 } \
5250 else if (NumConstants == 320) \
5251 { \
5252 UnifiedConst = gcvFALSE; \
5253 VsConstBase = AQVertexShaderConstRegAddrs; \
5254 PsConstBase = AQPixelShaderConstRegAddrs; \
5255 VsConstMax = 256; \
5256 PsConstMax = 64; \
5257 ConstMax = 320; \
5258 } \
5259 /* All GC1000 series chips can only support 64 uniforms for ps on non-unified const mode. */ \
5260 else if (NumConstants > 256 && ChipModel == gcv1000) \
5261 { \
5262 UnifiedConst = gcvFALSE; \
5263 VsConstBase = AQVertexShaderConstRegAddrs; \
5264 PsConstBase = AQPixelShaderConstRegAddrs; \
5265 VsConstMax = 256; \
5266 PsConstMax = 64; \
5267 ConstMax = 320; \
5268 } \
5269 else if (NumConstants > 256) \
5270 { \
5271 UnifiedConst = gcvFALSE; \
5272 VsConstBase = AQVertexShaderConstRegAddrs; \
5273 PsConstBase = AQPixelShaderConstRegAddrs; \
5274 VsConstMax = 256; \
5275 PsConstMax = 256; \
5276 ConstMax = 512; \
5277 } \
5278 else if (NumConstants == 256) \
5279 { \
5280 UnifiedConst = gcvFALSE; \
5281 VsConstBase = AQVertexShaderConstRegAddrs; \
5282 PsConstBase = AQPixelShaderConstRegAddrs; \
5283 VsConstMax = 256; \
5284 PsConstMax = 256; \
5285 ConstMax = 512; \
5286 } \
5287 else \
5288 { \
5289 UnifiedConst = gcvFALSE; \
5290 VsConstBase = AQVertexShaderConstRegAddrs; \
5291 PsConstBase = AQPixelShaderConstRegAddrs; \
5292 VsConstMax = 168; \
5293 PsConstMax = 64; \
5294 ConstMax = 232; \
5295 } \
5296}
5297#else
5298#define gcmCONFIGUREUNIFORMS(ChipModel, ChipRevision, NumConstants, \
5299 UnifiedConst, VsConstBase, PsConstBase, VsConstMax, PsConstMax, ConstMax) \
5300{ \
5301 if (NumConstants > 256) \
5302 { \
5303 UnifiedConst = gcvTRUE; \
5304 VsConstBase = gcregSHUniformsRegAddrs; \
5305 PsConstBase = gcregSHUniformsRegAddrs; \
5306 VsConstMax = gcmMIN(512, NumConstants - 64); \
5307 PsConstMax = gcmMIN(512, NumConstants - 64); \
5308 ConstMax = NumConstants; \
5309 } \
5310 else if (NumConstants == 256) \
5311 { \
5312 if (ChipModel == gcv2000 && ChipRevision == 0x5118) \
5313 { \
5314 UnifiedConst = gcvFALSE; \
5315 VsConstBase = AQVertexShaderConstRegAddrs; \
5316 PsConstBase = AQPixelShaderConstRegAddrs; \
5317 VsConstMax = 256; \
5318 PsConstMax = 64; \
5319 ConstMax = 320; \
5320 } \
5321 else \
5322 { \
5323 UnifiedConst = gcvFALSE; \
5324 VsConstBase = AQVertexShaderConstRegAddrs; \
5325 PsConstBase = AQPixelShaderConstRegAddrs; \
5326 VsConstMax = 256; \
5327 PsConstMax = 256; \
5328 ConstMax = 512; \
5329 } \
5330 } \
5331 else \
5332 { \
5333 UnifiedConst = gcvFALSE; \
5334 VsConstBase = AQVertexShaderConstRegAddrs; \
5335 PsConstBase = AQPixelShaderConstRegAddrs; \
5336 VsConstMax = 168; \
5337 PsConstMax = 64; \
5338 ConstMax = 232; \
5339 } \
5340}
5341#endif
5342
5343#ifdef __cplusplus
5344}
5345#endif
5346
5347#endif /* __gc_hal_base_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_driver.h b/src/hal/kernel/inc/gc_hal_driver.h
new file mode 100755
index 0000000..9530c82
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_driver.h
@@ -0,0 +1,1203 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_driver_h_
57#define __gc_hal_driver_h_
58
59#include "gc_hal_enum.h"
60#include "gc_hal_types.h"
61
62
63#ifdef __cplusplus
64extern "C" {
65#endif
66
67/******************************************************************************\
68******************************* I/O Control Codes ******************************
69\******************************************************************************/
70
71#define gcvHAL_CLASS "galcore"
72#define IOCTL_GCHAL_INTERFACE 30000
73#define IOCTL_GCHAL_KERNEL_INTERFACE 30001
74#define IOCTL_GCHAL_TERMINATE 30002
75
76/******************************************************************************\
77********************************* Command Codes ********************************
78\******************************************************************************/
79
80typedef enum _gceHAL_COMMAND_CODES
81{
82 /* Generic query. */
83 gcvHAL_QUERY_VIDEO_MEMORY,
84 gcvHAL_QUERY_CHIP_IDENTITY,
85
86 /* Contiguous memory. */
87 gcvHAL_ALLOCATE_NON_PAGED_MEMORY,
88 gcvHAL_FREE_NON_PAGED_MEMORY,
89 gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY,
90 gcvHAL_FREE_CONTIGUOUS_MEMORY,
91
92 /* Video memory allocation. */
93 gcvHAL_ALLOCATE_VIDEO_MEMORY, /* Enforced alignment. */
94 gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY, /* No alignment. */
95 gcvHAL_RELEASE_VIDEO_MEMORY,
96
97 /* Physical-to-logical mapping. */
98 gcvHAL_MAP_MEMORY,
99 gcvHAL_UNMAP_MEMORY,
100
101 /* Logical-to-physical mapping. */
102 gcvHAL_MAP_USER_MEMORY,
103 gcvHAL_UNMAP_USER_MEMORY,
104
105 /* Surface lock/unlock. */
106 gcvHAL_LOCK_VIDEO_MEMORY,
107 gcvHAL_UNLOCK_VIDEO_MEMORY,
108
109 /* Event queue. */
110 gcvHAL_EVENT_COMMIT,
111
112 gcvHAL_USER_SIGNAL,
113 gcvHAL_SIGNAL,
114 gcvHAL_WRITE_DATA,
115
116 gcvHAL_COMMIT,
117 gcvHAL_STALL,
118
119 gcvHAL_READ_REGISTER,
120 gcvHAL_WRITE_REGISTER,
121
122 gcvHAL_GET_PROFILE_SETTING,
123 gcvHAL_SET_PROFILE_SETTING,
124
125 gcvHAL_READ_ALL_PROFILE_REGISTERS,
126 gcvHAL_PROFILE_REGISTERS_2D,
127#if VIVANTE_PROFILER_PERDRAW
128 gcvHAL_READ_PROFILER_REGISTER_SETTING,
129#endif
130
131 /* Power management. */
132 gcvHAL_SET_POWER_MANAGEMENT_STATE,
133 gcvHAL_QUERY_POWER_MANAGEMENT_STATE,
134
135 gcvHAL_GET_BASE_ADDRESS,
136
137 gcvHAL_SET_IDLE, /* reserved */
138
139 /* Queries. */
140 gcvHAL_QUERY_KERNEL_SETTINGS,
141
142 /* Reset. */
143 gcvHAL_RESET,
144
145 /* Map physical address into handle. */
146 gcvHAL_MAP_PHYSICAL,
147
148 /* Debugger stuff. */
149 gcvHAL_DEBUG,
150
151 /* Cache stuff. */
152 gcvHAL_CACHE,
153
154 /* TimeStamp */
155 gcvHAL_TIMESTAMP,
156
157 /* Database. */
158 gcvHAL_DATABASE,
159
160 /* Version. */
161 gcvHAL_VERSION,
162
163 /* Chip info */
164 gcvHAL_CHIP_INFO,
165
166 /* Process attaching/detaching. */
167 gcvHAL_ATTACH,
168 gcvHAL_DETACH,
169
170 /* Composition. */
171 gcvHAL_COMPOSE,
172
173 /* Set timeOut value */
174 gcvHAL_SET_TIMEOUT,
175
176 /* Frame database. */
177 gcvHAL_GET_FRAME_INFO,
178
179 gcvHAL_QUERY_COMMAND_BUFFER,
180
181 gcvHAL_COMMIT_DONE,
182
183 /* GPU and event dump */
184 gcvHAL_DUMP_GPU_STATE,
185 gcvHAL_DUMP_EVENT,
186
187 /* Virtual command buffer. */
188 gcvHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER,
189 gcvHAL_FREE_VIRTUAL_COMMAND_BUFFER,
190
191 /* FSCALE_VAL. */
192 gcvHAL_SET_FSCALE_VALUE,
193 gcvHAL_GET_FSCALE_VALUE,
194
195 gcvHAL_NAME_VIDEO_MEMORY,
196 gcvHAL_IMPORT_VIDEO_MEMORY,
197
198 /* Reset time stamp. */
199 gcvHAL_QUERY_RESET_TIME_STAMP,
200
201 /* Multi-GPU read/write. */
202 gcvHAL_READ_REGISTER_EX,
203 gcvHAL_WRITE_REGISTER_EX,
204
205 /* Sync point operations. */
206 gcvHAL_SYNC_POINT,
207
208 /* Create native fence and return its fd. */
209 gcvHAL_CREATE_NATIVE_FENCE,
210
211 /* Wait native fence for GPU. */
212 gcvHAL_WAIT_NATIVE_FENCE,
213
214 /* Destory MMU. */
215 gcvHAL_DESTROY_MMU,
216
217 /* Shared buffer. */
218 gcvHAL_SHBUF,
219
220 /* Config power management. */
221 gcvHAL_CONFIG_POWER_MANAGEMENT,
222
223 /* Connect a video node to an OS native fd. */
224 gcvHAL_GET_VIDEO_MEMORY_FD,
225
226 /* Wrap a user memory into a video memory node. */
227 gcvHAL_WRAP_USER_MEMORY,
228
229#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
230 gcvHAL_DEC300_READ,
231 gcvHAL_DEC300_WRITE,
232 gcvHAL_DEC300_FLUSH,
233 gcvHAL_DEC300_FLUSH_WAIT,
234#endif
235}
236gceHAL_COMMAND_CODES;
237
238/******************************************************************************\
239****************************** Interface Structure *****************************
240\******************************************************************************/
241
242#define gcdMAX_PROFILE_FILE_NAME 128
243
244/* Kernel settings. */
245typedef struct _gcsKERNEL_SETTINGS
246{
247 /* Used RealTime signal between kernel and user. */
248 gctINT signal;
249}
250gcsKERNEL_SETTINGS;
251
252typedef struct _gcsUSER_MEMORY_DESC
253{
254 /* Import flag. */
255 gctUINT32 flag;
256
257 /* gcvALLOC_FLAG_DMABUF */
258 gctUINT32 handle;
259
260 /* gcvALLOC_FLAG_USERMEMORY */
261 gctUINT64 logical;
262 gctUINT32 physical;
263 gctUINT32 size;
264}
265gcsUSER_MEMORY_DESC;
266
267
268/* gcvHAL_QUERY_CHIP_IDENTITY */
269typedef struct _gcsHAL_QUERY_CHIP_IDENTITY * gcsHAL_QUERY_CHIP_IDENTITY_PTR;
270typedef struct _gcsHAL_QUERY_CHIP_IDENTITY
271{
272
273 /* Chip model. */
274 gceCHIPMODEL chipModel;
275
276 /* Revision value.*/
277 gctUINT32 chipRevision;
278
279 /* Supported feature fields. */
280 gctUINT32 chipFeatures;
281
282 /* Supported minor feature fields. */
283 gctUINT32 chipMinorFeatures;
284
285 /* Supported minor feature 1 fields. */
286 gctUINT32 chipMinorFeatures1;
287
288 /* Supported minor feature 2 fields. */
289 gctUINT32 chipMinorFeatures2;
290
291 /* Supported minor feature 3 fields. */
292 gctUINT32 chipMinorFeatures3;
293
294 /* Supported minor feature 4 fields. */
295 gctUINT32 chipMinorFeatures4;
296
297 /* Supported minor feature 5 fields. */
298 gctUINT32 chipMinorFeatures5;
299
300 /* Supported minor feature 5 fields. */
301 gctUINT32 chipMinorFeatures6;
302
303 /* Number of streams supported. */
304 gctUINT32 streamCount;
305
306 /* Total number of temporary registers per thread. */
307 gctUINT32 registerMax;
308
309 /* Maximum number of threads. */
310 gctUINT32 threadCount;
311
312 /* Number of shader cores. */
313 gctUINT32 shaderCoreCount;
314
315 /* Size of the vertex cache. */
316 gctUINT32 vertexCacheSize;
317
318 /* Number of entries in the vertex output buffer. */
319 gctUINT32 vertexOutputBufferSize;
320
321 /* Number of pixel pipes. */
322 gctUINT32 pixelPipes;
323
324 /* Number of instructions. */
325 gctUINT32 instructionCount;
326
327 /* Number of constants. */
328 gctUINT32 numConstants;
329
330 /* Buffer size */
331 gctUINT32 bufferSize;
332
333 /* Number of varyings */
334 gctUINT32 varyingsCount;
335
336 /* Supertile layout style in hardware */
337 gctUINT32 superTileMode;
338
339
340 /* Special control bits for 2D chip. */
341 gctUINT32 chip2DControl;
342
343 /* Product ID */
344 gctUINT32 productID;
345
346 /* Special chip flag bits */
347 gceCHIP_FLAG chipFlags;
348}
349gcsHAL_QUERY_CHIP_IDENTITY;
350
351/* gcvHAL_COMPOSE. */
352typedef struct _gcsHAL_COMPOSE * gcsHAL_COMPOSE_PTR;
353typedef struct _gcsHAL_COMPOSE
354{
355 /* Composition state buffer. */
356 gctUINT64 physical;
357 gctUINT64 logical;
358 gctUINT offset;
359 gctUINT size;
360
361 /* Composition end signal. */
362 gctUINT64 process;
363 gctUINT64 signal;
364
365 /* User signals. */
366 gctUINT64 userProcess;
367 gctUINT64 userSignal1;
368 gctUINT64 userSignal2;
369
370#if defined(__QNXNTO__)
371 /* Client pulse side-channel connection ID. */
372 gctINT32 coid;
373
374 /* Set by server. */
375 gctINT32 rcvid;
376#endif
377}
378gcsHAL_COMPOSE;
379
380
381typedef struct _gcsHAL_INTERFACE
382{
383 /* Command code. */
384 gceHAL_COMMAND_CODES command;
385
386 /* Hardware type. */
387 gceHARDWARE_TYPE hardwareType;
388
389 /* Status value. */
390 gceSTATUS status;
391
392 /* Handle to this interface channel. */
393 gctUINT64 handle;
394
395 /* Pid of the client. */
396 gctUINT32 pid;
397
398 /* Union of command structures. */
399 union _u
400 {
401 /* gcvHAL_GET_BASE_ADDRESS */
402 struct _gcsHAL_GET_BASE_ADDRESS
403 {
404 /* Physical memory address of internal memory. */
405 OUT gctUINT32 baseAddress;
406 }
407 GetBaseAddress;
408
409 /* gcvHAL_QUERY_VIDEO_MEMORY */
410 struct _gcsHAL_QUERY_VIDEO_MEMORY
411 {
412 /* Physical memory address of internal memory. Just a name. */
413 OUT gctUINT32 internalPhysical;
414
415 /* Size in bytes of internal memory. */
416 OUT gctUINT64 internalSize;
417
418 /* Physical memory address of external memory. Just a name. */
419 OUT gctUINT32 externalPhysical;
420
421 /* Size in bytes of external memory.*/
422 OUT gctUINT64 externalSize;
423
424 /* Physical memory address of contiguous memory. Just a name. */
425 OUT gctUINT32 contiguousPhysical;
426
427 /* Size in bytes of contiguous memory.*/
428 OUT gctUINT64 contiguousSize;
429 }
430 QueryVideoMemory;
431
432 /* gcvHAL_QUERY_CHIP_IDENTITY */
433 gcsHAL_QUERY_CHIP_IDENTITY QueryChipIdentity;
434
435 /* gcvHAL_MAP_MEMORY */
436 struct _gcsHAL_MAP_MEMORY
437 {
438 /* Physical memory address to map. Just a name on Linux/Qnx. */
439 IN gctUINT32 physical;
440
441 /* Number of bytes in physical memory to map. */
442 IN gctUINT64 bytes;
443
444 /* Address of mapped memory. */
445 OUT gctUINT64 logical;
446 }
447 MapMemory;
448
449 /* gcvHAL_UNMAP_MEMORY */
450 struct _gcsHAL_UNMAP_MEMORY
451 {
452 /* Physical memory address to unmap. Just a name on Linux/Qnx. */
453 IN gctUINT32 physical;
454
455 /* Number of bytes in physical memory to unmap. */
456 IN gctUINT64 bytes;
457
458 /* Address of mapped memory to unmap. */
459 IN gctUINT64 logical;
460 }
461 UnmapMemory;
462
463 /* gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY */
464 struct _gcsHAL_ALLOCATE_LINEAR_VIDEO_MEMORY
465 {
466 /* Number of bytes to allocate. */
467 IN OUT gctUINT bytes;
468
469 /* Buffer alignment. */
470 IN gctUINT alignment;
471
472 /* Type of allocation. */
473 IN gceSURF_TYPE type;
474
475 /* Flag of allocation. */
476 IN gctUINT32 flag;
477
478 /* Memory pool to allocate from. */
479 IN OUT gcePOOL pool;
480
481 /* Allocated video memory. */
482 OUT gctUINT32 node;
483 }
484 AllocateLinearVideoMemory;
485
486 /* gcvHAL_ALLOCATE_VIDEO_MEMORY */
487 struct _gcsHAL_ALLOCATE_VIDEO_MEMORY
488 {
489 /* Width of rectangle to allocate. */
490 IN OUT gctUINT width;
491
492 /* Height of rectangle to allocate. */
493 IN OUT gctUINT height;
494
495 /* Depth of rectangle to allocate. */
496 IN gctUINT depth;
497
498 /* Format rectangle to allocate in gceSURF_FORMAT. */
499 IN gceSURF_FORMAT format;
500
501 /* Type of allocation. */
502 IN gceSURF_TYPE type;
503
504 /* Memory pool to allocate from. */
505 IN OUT gcePOOL pool;
506
507 /* Allocated video memory. */
508 OUT gctUINT32 node;
509 }
510 AllocateVideoMemory;
511
512 /* gcvHAL_RELEASE_VIDEO_MEMORY */
513 struct _gcsHAL_RELEASE_VIDEO_MEMORY
514 {
515 /* Allocated video memory. */
516 IN gctUINT32 node;
517
518#ifdef __QNXNTO__
519/* TODO: This is part of the unlock - why is it here? */
520 /* Mapped logical address to unmap in user space. */
521 OUT gctUINT64 memory;
522
523 /* Number of bytes to allocated. */
524 OUT gctUINT64 bytes;
525#endif
526 }
527 ReleaseVideoMemory;
528
529 /* gcvHAL_LOCK_VIDEO_MEMORY */
530 struct _gcsHAL_LOCK_VIDEO_MEMORY
531 {
532 /* Allocated video memory. */
533 IN gctUINT32 node;
534
535 /* Cache configuration. */
536 /* Only gcvPOOL_CONTIGUOUS and gcvPOOL_VIRUTAL
537 ** can be configured */
538 IN gctBOOL cacheable;
539
540 /* Hardware specific address. */
541 OUT gctUINT32 address;
542
543 /* Mapped logical address. */
544 OUT gctUINT64 memory;
545
546 /* Customer priviate handle*/
547 OUT gctUINT32 gid;
548
549 /* Bus address of a contiguous video node. */
550 OUT gctUINT64 physicalAddress;
551 }
552 LockVideoMemory;
553
554 /* gcvHAL_UNLOCK_VIDEO_MEMORY */
555 struct _gcsHAL_UNLOCK_VIDEO_MEMORY
556 {
557 /* Allocated video memory. */
558 IN gctUINT64 node;
559
560 /* Type of surface. */
561 IN gceSURF_TYPE type;
562
563 /* Flag to unlock surface asynchroneously. */
564 IN OUT gctBOOL asynchroneous;
565 }
566 UnlockVideoMemory;
567
568 /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
569 struct _gcsHAL_ALLOCATE_NON_PAGED_MEMORY
570 {
571 /* Number of bytes to allocate. */
572 IN OUT gctUINT64 bytes;
573
574 /* Physical address of allocation. Just a name. */
575 OUT gctUINT32 physical;
576
577 /* Logical address of allocation. */
578 OUT gctUINT64 logical;
579 }
580 AllocateNonPagedMemory;
581
582 /* gcvHAL_FREE_NON_PAGED_MEMORY */
583 struct _gcsHAL_FREE_NON_PAGED_MEMORY
584 {
585 /* Number of bytes allocated. */
586 IN gctUINT64 bytes;
587
588 /* Physical address of allocation. Just a name. */
589 IN gctUINT32 physical;
590
591 /* Logical address of allocation. */
592 IN gctUINT64 logical;
593 }
594 FreeNonPagedMemory;
595
596 /* gcvHAL_ALLOCATE_NON_PAGED_MEMORY */
597 struct _gcsHAL_ALLOCATE_VIRTUAL_COMMAND_BUFFER
598 {
599 /* Number of bytes to allocate. */
600 IN OUT gctUINT64 bytes;
601
602 /* Physical address of allocation. Just a name. */
603 OUT gctUINT32 physical;
604
605 /* Logical address of allocation. */
606 OUT gctUINT64 logical;
607 }
608 AllocateVirtualCommandBuffer;
609
610 /* gcvHAL_FREE_NON_PAGED_MEMORY */
611 struct _gcsHAL_FREE_VIRTUAL_COMMAND_BUFFER
612 {
613 /* Number of bytes allocated. */
614 IN gctUINT64 bytes;
615
616 /* Physical address of allocation. Just a name. */
617 IN gctUINT32 physical;
618
619 /* Logical address of allocation. */
620 IN gctUINT64 logical;
621 }
622 FreeVirtualCommandBuffer;
623
624 /* gcvHAL_EVENT_COMMIT. */
625 struct _gcsHAL_EVENT_COMMIT
626 {
627 /* Event queue in gcsQUEUE. */
628 IN gctUINT64 queue;
629
630 }
631 Event;
632
633 /* gcvHAL_COMMIT */
634 struct _gcsHAL_COMMIT
635 {
636 /* Context buffer object gckCONTEXT. */
637 IN gctUINT64 context;
638
639 /* Command buffer gcoCMDBUF. */
640 IN gctUINT64 commandBuffer;
641
642 /* State delta buffer in gcsSTATE_DELTA. */
643 gctUINT64 delta;
644
645 /* Event queue in gcsQUEUE. */
646 IN gctUINT64 queue;
647
648 }
649 Commit;
650
651 /* gcvHAL_MAP_USER_MEMORY */
652 struct _gcsHAL_MAP_USER_MEMORY
653 {
654 /* Base address of user memory to map. */
655 IN gctUINT64 memory;
656
657 /* Physical address of user memory to map. */
658 IN gctUINT32 physical;
659
660 /* Size of user memory in bytes to map. */
661 IN gctUINT64 size;
662
663 /* Info record required by gcvHAL_UNMAP_USER_MEMORY. Just a name. */
664 OUT gctUINT32 info;
665
666 /* Physical address of mapped memory. */
667 OUT gctUINT32 address;
668 }
669 MapUserMemory;
670
671 /* gcvHAL_UNMAP_USER_MEMORY */
672 struct _gcsHAL_UNMAP_USER_MEMORY
673 {
674 /* Base address of user memory to unmap. */
675 IN gctUINT64 memory;
676
677 /* Size of user memory in bytes to unmap. */
678 IN gctUINT64 size;
679
680 /* Info record returned by gcvHAL_MAP_USER_MEMORY. Just a name. */
681 IN gctUINT32 info;
682
683 /* Physical address of mapped memory as returned by
684 gcvHAL_MAP_USER_MEMORY. */
685 IN gctUINT32 address;
686 }
687 UnmapUserMemory;
688#if !USE_NEW_LINUX_SIGNAL
689 /* gcsHAL_USER_SIGNAL */
690 struct _gcsHAL_USER_SIGNAL
691 {
692 /* Command. */
693 gceUSER_SIGNAL_COMMAND_CODES command;
694
695 /* Signal ID. */
696 IN OUT gctINT id;
697
698 /* Reset mode. */
699 IN gctBOOL manualReset;
700
701 /* Wait timedout. */
702 IN gctUINT32 wait;
703
704 /* State. */
705 IN gctBOOL state;
706 }
707 UserSignal;
708#endif
709
710 /* gcvHAL_SIGNAL. */
711 struct _gcsHAL_SIGNAL
712 {
713 /* Signal handle to signal gctSIGNAL. */
714 IN gctUINT64 signal;
715
716 /* Reserved gctSIGNAL. */
717 IN gctUINT64 auxSignal;
718
719 /* Process owning the signal gctHANDLE. */
720 IN gctUINT64 process;
721
722#if defined(__QNXNTO__)
723 /* Client pulse side-channel connection ID. Set by client in gcoOS_CreateSignal. */
724 IN gctINT32 coid;
725
726 /* Set by server. */
727 IN gctINT32 rcvid;
728#endif
729 /* Event generated from where of pipeline */
730 IN gceKERNEL_WHERE fromWhere;
731 }
732 Signal;
733
734 /* gcvHAL_WRITE_DATA. */
735 struct _gcsHAL_WRITE_DATA
736 {
737 /* Address to write data to. */
738 IN gctUINT32 address;
739
740 /* Data to write. */
741 IN gctUINT32 data;
742 }
743 WriteData;
744
745 /* gcvHAL_ALLOCATE_CONTIGUOUS_MEMORY */
746 struct _gcsHAL_ALLOCATE_CONTIGUOUS_MEMORY
747 {
748 /* Number of bytes to allocate. */
749 IN OUT gctUINT64 bytes;
750
751 /* Hardware address of allocation. */
752 OUT gctUINT32 address;
753
754 /* Physical address of allocation. Just a name. */
755 OUT gctUINT32 physical;
756
757 /* Logical address of allocation. */
758 OUT gctUINT64 logical;
759 }
760 AllocateContiguousMemory;
761
762 /* gcvHAL_FREE_CONTIGUOUS_MEMORY */
763 struct _gcsHAL_FREE_CONTIGUOUS_MEMORY
764 {
765 /* Number of bytes allocated. */
766 IN gctUINT64 bytes;
767
768 /* Physical address of allocation. Just a name. */
769 IN gctUINT32 physical;
770
771 /* Logical address of allocation. */
772 IN gctUINT64 logical;
773 }
774 FreeContiguousMemory;
775
776 /* gcvHAL_READ_REGISTER */
777 struct _gcsHAL_READ_REGISTER
778 {
779 /* Logical address of memory to write data to. */
780 IN gctUINT32 address;
781
782 /* Data read. */
783 OUT gctUINT32 data;
784 }
785 ReadRegisterData;
786
787 /* gcvHAL_WRITE_REGISTER */
788 struct _gcsHAL_WRITE_REGISTER
789 {
790 /* Logical address of memory to write data to. */
791 IN gctUINT32 address;
792
793 /* Data read. */
794 IN gctUINT32 data;
795 }
796 WriteRegisterData;
797
798
799#if VIVANTE_PROFILER
800 /* gcvHAL_GET_PROFILE_SETTING */
801 struct _gcsHAL_GET_PROFILE_SETTING
802 {
803 /* Enable profiling */
804 OUT gctBOOL enable;
805 }
806 GetProfileSetting;
807
808 /* gcvHAL_SET_PROFILE_SETTING */
809 struct _gcsHAL_SET_PROFILE_SETTING
810 {
811 /* Enable profiling */
812 IN gctBOOL enable;
813 }
814 SetProfileSetting;
815
816#if VIVANTE_PROFILER_PERDRAW
817 /* gcvHAL_READ_PROFILER_REGISTER_SETTING */
818 struct _gcsHAL_READ_PROFILER_REGISTER_SETTING
819 {
820 /*Should Clear Register*/
821 IN gctBOOL bclear;
822 }
823 SetProfilerRegisterClear;
824#endif
825
826 /* gcvHAL_READ_ALL_PROFILE_REGISTERS */
827 struct _gcsHAL_READ_ALL_PROFILE_REGISTERS
828 {
829#if VIVANTE_PROFILER_CONTEXT
830 /* Context buffer object gckCONTEXT. Just a name. */
831 IN gctUINT32 context;
832#endif
833
834 /* Data read. */
835 OUT gcsPROFILER_COUNTERS counters;
836 }
837 RegisterProfileData;
838
839 /* gcvHAL_PROFILE_REGISTERS_2D */
840 struct _gcsHAL_PROFILE_REGISTERS_2D
841 {
842 /* Data read in gcs2D_PROFILE. */
843 OUT gctUINT64 hwProfile2D;
844 }
845 RegisterProfileData2D;
846#endif
847
848 /* Power management. */
849 /* gcvHAL_SET_POWER_MANAGEMENT_STATE */
850 struct _gcsHAL_SET_POWER_MANAGEMENT
851 {
852 /* Data read. */
853 IN gceCHIPPOWERSTATE state;
854 }
855 SetPowerManagement;
856
857 /* gcvHAL_QUERY_POWER_MANAGEMENT_STATE */
858 struct _gcsHAL_QUERY_POWER_MANAGEMENT
859 {
860 /* Data read. */
861 OUT gceCHIPPOWERSTATE state;
862
863 /* Idle query. */
864 OUT gctBOOL isIdle;
865 }
866 QueryPowerManagement;
867
868 /* gcvHAL_QUERY_KERNEL_SETTINGS */
869 struct _gcsHAL_QUERY_KERNEL_SETTINGS
870 {
871 /* Settings.*/
872 OUT gcsKERNEL_SETTINGS settings;
873 }
874 QueryKernelSettings;
875
876 /* gcvHAL_MAP_PHYSICAL */
877 struct _gcsHAL_MAP_PHYSICAL
878 {
879 /* gcvTRUE to map, gcvFALSE to unmap. */
880 IN gctBOOL map;
881
882 /* Physical address. */
883 IN OUT gctUINT64 physical;
884 }
885 MapPhysical;
886
887 /* gcvHAL_DEBUG */
888 struct _gcsHAL_DEBUG
889 {
890 /* If gcvTRUE, set the debug information. */
891 IN gctBOOL set;
892 IN gctUINT32 level;
893 IN gctUINT32 zones;
894 IN gctBOOL enable;
895
896 IN gceDEBUG_MESSAGE_TYPE type;
897 IN gctUINT32 messageSize;
898
899 /* Message to print if not empty. */
900 IN gctCHAR message[80];
901 }
902 Debug;
903
904 /* gcvHAL_CACHE */
905 struct _gcsHAL_CACHE
906 {
907 IN gceCACHEOPERATION operation;
908 IN gctUINT64 process;
909 IN gctUINT64 logical;
910 IN gctUINT64 bytes;
911 IN gctUINT32 node;
912 }
913 Cache;
914
915 /* gcvHAL_TIMESTAMP */
916 struct _gcsHAL_TIMESTAMP
917 {
918 /* Timer select. */
919 IN gctUINT32 timer;
920
921 /* Timer request type (0-stop, 1-start, 2-send delta). */
922 IN gctUINT32 request;
923
924 /* Result of delta time in microseconds. */
925 OUT gctINT32 timeDelta;
926 }
927 TimeStamp;
928
929 /* gcvHAL_DATABASE */
930 struct _gcsHAL_DATABASE
931 {
932 /* Set to gcvTRUE if you want to query a particular process ID.
933 ** Set to gcvFALSE to query the last detached process. */
934 IN gctBOOL validProcessID;
935
936 /* Process ID to query. */
937 IN gctUINT32 processID;
938
939 /* Information. */
940 OUT gcuDATABASE_INFO vidMem;
941 OUT gcuDATABASE_INFO nonPaged;
942 OUT gcuDATABASE_INFO contiguous;
943 OUT gcuDATABASE_INFO gpuIdle;
944
945 /* Detail information about video memory. */
946 OUT gcuDATABASE_INFO vidMemPool[3];
947 }
948 Database;
949
950 /* gcvHAL_VERSION */
951 struct _gcsHAL_VERSION
952 {
953 /* Major version: N.n.n. */
954 OUT gctINT32 major;
955
956 /* Minor version: n.N.n. */
957 OUT gctINT32 minor;
958
959 /* Patch version: n.n.N. */
960 OUT gctINT32 patch;
961
962 /* Build version. */
963 OUT gctUINT32 build;
964 }
965 Version;
966
967 /* gcvHAL_CHIP_INFO */
968 struct _gcsHAL_CHIP_INFO
969 {
970 /* Chip count. */
971 OUT gctINT32 count;
972
973 /* Chip types. */
974 OUT gceHARDWARE_TYPE types[gcdCHIP_COUNT];
975 }
976 ChipInfo;
977
978 /* gcvHAL_ATTACH */
979 struct _gcsHAL_ATTACH
980 {
981 /* Handle of context buffer object. */
982 OUT gctUINT32 context;
983
984 /* Maximum state in the buffer. */
985 OUT gctUINT64 maxState;
986
987 /* Number of states in the buffer. */
988 OUT gctUINT32 numStates;
989
990 /* Map context buffer to user or not. */
991 IN gctBOOL map;
992
993 /* Physical of context buffer. */
994 OUT gctUINT32 physicals[2];
995
996 /* Physical of context buffer. */
997 OUT gctUINT64 logicals[2];
998
999 /* Bytes of context buffer. */
1000 OUT gctUINT32 bytes;
1001 }
1002 Attach;
1003
1004 /* gcvHAL_DETACH */
1005 struct _gcsHAL_DETACH
1006 {
1007 /* Context buffer object gckCONTEXT. Just a name. */
1008 IN gctUINT32 context;
1009 }
1010 Detach;
1011
1012 /* gcvHAL_COMPOSE. */
1013 gcsHAL_COMPOSE Compose;
1014
1015 /* gcvHAL_GET_FRAME_INFO. */
1016 struct _gcsHAL_GET_FRAME_INFO
1017 {
1018 /* gcsHAL_FRAME_INFO* */
1019 OUT gctUINT64 frameInfo;
1020 }
1021 GetFrameInfo;
1022
1023 /* gcvHAL_SET_TIME_OUT. */
1024 struct _gcsHAL_SET_TIMEOUT
1025 {
1026 gctUINT32 timeOut;
1027 }
1028 SetTimeOut;
1029
1030
1031 struct _gcsHAL_SET_FSCALE_VALUE
1032 {
1033 IN gctUINT value;
1034 }
1035 SetFscaleValue;
1036
1037 struct _gcsHAL_GET_FSCALE_VALUE
1038 {
1039 OUT gctUINT value;
1040 OUT gctUINT minValue;
1041 OUT gctUINT maxValue;
1042 }
1043 GetFscaleValue;
1044
1045 struct _gcsHAL_NAME_VIDEO_MEMORY
1046 {
1047 IN gctUINT32 handle;
1048 OUT gctUINT32 name;
1049 }
1050 NameVideoMemory;
1051
1052 struct _gcsHAL_IMPORT_VIDEO_MEMORY
1053 {
1054 IN gctUINT32 name;
1055 OUT gctUINT32 handle;
1056 }
1057 ImportVideoMemory;
1058
1059 struct _gcsHAL_QUERY_RESET_TIME_STAMP
1060 {
1061 OUT gctUINT64 timeStamp;
1062 }
1063 QueryResetTimeStamp;
1064
1065 struct _gcsHAL_SYNC_POINT
1066 {
1067 /* Command. */
1068 gceSYNC_POINT_COMMAND_CODES command;
1069
1070 /* Sync point. */
1071 IN OUT gctUINT64 syncPoint;
1072
1073 /* From where. */
1074 IN gceKERNEL_WHERE fromWhere;
1075
1076 /* Signaled state. */
1077 OUT gctBOOL state;
1078 }
1079 SyncPoint;
1080
1081 struct _gcsHAL_CREATE_NATIVE_FENCE
1082 {
1083 /* Signal id to dup. */
1084 IN gctUINT64 syncPoint;
1085
1086 /* Native fence file descriptor. */
1087 OUT gctINT fenceFD;
1088
1089 }
1090 CreateNativeFence;
1091
1092 struct _gcsHAL_WAIT_NATIVE_FENCE
1093 {
1094 /* Native fence file descriptor. */
1095 IN gctINT fenceFD;
1096
1097 /* Wait timeout. */
1098 IN gctUINT32 timeout;
1099 }
1100 WaitNativeFence;
1101
1102 struct _gcsHAL_DESTROY_MMU
1103 {
1104 /* Mmu object. */
1105 IN gctUINT64 mmu;
1106 }
1107 DestroyMmu;
1108
1109 struct _gcsHAL_SHBUF
1110 {
1111 gceSHBUF_COMMAND_CODES command;
1112
1113 /* Shared buffer. */
1114 IN OUT gctUINT64 id;
1115
1116 /* User data to be shared. */
1117 IN gctUINT64 data;
1118
1119 /* Data size. */
1120 IN OUT gctUINT32 bytes;
1121 }
1122 ShBuf;
1123
1124 struct _gcsHAL_CONFIG_POWER_MANAGEMENT
1125 {
1126 IN gctBOOL enable;
1127 }
1128 ConfigPowerManagement;
1129
1130 struct _gcsHAL_GET_VIDEO_MEMORY_FD
1131 {
1132 IN gctUINT32 handle;
1133 OUT gctINT fd;
1134 }
1135 GetVideoMemoryFd;
1136
1137 struct _gcsHAL_WRAP_USER_MEMORY
1138 {
1139 /* Handle from other allocators. */
1140 IN gctUINT32 handle;
1141
1142 /* Allocation flag to wrap user memory*/
1143 IN gctUINT32 flag;
1144
1145 /* Video mmory node. */
1146 OUT gctUINT32 node;
1147
1148 /* Description of user memory. */
1149 IN gcsUSER_MEMORY_DESC desc;
1150 }
1151 WrapUserMemory;
1152
1153#if gcdENABLE_DEC_COMPRESSION && gcdDEC_ENABLE_AHB
1154 struct _gcsHAL_DEC300_READ
1155 {
1156 gctUINT32 enable;
1157 gctUINT32 readId;
1158 gctUINT32 format;
1159 gctUINT32 strides[3];
1160 gctUINT32 is3D;
1161 gctUINT32 isMSAA;
1162 gctUINT32 clearValue;
1163 gctUINT32 isTPC;
1164 gctUINT32 isTPCCompressed;
1165 gctUINT32 surfAddrs[3];
1166 gctUINT32 tileAddrs[3];
1167 }
1168 DEC300Read;
1169
1170 struct _gcsHAL_DEC300_WRITE
1171 {
1172 gctUINT32 enable;
1173 gctUINT32 readId;
1174 gctUINT32 writeId;
1175 gctUINT32 format;
1176 gctUINT32 surfAddr;
1177 gctUINT32 tileAddr;
1178 }
1179 DEC300Write;
1180
1181 struct _gcsHAL_DEC300_FLUSH
1182 {
1183 IN gctUINT8 useless;
1184 }
1185 DEC300Flush;
1186
1187 struct _gcsHAL_DEC300_FLUSH_WAIT
1188 {
1189 IN gctUINT32 done;
1190 }
1191 DEC300FlushWait;
1192#endif
1193 }
1194 u;
1195}
1196gcsHAL_INTERFACE;
1197
1198
1199#ifdef __cplusplus
1200}
1201#endif
1202
1203#endif /* __gc_hal_driver_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_dump.h b/src/hal/kernel/inc/gc_hal_dump.h
new file mode 100755
index 0000000..b203f8f
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_dump.h
@@ -0,0 +1,123 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_dump_h_
57#define __gc_hal_dump_h_
58
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63/*
64** FILE LAYOUT:
65**
66** gcsDUMP_FILE structure
67**
68** gcsDUMP_DATA frame
69** gcsDUMP_DATA or gcDUMP_DATA_SIZE records rendingring the frame
70** gctUINT8 data[length]
71*/
72
73#define gcvDUMP_FILE_SIGNATURE gcmCC('g','c','D','B')
74
75typedef struct _gcsDUMP_FILE
76{
77 gctUINT32 signature; /* File signature */
78 gctSIZE_T length; /* Length of file */
79 gctUINT32 frames; /* Number of frames in file */
80}
81gcsDUMP_FILE;
82
83typedef enum _gceDUMP_TAG
84{
85 gcvTAG_SURFACE = gcmCC('s','u','r','f'),
86 gcvTAG_FRAME = gcmCC('f','r','m',' '),
87 gcvTAG_COMMAND = gcmCC('c','m','d',' '),
88 gcvTAG_INDEX = gcmCC('i','n','d','x'),
89 gcvTAG_STREAM = gcmCC('s','t','r','m'),
90 gcvTAG_TEXTURE = gcmCC('t','e','x','t'),
91 gcvTAG_RENDER_TARGET = gcmCC('r','n','d','r'),
92 gcvTAG_DEPTH = gcmCC('z','b','u','f'),
93 gcvTAG_RESOLVE = gcmCC('r','s','l','v'),
94 gcvTAG_DELETE = gcmCC('d','e','l',' '),
95 gcvTAG_BUFOBJ = gcmCC('b','u','f','o'),
96}
97gceDUMP_TAG;
98
99typedef struct _gcsDUMP_SURFACE
100{
101 gceDUMP_TAG type; /* Type of record. */
102 gctUINT32 address; /* Address of the surface. */
103 gctINT16 width; /* Width of surface. */
104 gctINT16 height; /* Height of surface. */
105 gceSURF_FORMAT format; /* Surface pixel format. */
106 gctSIZE_T length; /* Number of bytes inside the surface. */
107}
108gcsDUMP_SURFACE;
109
110typedef struct _gcsDUMP_DATA
111{
112 gceDUMP_TAG type; /* Type of record. */
113 gctSIZE_T length; /* Number of bytes of data. */
114 gctUINT32 address; /* Address for the data. */
115}
116gcsDUMP_DATA;
117
118#ifdef __cplusplus
119}
120#endif
121
122#endif /* __gc_hal_dump_h_ */
123
diff --git a/src/hal/kernel/inc/gc_hal_eglplatform.h b/src/hal/kernel/inc/gc_hal_eglplatform.h
new file mode 100755
index 0000000..76326c2
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_eglplatform.h
@@ -0,0 +1,676 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_eglplatform_h_
57#define __gc_hal_eglplatform_h_
58
59/* Include VDK types. */
60#include "gc_hal_types.h"
61#include "gc_hal_base.h"
62#include "gc_hal_eglplatform_type.h"
63#ifdef __cplusplus
64extern "C" {
65#endif
66
67
68#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
69/* Win32 and Windows CE platforms. */
70#include <windows.h>
71typedef HDC HALNativeDisplayType;
72typedef HWND HALNativeWindowType;
73typedef HBITMAP HALNativePixmapType;
74
75typedef struct __BITFIELDINFO{
76 BITMAPINFO bmi;
77 RGBQUAD bmiColors[2];
78} BITFIELDINFO;
79
80#elif defined(LINUX) && defined(EGL_API_DFB) && !defined(__APPLE__)
81#include <directfb.h>
82typedef struct _DFBDisplay * HALNativeDisplayType;
83typedef struct _DFBWindow * HALNativeWindowType;
84typedef struct _DFBPixmap * HALNativePixmapType;
85
86#elif defined(LINUX) && defined(EGL_API_FB) && !defined(__APPLE__)
87
88#if defined(EGL_API_WL)
89
90#if defined(__GNUC__)
91# define inline __inline__ /* GNU keyword. */
92#endif
93
94/* Wayland platform. */
95#include <wayland-egl.h>
96
97#define WL_EGL_NUM_BACKBUFFERS 3
98#define WL_COMPOSITOR_SIGNATURE (0x31415926)
99
100typedef struct _gcsWL_VIV_BUFFER
101{
102 struct wl_resource *wl_buffer;
103 gcoSURF surface;
104 gctINT32 width, height;
105} gcsWL_VIV_BUFFER;
106
107typedef struct _gcsWL_EGL_DISPLAY
108{
109 struct wl_display* wl_display;
110 struct wl_viv* wl_viv;
111 struct wl_registry *registry;
112 struct wl_event_queue *wl_queue;
113 struct wl_event_queue *wl_swap_queue;
114 gctINT swapInterval;
115} gcsWL_EGL_DISPLAY;
116
117typedef struct _gcsWL_EGL_BUFFER_INFO
118{
119 gctINT32 width;
120 gctINT32 height;
121 gctINT32 stride;
122 gceSURF_FORMAT format;
123 gceSURF_TYPE type;
124 gcuVIDMEM_NODE_PTR node;
125 gcePOOL pool;
126 gctUINT bytes;
127 gcoSURF surface;
128 gcoSURF attached_surface;
129 gctINT32 invalidate;
130 gctBOOL locked;
131} gcsWL_EGL_BUFFER_INFO;
132
133typedef struct _gcsWL_EGL_BUFFER
134{
135 struct wl_buffer* wl_buffer;
136 gcsWL_EGL_BUFFER_INFO info;
137 struct wl_callback* frame_callback;
138} gcsWL_EGL_BUFFER;
139
140typedef struct _gcsWL_EGL_WINDOW_INFO
141{
142 gctINT32 dx;
143 gctINT32 dy;
144 gctUINT width;
145 gctUINT height;
146 gctINT32 attached_width;
147 gctINT32 attached_height;
148 gceSURF_FORMAT format;
149 gctUINT bpp;
150} gcsWL_EGL_WINDOW_INFO;
151
152struct wl_egl_window
153{
154 gcsWL_EGL_DISPLAY* display;
155 gcsWL_EGL_BUFFER backbuffers[WL_EGL_NUM_BACKBUFFERS];
156 gcsWL_EGL_WINDOW_INFO info;
157 gctUINT current;
158 struct wl_surface* surface;
159};
160
161typedef void* HALNativeDisplayType;
162typedef void* HALNativeWindowType;
163typedef void* HALNativePixmapType;
164#else
165/* Linux platform for FBDEV. */
166typedef struct _FBDisplay * HALNativeDisplayType;
167typedef struct _FBWindow * HALNativeWindowType;
168typedef struct _FBPixmap * HALNativePixmapType;
169#endif
170#elif defined(__ANDROID__) || defined(ANDROID)
171
172struct egl_native_pixmap_t;
173
174#if ANDROID_SDK_VERSION >= 9
175 #include <android/native_window.h>
176
177 typedef struct ANativeWindow* HALNativeWindowType;
178 typedef struct egl_native_pixmap_t* HALNativePixmapType;
179 typedef void* HALNativeDisplayType;
180#else
181 struct android_native_window_t;
182 typedef struct android_native_window_t* HALNativeWindowType;
183 typedef struct egl_native_pixmap_t * HALNativePixmapType;
184 typedef void* HALNativeDisplayType;
185#endif
186
187#elif defined(LINUX) || defined(__APPLE__)
188/* X11 platform. */
189#include <X11/Xlib.h>
190#include <X11/Xutil.h>
191
192typedef Display * HALNativeDisplayType;
193typedef Window HALNativeWindowType;
194
195#ifdef CUSTOM_PIXMAP
196typedef void * HALNativePixmapType;
197#else
198typedef Pixmap HALNativePixmapType;
199#endif /* CUSTOM_PIXMAP */
200
201/* Rename some badly named X defines. */
202#ifdef Status
203# define XStatus int
204# undef Status
205#endif
206#ifdef Always
207# define XAlways 2
208# undef Always
209#endif
210#ifdef CurrentTime
211# undef CurrentTime
212# define XCurrentTime 0
213#endif
214
215#elif defined(__QNXNTO__)
216#include <screen/screen.h>
217
218/* VOID */
219typedef int HALNativeDisplayType;
220typedef screen_window_t HALNativeWindowType;
221typedef screen_pixmap_t HALNativePixmapType;
222
223#else
224
225#error "Platform not recognized"
226
227/* VOID */
228typedef void * HALNativeDisplayType;
229typedef void * HALNativeWindowType;
230typedef void * HALNativePixmapType;
231
232#endif
233
234/* define DUMMY according to the system */
235#if defined(EGL_API_WL)
236# define WL_DUMMY (31415926)
237# define EGL_DUMMY WL_DUMMY
238#elif defined(__ANDROID__) || defined(ANDROID)
239# define ANDROID_DUMMY (31415926)
240# define EGL_DUMMY ANDROID_DUMMY
241#else
242# define EGL_DUMMY (31415926)
243#endif
244
245/*******************************************************************************
246** Display. ********************************************************************
247*/
248
249gceSTATUS
250gcoOS_GetDisplay(
251 OUT HALNativeDisplayType * Display,
252 IN gctPOINTER Context
253 );
254
255gceSTATUS
256gcoOS_GetDisplayByIndex(
257 IN gctINT DisplayIndex,
258 OUT HALNativeDisplayType * Display,
259 IN gctPOINTER Context
260 );
261
262gceSTATUS
263gcoOS_GetDisplayInfo(
264 IN HALNativeDisplayType Display,
265 OUT gctINT * Width,
266 OUT gctINT * Height,
267 OUT gctSIZE_T * Physical,
268 OUT gctINT * Stride,
269 OUT gctINT * BitsPerPixel
270 );
271
272
273
274gceSTATUS
275gcoOS_GetDisplayInfoEx(
276 IN HALNativeDisplayType Display,
277 IN HALNativeWindowType Window,
278 IN gctUINT DisplayInfoSize,
279 OUT halDISPLAY_INFO * DisplayInfo
280 );
281
282gceSTATUS
283gcoOS_GetDisplayVirtual(
284 IN HALNativeDisplayType Display,
285 OUT gctINT * Width,
286 OUT gctINT * Height
287 );
288
289gceSTATUS
290gcoOS_GetDisplayBackbuffer(
291 IN HALNativeDisplayType Display,
292 IN HALNativeWindowType Window,
293 OUT gctPOINTER * context,
294 OUT gcoSURF * surface,
295 OUT gctUINT * Offset,
296 OUT gctINT * X,
297 OUT gctINT * Y
298 );
299
300gceSTATUS
301gcoOS_SetDisplayVirtual(
302 IN HALNativeDisplayType Display,
303 IN HALNativeWindowType Window,
304 IN gctUINT Offset,
305 IN gctINT X,
306 IN gctINT Y
307 );
308
309gceSTATUS
310gcoOS_SetDisplayVirtualEx(
311 IN HALNativeDisplayType Display,
312 IN HALNativeWindowType Window,
313 IN gctPOINTER Context,
314 IN gcoSURF Surface,
315 IN gctUINT Offset,
316 IN gctINT X,
317 IN gctINT Y
318 );
319
320gceSTATUS
321gcoOS_SetSwapInterval(
322 IN HALNativeDisplayType Display,
323 IN gctINT Interval
324);
325
326gceSTATUS
327gcoOS_SetSwapIntervalEx(
328 IN HALNativeDisplayType Display,
329 IN gctINT Interval,
330 IN gctPOINTER localDisplay);
331
332gceSTATUS
333gcoOS_GetSwapInterval(
334 IN HALNativeDisplayType Display,
335 IN gctINT_PTR Min,
336 IN gctINT_PTR Max
337);
338
339gceSTATUS
340gcoOS_DisplayBufferRegions(
341 IN HALNativeDisplayType Display,
342 IN HALNativeWindowType Window,
343 IN gctINT NumRects,
344 IN gctINT_PTR Rects
345 );
346
347gceSTATUS
348gcoOS_DestroyDisplay(
349 IN HALNativeDisplayType Display
350 );
351
352gceSTATUS
353gcoOS_InitLocalDisplayInfo(
354 IN HALNativeDisplayType Display,
355 IN OUT gctPOINTER * localDisplay
356 );
357
358gceSTATUS
359gcoOS_DeinitLocalDisplayInfo(
360 IN HALNativeDisplayType Display,
361 IN OUT gctPOINTER * localDisplay
362 );
363
364gceSTATUS
365gcoOS_GetDisplayInfoEx2(
366 IN HALNativeDisplayType Display,
367 IN HALNativeWindowType Window,
368 IN gctPOINTER localDisplay,
369 IN gctUINT DisplayInfoSize,
370 OUT halDISPLAY_INFO * DisplayInfo
371 );
372
373gceSTATUS
374gcoOS_GetDisplayBackbufferEx(
375 IN HALNativeDisplayType Display,
376 IN HALNativeWindowType Window,
377 IN gctPOINTER localDisplay,
378 OUT gctPOINTER * context,
379 OUT gcoSURF * surface,
380 OUT gctUINT * Offset,
381 OUT gctINT * X,
382 OUT gctINT * Y
383 );
384
385gceSTATUS
386gcoOS_IsValidDisplay(
387 IN HALNativeDisplayType Display
388 );
389
390gceSTATUS
391gcoOS_GetNativeVisualId(
392 IN HALNativeDisplayType Display,
393 OUT gctINT* nativeVisualId
394 );
395
396gctBOOL
397gcoOS_SynchronousFlip(
398 IN HALNativeDisplayType Display
399 );
400
401/*******************************************************************************
402** Windows. ********************************************************************
403*/
404
405gceSTATUS
406gcoOS_CreateWindow(
407 IN HALNativeDisplayType Display,
408 IN gctINT X,
409 IN gctINT Y,
410 IN gctINT Width,
411 IN gctINT Height,
412 OUT HALNativeWindowType * Window
413 );
414
415gceSTATUS
416gcoOS_GetWindowInfo(
417 IN HALNativeDisplayType Display,
418 IN HALNativeWindowType Window,
419 OUT gctINT * X,
420 OUT gctINT * Y,
421 OUT gctINT * Width,
422 OUT gctINT * Height,
423 OUT gctINT * BitsPerPixel,
424 OUT gctUINT * Offset
425 );
426
427gceSTATUS
428gcoOS_SetWindowFormat(
429 IN HALNativeDisplayType Display,
430 IN HALNativeWindowType Window,
431 IN gceTILING Tiling,
432 IN gceSURF_FORMAT Format
433 );
434
435gceSTATUS
436gcoOS_DestroyWindow(
437 IN HALNativeDisplayType Display,
438 IN HALNativeWindowType Window
439 );
440
441gceSTATUS
442gcoOS_DrawImage(
443 IN HALNativeDisplayType Display,
444 IN HALNativeWindowType Window,
445 IN gctINT Left,
446 IN gctINT Top,
447 IN gctINT Right,
448 IN gctINT Bottom,
449 IN gctINT Width,
450 IN gctINT Height,
451 IN gctINT BitsPerPixel,
452 IN gctPOINTER Bits
453 );
454
455gceSTATUS
456gcoOS_GetImage(
457 IN HALNativeWindowType Window,
458 IN gctINT Left,
459 IN gctINT Top,
460 IN gctINT Right,
461 IN gctINT Bottom,
462 OUT gctINT * BitsPerPixel,
463 OUT gctPOINTER * Bits
464 );
465
466gceSTATUS
467gcoOS_GetWindowInfoEx(
468 IN HALNativeDisplayType Display,
469 IN HALNativeWindowType Window,
470 OUT gctINT * X,
471 OUT gctINT * Y,
472 OUT gctINT * Width,
473 OUT gctINT * Height,
474 OUT gctINT * BitsPerPixel,
475 OUT gctUINT * Offset,
476 OUT gceSURF_FORMAT * Format
477 );
478
479gceSTATUS
480gcoOS_DrawImageEx(
481 IN HALNativeDisplayType Display,
482 IN HALNativeWindowType Window,
483 IN gctINT Left,
484 IN gctINT Top,
485 IN gctINT Right,
486 IN gctINT Bottom,
487 IN gctINT Width,
488 IN gctINT Height,
489 IN gctINT BitsPerPixel,
490 IN gctPOINTER Bits,
491 IN gceSURF_FORMAT Format
492 );
493
494/*******************************************************************************
495** Pixmaps. ********************************************************************
496*/
497
498gceSTATUS
499gcoOS_CreatePixmap(
500 IN HALNativeDisplayType Display,
501 IN gctINT Width,
502 IN gctINT Height,
503 IN gctINT BitsPerPixel,
504 OUT HALNativePixmapType * Pixmap
505 );
506
507gceSTATUS
508gcoOS_GetPixmapInfo(
509 IN HALNativeDisplayType Display,
510 IN HALNativePixmapType Pixmap,
511 OUT gctINT * Width,
512 OUT gctINT * Height,
513 OUT gctINT * BitsPerPixel,
514 OUT gctINT * Stride,
515 OUT gctPOINTER * Bits
516 );
517
518gceSTATUS
519gcoOS_DrawPixmap(
520 IN HALNativeDisplayType Display,
521 IN HALNativePixmapType Pixmap,
522 IN gctINT Left,
523 IN gctINT Top,
524 IN gctINT Right,
525 IN gctINT Bottom,
526 IN gctINT Width,
527 IN gctINT Height,
528 IN gctINT BitsPerPixel,
529 IN gctPOINTER Bits
530 );
531
532gceSTATUS
533gcoOS_DestroyPixmap(
534 IN HALNativeDisplayType Display,
535 IN HALNativePixmapType Pixmap
536 );
537
538gceSTATUS
539gcoOS_GetPixmapInfoEx(
540 IN HALNativeDisplayType Display,
541 IN HALNativePixmapType Pixmap,
542 OUT gctINT * Width,
543 OUT gctINT * Height,
544 OUT gctINT * BitsPerPixel,
545 OUT gctINT * Stride,
546 OUT gctPOINTER * Bits,
547 OUT gceSURF_FORMAT * Format
548 );
549
550gceSTATUS
551gcoOS_CopyPixmapBits(
552 IN HALNativeDisplayType Display,
553 IN HALNativePixmapType Pixmap,
554 IN gctUINT DstWidth,
555 IN gctUINT DstHeight,
556 IN gctINT DstStride,
557 IN gceSURF_FORMAT DstFormat,
558 OUT gctPOINTER DstBits
559 );
560
561/*******************************************************************************
562** OS relative. ****************************************************************
563*/
564gceSTATUS
565gcoOS_LoadEGLLibrary(
566 OUT gctHANDLE * Handle
567 );
568
569gceSTATUS
570gcoOS_FreeEGLLibrary(
571 IN gctHANDLE Handle
572 );
573
574gceSTATUS
575gcoOS_ShowWindow(
576 IN HALNativeDisplayType Display,
577 IN HALNativeWindowType Window
578 );
579
580gceSTATUS
581gcoOS_HideWindow(
582 IN HALNativeDisplayType Display,
583 IN HALNativeWindowType Window
584 );
585
586gceSTATUS
587gcoOS_SetWindowTitle(
588 IN HALNativeDisplayType Display,
589 IN HALNativeWindowType Window,
590 IN gctCONST_STRING Title
591 );
592
593gceSTATUS
594gcoOS_CapturePointer(
595 IN HALNativeDisplayType Display,
596 IN HALNativeWindowType Window
597 );
598
599gceSTATUS
600gcoOS_GetEvent(
601 IN HALNativeDisplayType Display,
602 IN HALNativeWindowType Window,
603 OUT halEvent * Event
604 );
605
606gceSTATUS
607gcoOS_CreateClientBuffer(
608 IN gctINT Width,
609 IN gctINT Height,
610 IN gctINT Format,
611 IN gctINT Type,
612 OUT gctPOINTER * ClientBuffer
613 );
614
615gceSTATUS
616gcoOS_GetClientBufferInfo(
617 IN gctPOINTER ClientBuffer,
618 OUT gctINT * Width,
619 OUT gctINT * Height,
620 OUT gctINT * Stride,
621 OUT gctPOINTER * Bits
622 );
623
624gceSTATUS
625gcoOS_DestroyClientBuffer(
626 IN gctPOINTER ClientBuffer
627 );
628
629gceSTATUS
630gcoOS_DestroyContext(
631 IN gctPOINTER Display,
632 IN gctPOINTER Context
633 );
634
635gceSTATUS
636gcoOS_CreateContext(
637 IN gctPOINTER LocalDisplay,
638 IN gctPOINTER Context
639 );
640
641gceSTATUS
642gcoOS_MakeCurrent(
643 IN gctPOINTER LocalDisplay,
644 IN HALNativeWindowType DrawDrawable,
645 IN HALNativeWindowType ReadDrawable,
646 IN gctPOINTER Context,
647 IN gcoSURF ResolveTarget
648 );
649
650gceSTATUS
651gcoOS_CreateDrawable(
652 IN gctPOINTER LocalDisplay,
653 IN HALNativeWindowType Drawable
654 );
655
656gceSTATUS
657gcoOS_DestroyDrawable(
658 IN gctPOINTER LocalDisplay,
659 IN HALNativeWindowType Drawable
660 );
661gceSTATUS
662gcoOS_SwapBuffers(
663 IN gctPOINTER LocalDisplay,
664 IN HALNativeWindowType Drawable,
665 IN gcoSURF RenderTarget,
666 IN gcoSURF ResolveTarget,
667 IN gctPOINTER ResolveBits,
668 OUT gctUINT *Width,
669 OUT gctUINT *Height
670 );
671#ifdef __cplusplus
672}
673#endif
674
675#endif /* __gc_hal_eglplatform_h_ */
676
diff --git a/src/hal/kernel/inc/gc_hal_enum.h b/src/hal/kernel/inc/gc_hal_enum.h
new file mode 100755
index 0000000..aeb11ef
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_enum.h
@@ -0,0 +1,1650 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_enum_h_
57#define __gc_hal_enum_h_
58
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63/* Chip models. */
64typedef enum _gceCHIPMODEL
65{
66 gcv200 = 0x0200,
67 gcv300 = 0x0300,
68 gcv320 = 0x0320,
69 gcv328 = 0x0328,
70 gcv350 = 0x0350,
71 gcv355 = 0x0355,
72 gcv400 = 0x0400,
73 gcv410 = 0x0410,
74 gcv420 = 0x0420,
75 gcv428 = 0x0428,
76 gcv450 = 0x0450,
77 gcv500 = 0x0500,
78 gcv520 = 0x0520,
79 gcv530 = 0x0530,
80 gcv600 = 0x0600,
81 gcv700 = 0x0700,
82 gcv800 = 0x0800,
83 gcv860 = 0x0860,
84 gcv880 = 0x0880,
85 gcv1000 = 0x1000,
86 gcv1500 = 0x1500,
87 gcv2000 = 0x2000,
88 gcv2100 = 0x2100,
89 gcv2200 = 0x2200,
90 gcv2500 = 0x2500,
91 gcv3000 = 0x3000,
92 gcv4000 = 0x4000,
93 gcv5000 = 0x5000,
94 gcv5200 = 0x5200,
95 gcv6400 = 0x6400,
96}
97gceCHIPMODEL;
98
99/* Chip features. */
100typedef enum _gceFEATURE
101{
102 gcvFEATURE_PIPE_2D = 0,
103 gcvFEATURE_PIPE_3D,
104 gcvFEATURE_PIPE_VG,
105 gcvFEATURE_DC,
106 gcvFEATURE_HIGH_DYNAMIC_RANGE,
107 gcvFEATURE_MODULE_CG,
108 gcvFEATURE_MIN_AREA,
109 gcvFEATURE_BUFFER_INTERLEAVING,
110 gcvFEATURE_BYTE_WRITE_2D,
111 gcvFEATURE_ENDIANNESS_CONFIG,
112 gcvFEATURE_DUAL_RETURN_BUS,
113 gcvFEATURE_DEBUG_MODE,
114 gcvFEATURE_YUY2_RENDER_TARGET,
115 gcvFEATURE_FRAGMENT_PROCESSOR,
116 gcvFEATURE_2DPE20,
117 gcvFEATURE_FAST_CLEAR,
118 gcvFEATURE_YUV420_TILER,
119 gcvFEATURE_YUY2_AVERAGING,
120 gcvFEATURE_FLIP_Y,
121 gcvFEATURE_EARLY_Z,
122 gcvFEATURE_COMPRESSION,
123 gcvFEATURE_MSAA,
124 gcvFEATURE_SPECIAL_ANTI_ALIASING,
125 gcvFEATURE_SPECIAL_MSAA_LOD,
126 gcvFEATURE_422_TEXTURE_COMPRESSION,
127 gcvFEATURE_DXT_TEXTURE_COMPRESSION,
128 gcvFEATURE_ETC1_TEXTURE_COMPRESSION,
129 gcvFEATURE_CORRECT_TEXTURE_CONVERTER,
130 gcvFEATURE_TEXTURE_8K,
131 gcvFEATURE_SCALER,
132 gcvFEATURE_YUV420_SCALER,
133 gcvFEATURE_SHADER_HAS_W,
134 gcvFEATURE_SHADER_HAS_SIGN,
135 gcvFEATURE_SHADER_HAS_FLOOR,
136 gcvFEATURE_SHADER_HAS_CEIL,
137 gcvFEATURE_SHADER_HAS_SQRT,
138 gcvFEATURE_SHADER_HAS_TRIG,
139 gcvFEATURE_VAA,
140 gcvFEATURE_HZ,
141 gcvFEATURE_CORRECT_STENCIL,
142 gcvFEATURE_VG20,
143 gcvFEATURE_VG_FILTER,
144 gcvFEATURE_VG21,
145 gcvFEATURE_VG_DOUBLE_BUFFER,
146 gcvFEATURE_MC20,
147 gcvFEATURE_SUPER_TILED,
148 gcvFEATURE_FAST_CLEAR_FLUSH,
149 gcvFEATURE_2D_FILTERBLIT_PLUS_ALPHABLEND,
150 gcvFEATURE_2D_DITHER,
151 gcvFEATURE_2D_A8_TARGET,
152 gcvFEATURE_2D_A8_NO_ALPHA,
153 gcvFEATURE_2D_FILTERBLIT_FULLROTATION,
154 gcvFEATURE_2D_BITBLIT_FULLROTATION,
155 gcvFEATURE_WIDE_LINE,
156 gcvFEATURE_FC_FLUSH_STALL,
157 gcvFEATURE_FULL_DIRECTFB,
158 gcvFEATURE_HALF_FLOAT_PIPE,
159 gcvFEATURE_LINE_LOOP,
160 gcvFEATURE_2D_YUV_BLIT,
161 gcvFEATURE_2D_TILING,
162 gcvFEATURE_NON_POWER_OF_TWO,
163 gcvFEATURE_3D_TEXTURE,
164 gcvFEATURE_TEXTURE_ARRAY,
165 gcvFEATURE_TILE_FILLER,
166 gcvFEATURE_LOGIC_OP,
167 gcvFEATURE_COMPOSITION,
168 gcvFEATURE_MIXED_STREAMS,
169 gcvFEATURE_2D_MULTI_SOURCE_BLT,
170 gcvFEATURE_END_EVENT,
171 gcvFEATURE_VERTEX_10_10_10_2,
172 gcvFEATURE_TEXTURE_10_10_10_2,
173 gcvFEATURE_TEXTURE_ANISOTROPIC_FILTERING,
174 gcvFEATURE_TEXTURE_FLOAT_HALF_FLOAT,
175 gcvFEATURE_2D_ROTATION_STALL_FIX,
176 gcvFEATURE_2D_MULTI_SOURCE_BLT_EX,
177 gcvFEATURE_BUG_FIXES10,
178 gcvFEATURE_2D_MINOR_TILING,
179 /* Supertiled compressed textures are supported. */
180 gcvFEATURE_TEX_COMPRRESSION_SUPERTILED,
181 gcvFEATURE_FAST_MSAA,
182 gcvFEATURE_BUG_FIXED_INDEXED_TRIANGLE_STRIP,
183 gcvFEATURE_INDEX_FETCH_FIX,
184 gcvFEATURE_TEXTURE_TILE_STATUS_READ,
185 gcvFEATURE_DEPTH_BIAS_FIX,
186 gcvFEATURE_RECT_PRIMITIVE,
187 gcvFEATURE_BUG_FIXES11,
188 gcvFEATURE_SUPERTILED_TEXTURE,
189 gcvFEATURE_2D_NO_COLORBRUSH_INDEX8,
190 gcvFEATURE_RS_YUV_TARGET,
191 gcvFEATURE_2D_FC_SOURCE,
192 gcvFEATURE_2D_CC_NOAA_SOURCE,
193 gcvFEATURE_PE_DITHER_FIX,
194 gcvFEATURE_2D_YUV_SEPARATE_STRIDE,
195 gcvFEATURE_FRUSTUM_CLIP_FIX,
196 gcvFEATURE_TEXTURE_SWIZZLE,
197 gcvFEATURE_PRIMITIVE_RESTART,
198 gcvFEATURE_TEXTURE_LINEAR,
199 gcvFEATURE_TEXTURE_YUV_ASSEMBLER,
200 gcvFEATURE_LINEAR_RENDER_TARGET,
201 gcvFEATURE_SHADER_HAS_ATOMIC,
202 gcvFEATURE_SHADER_HAS_INSTRUCTION_CACHE,
203 gcvFEATURE_SHADER_ENHANCEMENTS2,
204 gcvFEATURE_BUG_FIXES7,
205 gcvFEATURE_SHADER_HAS_RTNE,
206 gcvFEATURE_SHADER_HAS_EXTRA_INSTRUCTIONS2,
207 gcvFEATURE_SHADER_ENHANCEMENTS3,
208 gcvFEATURE_DYNAMIC_FREQUENCY_SCALING,
209 gcvFEATURE_SINGLE_BUFFER,
210 gcvFEATURE_OCCLUSION_QUERY,
211 gcvFEATURE_2D_GAMMA,
212 gcvFEATURE_2D_COLOR_SPACE_CONVERSION,
213 gcvFEATURE_2D_SUPER_TILE_VERSION,
214 gcvFEATURE_HALTI0,
215 gcvFEATURE_HALTI1,
216 gcvFEATURE_HALTI2,
217 gcvFEATURE_2D_MIRROR_EXTENSION,
218 gcvFEATURE_TEXTURE_ASTC,
219 gcvFEATURE_TEXTURE_ASTC_FIX,
220 gcvFEATURE_2D_SUPER_TILE_V1,
221 gcvFEATURE_2D_SUPER_TILE_V2,
222 gcvFEATURE_2D_SUPER_TILE_V3,
223 gcvFEATURE_2D_MULTI_SOURCE_BLT_EX2,
224 gcvFEATURE_NEW_RA,
225 gcvFEATURE_BUG_FIXED_IMPLICIT_PRIMITIVE_RESTART,
226 gcvFEATURE_PE_MULTI_RT_BLEND_ENABLE_CONTROL,
227 gcvFEATURE_SMALL_MSAA, /* An upgraded version of Fast MSAA */
228 gcvFEATURE_VERTEX_INST_ID_AS_ATTRIBUTE,
229 gcvFEATURE_DUAL_16,
230 gcvFEATURE_BRANCH_ON_IMMEDIATE_REG,
231 gcvFEATURE_2D_COMPRESSION,
232 gcvFEATURE_TPC_COMPRESSION,
233 gcvFEATURE_DEC_COMPRESSION,
234 gcvFEATURE_DEC_TPC_COMPRESSION,
235 gcvFEATURE_DEC_COMPRESSION_TILE_NV12_8BIT,
236 gcvFEATURE_DEC_COMPRESSION_TILE_NV12_10BIT,
237 gcvFEATURE_2D_OPF_YUV_OUTPUT,
238 gcvFEATURE_2D_FILTERBLIT_A8_ALPHA,
239 gcvFEATURE_2D_MULTI_SRC_BLT_TO_UNIFIED_DST_RECT,
240 gcvFEATURE_V2_COMPRESSION_Z16_FIX,
241
242 gcvFEATURE_VERTEX_INST_ID_AS_INTEGER,
243 gcvFEATURE_2D_YUV_MODE,
244 gcvFEATURE_ACE,
245 gcvFEATURE_COLOR_COMPRESSION,
246
247 gcvFEATURE_32BPP_COMPONENT_TEXTURE_CHANNEL_SWIZZLE,
248 gcvFEATURE_64BPP_HW_CLEAR_SUPPORT,
249 gcvFEATURE_TX_LERP_PRECISION_FIX,
250 gcvFEATURE_COMPRESSION_V2,
251 gcvFEATURE_MMU,
252 gcvFEATURE_COMPRESSION_V3,
253 gcvFEATURE_TX_DECOMPRESSOR,
254 gcvFEATURE_MRT_TILE_STATUS_BUFFER,
255 gcvFEATURE_COMPRESSION_V1,
256 gcvFEATURE_V1_COMPRESSION_Z16_DECOMPRESS_FIX,
257 gcvFEATURE_RTT,
258 gcvFEATURE_GENERICS,
259 gcvFEATURE_2D_ONE_PASS_FILTER,
260 gcvFEATURE_2D_ONE_PASS_FILTER_TAP,
261 gcvFEATURE_2D_POST_FLIP,
262 gcvFEATURE_2D_PIXEL_ALIGNMENT,
263 gcvFEATURE_CORRECT_AUTO_DISABLE_COUNT,
264 gcvFEATURE_CORRECT_AUTO_DISABLE_COUNT_WIDTH,
265
266 gcvFEATURE_HALTI3,
267 gcvFEATURE_EEZ,
268 gcvFEATURE_INTEGER_SIGNEXT_FIX,
269 gcvFEATURE_INTEGER_PIPE_FIX,
270 gcvFEATURE_PSOUTPUT_MAPPING,
271 gcvFEATURE_8K_RT_FIX,
272 gcvFEATURE_TX_TILE_STATUS_MAPPING,
273 gcvFEATURE_SRGB_RT_SUPPORT,
274 gcvFEATURE_UNIFORM_APERTURE,
275 gcvFEATURE_TEXTURE_16K,
276 gcvFEATURE_PA_FARZCLIPPING_FIX,
277 gcvFEATURE_PE_DITHER_COLORMASK_FIX,
278 gcvFEATURE_ZSCALE_FIX,
279
280 gcvFEATURE_MULTI_PIXELPIPES,
281 gcvFEATURE_PIPE_CL,
282
283 gcvFEATURE_BUG_FIXES18,
284
285 gcvFEATURE_UNIFIED_SAMPLERS,
286 gcvFEATURE_CL_PS_WALKER,
287 gcvFEATURE_NEW_HZ,
288
289 gcvFEATURE_TX_FRAC_PRECISION_6BIT,
290 gcvFEATURE_SH_INSTRUCTION_PREFETCH,
291 gcvFEATURE_PROBE,
292
293 gcvFEATURE_BUG_FIXES8,
294 gcvFEATURE_2D_ALL_QUAD,
295
296 gcvFEATURE_SINGLE_PIPE_HALTI1,
297
298 gcvFEATURE_BLOCK_SIZE_16x16,
299
300 gcvFEATURE_NO_USER_CSC,
301 gcvFEATURE_ANDROID_ONLY,
302 gcvFEATURE_HAS_PRODUCTID,
303
304 gcvFEATURE_V2_MSAA_COMP_FIX,
305
306 gcvFEATURE_S8_ONLY_RENDERING,
307
308 gcvFEATURE_SEPARATE_SRC_DST,
309
310 gcvFEATURE_FE_START_VERTEX_SUPPORT,
311 gcvFEATURE_FE_RESET_VERTEX_ID,
312 gcvFEATURE_RS_DEPTHSTENCIL_NATIVE_SUPPORT,
313
314 gcvFEATURE_HALTI4,
315 gcvFEATURE_MSAA_FRAGMENT_OPERATION,
316 gcvFEATURE_ZERO_ATTRIB_SUPPORT,
317 gcvFEATURE_TEX_CACHE_FLUSH_FIX,
318
319 /* Insert features above this comment only. */
320 gcvFEATURE_COUNT /* Not a feature. */
321}
322gceFEATURE;
323
324/* Chip SWWA. */
325typedef enum _gceSWWA
326{
327 gcvSWWA_601 = 0,
328 gcvSWWA_706,
329 gcvSWWA_1163,
330 gcvSWWA_1165,
331 /* Insert SWWA above this comment only. */
332 gcvSWWA_COUNT /* Not a SWWA. */
333}
334gceSWWA;
335
336
337/* Option Set*/
338typedef enum _gceOPITON
339{
340 /* HW setting we take PREFER */
341 gcvOPTION_PREFER_MULTIPIPE_RS = 0,
342 gcvOPTION_PREFER_ZCONVERT_BYPASS =1,
343
344
345 gcvOPTION_HW_NULL = 50,
346 gcvOPTION_PRINT_OPTION = 51,
347
348 gcvOPTION_FBO_PREFER_MEM = 80,
349
350 /* Insert option above this comment only */
351 gcvOPTION_COUNT /* Not a OPTION*/
352}
353gceOPTION;
354
355typedef enum _gceFRAMEINFO
356{
357 gcvFRAMEINFO_FRAME_NUM = 0,
358 gcvFRAMEINFO_DRAW_NUM = 1,
359 gcvFRAMEINFO_DRAW_DUAL16_NUM = 2,
360 gcvFRAMEINFO_DRAW_FL32_NUM = 3,
361
362
363 gcvFRAMEINFO_COUNT,
364}
365gceFRAMEINFO;
366
367typedef enum _gceFRAMEINFO_OP
368{
369 gcvFRAMEINFO_OP_INC = 0,
370 gcvFRAMEINFO_OP_DEC = 1,
371 gcvFRAMEINFO_OP_ZERO = 2,
372 gcvFRAMEINFO_OP_GET = 3,
373
374 gcvFRAMEINFO_OP_COUNT,
375}
376gceFRAMEINFO_OP;
377
378
379/* Chip Power Status. */
380typedef enum _gceCHIPPOWERSTATE
381{
382 gcvPOWER_ON = 0,
383 gcvPOWER_OFF,
384 gcvPOWER_IDLE,
385 gcvPOWER_SUSPEND,
386 gcvPOWER_SUSPEND_ATPOWERON,
387 gcvPOWER_OFF_ATPOWERON,
388 gcvPOWER_IDLE_BROADCAST,
389 gcvPOWER_SUSPEND_BROADCAST,
390 gcvPOWER_OFF_BROADCAST,
391 gcvPOWER_OFF_RECOVERY,
392 gcvPOWER_OFF_TIMEOUT,
393 gcvPOWER_ON_AUTO
394}
395gceCHIPPOWERSTATE;
396
397/* CPU cache operations */
398typedef enum _gceCACHEOPERATION
399{
400 gcvCACHE_CLEAN = 0x01,
401 gcvCACHE_INVALIDATE = 0x02,
402 gcvCACHE_FLUSH = gcvCACHE_CLEAN | gcvCACHE_INVALIDATE,
403 gcvCACHE_MEMORY_BARRIER = 0x04
404}
405gceCACHEOPERATION;
406
407/* Surface types. */
408typedef enum _gceSURF_TYPE
409{
410 gcvSURF_TYPE_UNKNOWN = 0,
411 gcvSURF_INDEX,
412 gcvSURF_VERTEX,
413 gcvSURF_TEXTURE,
414 gcvSURF_RENDER_TARGET,
415 gcvSURF_DEPTH,
416 gcvSURF_BITMAP,
417 gcvSURF_TILE_STATUS,
418 gcvSURF_IMAGE,
419 gcvSURF_MASK,
420 gcvSURF_SCISSOR,
421 gcvSURF_HIERARCHICAL_DEPTH,
422 gcvSURF_NUM_TYPES, /* Make sure this is the last one! */
423
424 /* Combinations. */
425 gcvSURF_NO_TILE_STATUS = 0x100,
426 gcvSURF_NO_VIDMEM = 0x200, /* Used to allocate surfaces with no underlying vidmem node.
427 In Android, vidmem node is allocated by another process. */
428 gcvSURF_CACHEABLE = 0x400, /* Used to allocate a cacheable surface */
429
430 gcvSURF_FLIP = 0x800, /* The Resolve Target the will been flip resolve from RT */
431
432 gcvSURF_TILE_STATUS_DIRTY = 0x1000, /* Init tile status to all dirty */
433
434 gcvSURF_LINEAR = 0x2000,
435
436 gcvSURF_CREATE_AS_TEXTURE = 0x4000, /* create it as a texture */
437
438 gcvSURF_PROTECTED_CONTENT = 0x8000, /* create it as content protected */
439
440 /* Create it as no compression, valid on when it has tile status. */
441 gcvSURF_NO_COMPRESSION = 0x40000,
442
443 gcvSURF_CONTIGUOUS = 0x20000, /*create it as contiguous */
444
445 gcvSURF_TEXTURE_LINEAR = gcvSURF_TEXTURE
446 | gcvSURF_LINEAR,
447
448 gcvSURF_RENDER_TARGET_LINEAR = gcvSURF_RENDER_TARGET
449 | gcvSURF_LINEAR,
450
451 gcvSURF_RENDER_TARGET_NO_TILE_STATUS = gcvSURF_RENDER_TARGET
452 | gcvSURF_NO_TILE_STATUS,
453
454 gcvSURF_RENDER_TARGET_TS_DIRTY = gcvSURF_RENDER_TARGET
455 | gcvSURF_TILE_STATUS_DIRTY,
456
457 gcvSURF_DEPTH_NO_TILE_STATUS = gcvSURF_DEPTH
458 | gcvSURF_NO_TILE_STATUS,
459
460 gcvSURF_DEPTH_TS_DIRTY = gcvSURF_DEPTH
461 | gcvSURF_TILE_STATUS_DIRTY,
462
463 /* Supported surface types with no vidmem node. */
464 gcvSURF_BITMAP_NO_VIDMEM = gcvSURF_BITMAP
465 | gcvSURF_NO_VIDMEM,
466
467 gcvSURF_TEXTURE_NO_VIDMEM = gcvSURF_TEXTURE
468 | gcvSURF_NO_VIDMEM,
469
470 /* Cacheable surface types with no vidmem node. */
471 gcvSURF_CACHEABLE_BITMAP_NO_VIDMEM = gcvSURF_BITMAP_NO_VIDMEM
472 | gcvSURF_CACHEABLE,
473
474 gcvSURF_CACHEABLE_BITMAP = gcvSURF_BITMAP
475 | gcvSURF_CACHEABLE,
476
477 gcvSURF_FLIP_BITMAP = gcvSURF_BITMAP
478 | gcvSURF_FLIP,
479}
480gceSURF_TYPE;
481
482typedef enum _gceSURF_USAGE
483{
484 gcvSURF_USAGE_UNKNOWN,
485 gcvSURF_USAGE_RESOLVE_AFTER_CPU,
486 gcvSURF_USAGE_RESOLVE_AFTER_3D
487}
488gceSURF_USAGE;
489
490typedef enum _gceSURF_COLOR_SPACE
491{
492 gcvSURF_COLOR_SPACE_UNKNOWN,
493 gcvSURF_COLOR_SPACE_LINEAR,
494 gcvSURF_COLOR_SPACE_NONLINEAR,
495}
496gceSURF_COLOR_SPACE;
497
498typedef enum _gceSURF_COLOR_TYPE
499{
500 gcvSURF_COLOR_UNKNOWN = 0,
501 gcvSURF_COLOR_LINEAR = 0x01,
502 gcvSURF_COLOR_ALPHA_PRE = 0x02,
503}
504gceSURF_COLOR_TYPE;
505
506/* Rotation. */
507typedef enum _gceSURF_ROTATION
508{
509 gcvSURF_0_DEGREE = 0,
510 gcvSURF_90_DEGREE,
511 gcvSURF_180_DEGREE,
512 gcvSURF_270_DEGREE,
513 gcvSURF_FLIP_X,
514 gcvSURF_FLIP_Y,
515
516 gcvSURF_POST_FLIP_X = 0x40000000,
517 gcvSURF_POST_FLIP_Y = 0x80000000,
518}
519gceSURF_ROTATION;
520
521/* Surface flag */
522typedef enum _gceSURF_FLAG
523{
524 /* None flag */
525 gcvSURF_FLAG_NONE = 0x0,
526 /* content is preserved after swap */
527 gcvSURF_FLAG_CONTENT_PRESERVED = 0x1,
528 /* content is updated after swap*/
529 gcvSURF_FLAG_CONTENT_UPDATED = 0x2,
530 /* content is y inverted */
531 gcvSURF_FLAG_CONTENT_YINVERTED = 0x4,
532 /* content is protected */
533 gcvSURF_FLAG_CONTENT_PROTECTED = 0x8,
534 /* surface is contiguous. */
535 gcvSURF_FLAG_CONTIGUOUS = (1 << 4),
536 /* surface has multiple nodes */
537 gcvSURF_FLAG_MULTI_NODE = (1 << 5),
538}
539gceSURF_FLAG;
540
541typedef enum _gceMIPMAP_IMAGE_FORMAT
542{
543 gcvUNKNOWN_MIPMAP_IMAGE_FORMAT = -2
544}
545gceMIPMAP_IMAGE_FORMAT;
546
547/* Surface formats. */
548typedef enum _gceSURF_FORMAT
549{
550 /* Unknown format. */
551 gcvSURF_UNKNOWN = 0,
552
553 /* Palettized formats. */
554 gcvSURF_INDEX1 = 100,
555 gcvSURF_INDEX4,
556 gcvSURF_INDEX8,
557
558 /* RGB formats. */
559 gcvSURF_A2R2G2B2 = 200,
560 gcvSURF_R3G3B2,
561 gcvSURF_A8R3G3B2,
562 gcvSURF_X4R4G4B4,
563 gcvSURF_A4R4G4B4,
564 gcvSURF_R4G4B4A4,
565 gcvSURF_X1R5G5B5,
566 gcvSURF_A1R5G5B5,
567 gcvSURF_R5G5B5A1,
568 gcvSURF_R5G6B5,
569 gcvSURF_R8G8B8,
570 gcvSURF_X8R8G8B8,
571 gcvSURF_A8R8G8B8,
572 gcvSURF_R8G8B8A8,
573 gcvSURF_G8R8G8B8,
574 gcvSURF_R8G8B8G8,
575 gcvSURF_X2R10G10B10,
576 gcvSURF_A2R10G10B10,
577 gcvSURF_X12R12G12B12,
578 gcvSURF_A12R12G12B12,
579 gcvSURF_X16R16G16B16,
580 gcvSURF_A16R16G16B16,
581 gcvSURF_A32R32G32B32,
582 gcvSURF_R8G8B8X8,
583 gcvSURF_R5G5B5X1,
584 gcvSURF_R4G4B4X4,
585 gcvSURF_X16R16G16B16_2_A8R8G8B8,
586 gcvSURF_A16R16G16B16_2_A8R8G8B8,
587 gcvSURF_A32R32G32B32_2_G32R32F,
588 gcvSURF_A32R32G32B32_4_A8R8G8B8,
589
590 /* BGR formats. */
591 gcvSURF_A4B4G4R4 = 300,
592 gcvSURF_A1B5G5R5,
593 gcvSURF_B5G6R5,
594 gcvSURF_B8G8R8,
595 gcvSURF_B16G16R16,
596 gcvSURF_X8B8G8R8,
597 gcvSURF_A8B8G8R8,
598 gcvSURF_A2B10G10R10,
599 gcvSURF_X16B16G16R16,
600 gcvSURF_A16B16G16R16,
601 gcvSURF_B32G32R32,
602 gcvSURF_X32B32G32R32,
603 gcvSURF_A32B32G32R32,
604 gcvSURF_B4G4R4A4,
605 gcvSURF_B5G5R5A1,
606 gcvSURF_B8G8R8X8,
607 gcvSURF_B8G8R8A8,
608 gcvSURF_X4B4G4R4,
609 gcvSURF_X1B5G5R5,
610 gcvSURF_B4G4R4X4,
611 gcvSURF_B5G5R5X1,
612 gcvSURF_X2B10G10R10,
613 gcvSURF_B8G8R8_SNORM,
614 gcvSURF_X8B8G8R8_SNORM,
615 gcvSURF_A8B8G8R8_SNORM,
616 gcvSURF_A8B12G12R12_2_A8R8G8B8,
617
618 /* Compressed formats. */
619 gcvSURF_DXT1 = 400,
620 gcvSURF_DXT2,
621 gcvSURF_DXT3,
622 gcvSURF_DXT4,
623 gcvSURF_DXT5,
624 gcvSURF_CXV8U8,
625 gcvSURF_ETC1,
626 gcvSURF_R11_EAC,
627 gcvSURF_SIGNED_R11_EAC,
628 gcvSURF_RG11_EAC,
629 gcvSURF_SIGNED_RG11_EAC,
630 gcvSURF_RGB8_ETC2,
631 gcvSURF_SRGB8_ETC2,
632 gcvSURF_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
633 gcvSURF_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
634 gcvSURF_RGBA8_ETC2_EAC,
635 gcvSURF_SRGB8_ALPHA8_ETC2_EAC,
636
637 /* YUV formats. */
638 gcvSURF_YUY2 = 500,
639 gcvSURF_UYVY,
640 gcvSURF_YV12,
641 gcvSURF_I420,
642 gcvSURF_NV12,
643 gcvSURF_NV21,
644 gcvSURF_NV16,
645 gcvSURF_NV61,
646 gcvSURF_YVYU,
647 gcvSURF_VYUY,
648
649 /* Depth formats. */
650 gcvSURF_D16 = 600,
651 gcvSURF_D24S8,
652 gcvSURF_D32,
653 gcvSURF_D24X8,
654 gcvSURF_D32F,
655 gcvSURF_S8D32F,
656 gcvSURF_S8D32F_1_G32R32F,
657 gcvSURF_S8D32F_2_A8R8G8B8,
658 gcvSURF_D24S8_1_A8R8G8B8,
659 gcvSURF_S8,
660
661 /* Alpha formats. */
662 gcvSURF_A4 = 700,
663 gcvSURF_A8,
664 gcvSURF_A12,
665 gcvSURF_A16,
666 gcvSURF_A32,
667 gcvSURF_A1,
668
669 /* Luminance formats. */
670 gcvSURF_L4 = 800,
671 gcvSURF_L8,
672 gcvSURF_L12,
673 gcvSURF_L16,
674 gcvSURF_L32,
675 gcvSURF_L1,
676
677 /* Alpha/Luminance formats. */
678 gcvSURF_A4L4 = 900,
679 gcvSURF_A2L6,
680 gcvSURF_A8L8,
681 gcvSURF_A4L12,
682 gcvSURF_A12L12,
683 gcvSURF_A16L16,
684
685 /* Bump formats. */
686 gcvSURF_L6V5U5 = 1000,
687 gcvSURF_V8U8,
688 gcvSURF_X8L8V8U8,
689 gcvSURF_Q8W8V8U8,
690 gcvSURF_A2W10V10U10,
691 gcvSURF_V16U16,
692 gcvSURF_Q16W16V16U16,
693
694 /* R/RG/RA formats. */
695 gcvSURF_R8 = 1100,
696 gcvSURF_X8R8,
697 gcvSURF_G8R8,
698 gcvSURF_X8G8R8,
699 gcvSURF_A8R8,
700 gcvSURF_R16,
701 gcvSURF_X16R16,
702 gcvSURF_G16R16,
703 gcvSURF_X16G16R16,
704 gcvSURF_A16R16,
705 gcvSURF_R32,
706 gcvSURF_X32R32,
707 gcvSURF_G32R32,
708 gcvSURF_X32G32R32,
709 gcvSURF_A32R32,
710 gcvSURF_RG16,
711 gcvSURF_R8_SNORM,
712 gcvSURF_G8R8_SNORM,
713
714 gcvSURF_R8_1_X8R8G8B8,
715 gcvSURF_G8R8_1_X8R8G8B8,
716
717 /* Floating point formats. */
718 gcvSURF_R16F = 1200,
719 gcvSURF_X16R16F,
720 gcvSURF_G16R16F,
721 gcvSURF_X16G16R16F,
722 gcvSURF_B16G16R16F,
723 gcvSURF_X16B16G16R16F,
724 gcvSURF_A16B16G16R16F,
725 gcvSURF_R32F,
726 gcvSURF_X32R32F,
727 gcvSURF_G32R32F,
728 gcvSURF_X32G32R32F,
729 gcvSURF_B32G32R32F,
730 gcvSURF_X32B32G32R32F,
731 gcvSURF_A32B32G32R32F,
732 gcvSURF_A16F,
733 gcvSURF_L16F,
734 gcvSURF_A16L16F,
735 gcvSURF_A16R16F,
736 gcvSURF_A32F,
737 gcvSURF_L32F,
738 gcvSURF_A32L32F,
739 gcvSURF_A32R32F,
740 gcvSURF_E5B9G9R9,
741 gcvSURF_B10G11R11F,
742
743 gcvSURF_X16B16G16R16F_2_A8R8G8B8,
744 gcvSURF_A16B16G16R16F_2_A8R8G8B8,
745 gcvSURF_G32R32F_2_A8R8G8B8,
746 gcvSURF_X32B32G32R32F_2_G32R32F,
747 gcvSURF_A32B32G32R32F_2_G32R32F,
748 gcvSURF_X32B32G32R32F_4_A8R8G8B8,
749 gcvSURF_A32B32G32R32F_4_A8R8G8B8,
750
751 gcvSURF_R16F_1_A4R4G4B4,
752 gcvSURF_G16R16F_1_A8R8G8B8,
753 gcvSURF_B16G16R16F_2_A8R8G8B8,
754
755 gcvSURF_R32F_1_A8R8G8B8,
756 gcvSURF_B32G32R32F_3_A8R8G8B8,
757
758 gcvSURF_B10G11R11F_1_A8R8G8B8,
759
760
761 /* sRGB format. */
762 gcvSURF_SBGR8 = 1400,
763 gcvSURF_A8_SBGR8,
764 gcvSURF_X8_SBGR8,
765
766 /* Integer formats. */
767 gcvSURF_R8I = 1500,
768 gcvSURF_R8UI,
769 gcvSURF_R16I,
770 gcvSURF_R16UI,
771 gcvSURF_R32I,
772 gcvSURF_R32UI,
773 gcvSURF_X8R8I,
774 gcvSURF_G8R8I,
775 gcvSURF_X8R8UI,
776 gcvSURF_G8R8UI,
777 gcvSURF_X16R16I,
778 gcvSURF_G16R16I,
779 gcvSURF_X16R16UI,
780 gcvSURF_G16R16UI,
781 gcvSURF_X32R32I,
782 gcvSURF_G32R32I,
783 gcvSURF_X32R32UI,
784 gcvSURF_G32R32UI,
785 gcvSURF_X8G8R8I,
786 gcvSURF_B8G8R8I,
787 gcvSURF_X8G8R8UI,
788 gcvSURF_B8G8R8UI,
789 gcvSURF_X16G16R16I,
790 gcvSURF_B16G16R16I,
791 gcvSURF_X16G16R16UI,
792 gcvSURF_B16G16R16UI,
793 gcvSURF_X32G32R32I,
794 gcvSURF_B32G32R32I,
795 gcvSURF_X32G32R32UI,
796 gcvSURF_B32G32R32UI,
797 gcvSURF_X8B8G8R8I,
798 gcvSURF_A8B8G8R8I,
799 gcvSURF_X8B8G8R8UI,
800 gcvSURF_A8B8G8R8UI,
801 gcvSURF_X16B16G16R16I,
802 gcvSURF_A16B16G16R16I,
803 gcvSURF_X16B16G16R16UI,
804 gcvSURF_A16B16G16R16UI,
805 gcvSURF_X32B32G32R32I,
806 gcvSURF_A32B32G32R32I,
807 gcvSURF_X32B32G32R32UI,
808 gcvSURF_A32B32G32R32UI,
809 gcvSURF_A2B10G10R10UI,
810 gcvSURF_G32R32I_2_A8R8G8B8,
811 gcvSURF_G32R32UI_2_A8R8G8B8,
812 gcvSURF_X16B16G16R16I_2_A8R8G8B8,
813 gcvSURF_A16B16G16R16I_2_A8R8G8B8,
814 gcvSURF_X16B16G16R16UI_2_A8R8G8B8,
815 gcvSURF_A16B16G16R16UI_2_A8R8G8B8,
816 gcvSURF_X32B32G32R32I_2_G32R32I,
817 gcvSURF_A32B32G32R32I_2_G32R32I,
818 gcvSURF_X32B32G32R32I_3_A8R8G8B8,
819 gcvSURF_A32B32G32R32I_4_A8R8G8B8,
820 gcvSURF_X32B32G32R32UI_2_G32R32UI,
821 gcvSURF_A32B32G32R32UI_2_G32R32UI,
822 gcvSURF_X32B32G32R32UI_3_A8R8G8B8,
823 gcvSURF_A32B32G32R32UI_4_A8R8G8B8,
824 gcvSURF_A2B10G10R10UI_1_A8R8G8B8,
825 gcvSURF_A8B8G8R8I_1_A8R8G8B8,
826 gcvSURF_A8B8G8R8UI_1_A8R8G8B8,
827 gcvSURF_R8I_1_A4R4G4B4,
828 gcvSURF_R8UI_1_A4R4G4B4,
829 gcvSURF_R16I_1_A4R4G4B4,
830 gcvSURF_R16UI_1_A4R4G4B4,
831 gcvSURF_R32I_1_A8R8G8B8,
832 gcvSURF_R32UI_1_A8R8G8B8,
833 gcvSURF_X8R8I_1_A4R4G4B4,
834 gcvSURF_X8R8UI_1_A4R4G4B4,
835 gcvSURF_G8R8I_1_A4R4G4B4,
836 gcvSURF_G8R8UI_1_A4R4G4B4,
837 gcvSURF_X16R16I_1_A4R4G4B4,
838 gcvSURF_X16R16UI_1_A4R4G4B4,
839 gcvSURF_G16R16I_1_A8R8G8B8,
840 gcvSURF_G16R16UI_1_A8R8G8B8,
841 gcvSURF_X32R32I_1_A8R8G8B8,
842 gcvSURF_X32R32UI_1_A8R8G8B8,
843 gcvSURF_X8G8R8I_1_A4R4G4B4,
844 gcvSURF_X8G8R8UI_1_A4R4G4B4,
845 gcvSURF_B8G8R8I_1_A8R8G8B8,
846 gcvSURF_B8G8R8UI_1_A8R8G8B8,
847 gcvSURF_B16G16R16I_2_A8R8G8B8,
848 gcvSURF_B16G16R16UI_2_A8R8G8B8,
849 gcvSURF_B32G32R32I_3_A8R8G8B8,
850 gcvSURF_B32G32R32UI_3_A8R8G8B8,
851
852 /* ASTC formats. */
853 gcvSURF_ASTC4x4 = 1600,
854 gcvSURF_ASTC5x4,
855 gcvSURF_ASTC5x5,
856 gcvSURF_ASTC6x5,
857 gcvSURF_ASTC6x6,
858 gcvSURF_ASTC8x5,
859 gcvSURF_ASTC8x6,
860 gcvSURF_ASTC8x8,
861 gcvSURF_ASTC10x5,
862 gcvSURF_ASTC10x6,
863 gcvSURF_ASTC10x8,
864 gcvSURF_ASTC10x10,
865 gcvSURF_ASTC12x10,
866 gcvSURF_ASTC12x12,
867 gcvSURF_ASTC4x4_SRGB,
868 gcvSURF_ASTC5x4_SRGB,
869 gcvSURF_ASTC5x5_SRGB,
870 gcvSURF_ASTC6x5_SRGB,
871 gcvSURF_ASTC6x6_SRGB,
872 gcvSURF_ASTC8x5_SRGB,
873 gcvSURF_ASTC8x6_SRGB,
874 gcvSURF_ASTC8x8_SRGB,
875 gcvSURF_ASTC10x5_SRGB,
876 gcvSURF_ASTC10x6_SRGB,
877 gcvSURF_ASTC10x8_SRGB,
878 gcvSURF_ASTC10x10_SRGB,
879 gcvSURF_ASTC12x10_SRGB,
880 gcvSURF_ASTC12x12_SRGB,
881
882 gcvSURF_FORMAT_COUNT
883}
884gceSURF_FORMAT;
885
886typedef enum _gceSURF_YUV_COLOR_SPACE
887{
888 gcvSURF_ITU_REC601,
889 gcvSURF_ITU_REC709,
890 gcvSURF_ITU_REC2020,
891}
892gceSURF_YUV_COLOR_SPACE;
893
894typedef enum _gceSURF_YUV_CHROMA_SITING
895{
896 gcvSURF_YUV_CHROMA_SITING_0,
897 gcvSURF_YUV_CHROMA_SITING_0_5,
898}
899gceSURF_YUV_CHROMA_SITING;
900
901typedef enum _gceSURF_YUV_SAMPLE_RANGE
902{
903 gcvSURF_YUV_FULL_RANGE,
904 gcvSURF_YUV_NARROW_RANGE,
905}
906gceSURF_YUV_SAMPLE_RANGE;
907
908/* Format modifiers. */
909typedef enum _gceSURF_FORMAT_MODE
910{
911 gcvSURF_FORMAT_OCL = 0x80000000
912}
913gceSURF_FORMAT_MODE;
914
915/* Pixel swizzle modes. */
916typedef enum _gceSURF_SWIZZLE
917{
918 gcvSURF_NOSWIZZLE = 0,
919 gcvSURF_ARGB,
920 gcvSURF_ABGR,
921 gcvSURF_RGBA,
922 gcvSURF_BGRA
923}
924gceSURF_SWIZZLE;
925
926/* Transparency modes. */
927typedef enum _gceSURF_TRANSPARENCY
928{
929 /* Valid only for PE 1.0 */
930 gcvSURF_OPAQUE = 0,
931 gcvSURF_SOURCE_MATCH,
932 gcvSURF_SOURCE_MASK,
933 gcvSURF_PATTERN_MASK,
934}
935gceSURF_TRANSPARENCY;
936
937/* Surface Alignment. */
938typedef enum _gceSURF_ALIGNMENT
939{
940 gcvSURF_FOUR = 0,
941 gcvSURF_SIXTEEN,
942 gcvSURF_SUPER_TILED,
943 gcvSURF_SPLIT_TILED,
944 gcvSURF_SPLIT_SUPER_TILED
945}
946gceSURF_ALIGNMENT;
947
948/* Surface Addressing. */
949typedef enum _gceSURF_ADDRESSING
950{
951 gcvSURF_NO_STRIDE_TILED = 0,
952 gcvSURF_NO_STRIDE_LINEAR,
953 gcvSURF_STRIDE_TILED,
954 gcvSURF_STRIDE_LINEAR
955}
956gceSURF_ADDRESSING;
957
958/* Transparency modes. */
959typedef enum _gce2D_TRANSPARENCY
960{
961 /* Valid only for PE 2.0 */
962 gcv2D_OPAQUE = 0,
963 gcv2D_KEYED,
964 gcv2D_MASKED
965}
966gce2D_TRANSPARENCY;
967
968/* Mono packing modes. */
969typedef enum _gceSURF_MONOPACK
970{
971 gcvSURF_PACKED8 = 0,
972 gcvSURF_PACKED16,
973 gcvSURF_PACKED32,
974 gcvSURF_UNPACKED,
975}
976gceSURF_MONOPACK;
977
978/* Blending modes. */
979typedef enum _gceSURF_BLEND_MODE
980{
981 /* Porter-Duff blending modes. */
982 /* Fsrc Fdst */
983 gcvBLEND_CLEAR = 0, /* 0 0 */
984 gcvBLEND_SRC, /* 1 0 */
985 gcvBLEND_DST, /* 0 1 */
986 gcvBLEND_SRC_OVER_DST, /* 1 1 - Asrc */
987 gcvBLEND_DST_OVER_SRC, /* 1 - Adst 1 */
988 gcvBLEND_SRC_IN_DST, /* Adst 0 */
989 gcvBLEND_DST_IN_SRC, /* 0 Asrc */
990 gcvBLEND_SRC_OUT_DST, /* 1 - Adst 0 */
991 gcvBLEND_DST_OUT_SRC, /* 0 1 - Asrc */
992 gcvBLEND_SRC_ATOP_DST, /* Adst 1 - Asrc */
993 gcvBLEND_DST_ATOP_SRC, /* 1 - Adst Asrc */
994 gcvBLEND_SRC_XOR_DST, /* 1 - Adst 1 - Asrc */
995
996 /* Special blending modes. */
997 gcvBLEND_SET, /* DST = 1 */
998 gcvBLEND_SUB /* DST = DST * (1 - SRC) */
999}
1000gceSURF_BLEND_MODE;
1001
1002/* Per-pixel alpha modes. */
1003typedef enum _gceSURF_PIXEL_ALPHA_MODE
1004{
1005 gcvSURF_PIXEL_ALPHA_STRAIGHT = 0,
1006 gcvSURF_PIXEL_ALPHA_INVERSED
1007}
1008gceSURF_PIXEL_ALPHA_MODE;
1009
1010/* Global alpha modes. */
1011typedef enum _gceSURF_GLOBAL_ALPHA_MODE
1012{
1013 gcvSURF_GLOBAL_ALPHA_OFF = 0,
1014 gcvSURF_GLOBAL_ALPHA_ON,
1015 gcvSURF_GLOBAL_ALPHA_SCALE
1016}
1017gceSURF_GLOBAL_ALPHA_MODE;
1018
1019/* Color component modes for alpha blending. */
1020typedef enum _gceSURF_PIXEL_COLOR_MODE
1021{
1022 gcvSURF_COLOR_STRAIGHT = 0,
1023 gcvSURF_COLOR_MULTIPLY
1024}
1025gceSURF_PIXEL_COLOR_MODE;
1026
1027/* Color component modes for alpha blending. */
1028typedef enum _gce2D_PIXEL_COLOR_MULTIPLY_MODE
1029{
1030 gcv2D_COLOR_MULTIPLY_DISABLE = 0,
1031 gcv2D_COLOR_MULTIPLY_ENABLE
1032}
1033gce2D_PIXEL_COLOR_MULTIPLY_MODE;
1034
1035/* Color component modes for alpha blending. */
1036typedef enum _gce2D_GLOBAL_COLOR_MULTIPLY_MODE
1037{
1038 gcv2D_GLOBAL_COLOR_MULTIPLY_DISABLE = 0,
1039 gcv2D_GLOBAL_COLOR_MULTIPLY_ALPHA,
1040 gcv2D_GLOBAL_COLOR_MULTIPLY_COLOR
1041}
1042gce2D_GLOBAL_COLOR_MULTIPLY_MODE;
1043
1044/* Alpha blending factor modes. */
1045typedef enum _gceSURF_BLEND_FACTOR_MODE
1046{
1047 gcvSURF_BLEND_ZERO = 0,
1048 gcvSURF_BLEND_ONE,
1049 gcvSURF_BLEND_STRAIGHT,
1050 gcvSURF_BLEND_INVERSED,
1051 gcvSURF_BLEND_COLOR,
1052 gcvSURF_BLEND_COLOR_INVERSED,
1053 gcvSURF_BLEND_SRC_ALPHA_SATURATED,
1054 gcvSURF_BLEND_STRAIGHT_NO_CROSS,
1055 gcvSURF_BLEND_INVERSED_NO_CROSS,
1056 gcvSURF_BLEND_COLOR_NO_CROSS,
1057 gcvSURF_BLEND_COLOR_INVERSED_NO_CROSS,
1058 gcvSURF_BLEND_SRC_ALPHA_SATURATED_CROSS
1059}
1060gceSURF_BLEND_FACTOR_MODE;
1061
1062/* Alpha blending porter duff rules. */
1063typedef enum _gce2D_PORTER_DUFF_RULE
1064{
1065 gcvPD_CLEAR = 0,
1066 gcvPD_SRC,
1067 gcvPD_SRC_OVER,
1068 gcvPD_DST_OVER,
1069 gcvPD_SRC_IN,
1070 gcvPD_DST_IN,
1071 gcvPD_SRC_OUT,
1072 gcvPD_DST_OUT,
1073 gcvPD_SRC_ATOP,
1074 gcvPD_DST_ATOP,
1075 gcvPD_ADD,
1076 gcvPD_XOR,
1077 gcvPD_DST
1078}
1079gce2D_PORTER_DUFF_RULE;
1080
1081/* Alpha blending factor modes. */
1082typedef enum _gce2D_YUV_COLOR_MODE
1083{
1084 gcv2D_YUV_601= 0,
1085 gcv2D_YUV_709,
1086 gcv2D_YUV_USER_DEFINED,
1087 gcv2D_YUV_USER_DEFINED_CLAMP,
1088
1089 /* Default setting is for src. gcv2D_YUV_DST
1090 can be ORed to set dst.
1091 */
1092 gcv2D_YUV_DST = 0x80000000,
1093}
1094gce2D_YUV_COLOR_MODE;
1095
1096typedef enum _gce2D_COMMAND
1097{
1098 gcv2D_CLEAR = 0,
1099 gcv2D_LINE,
1100 gcv2D_BLT,
1101 gcv2D_STRETCH,
1102 gcv2D_HOR_FILTER,
1103 gcv2D_VER_FILTER,
1104 gcv2D_MULTI_SOURCE_BLT,
1105 gcv2D_FILTER_BLT,
1106}
1107gce2D_COMMAND;
1108
1109typedef enum _gce2D_TILE_STATUS_CONFIG
1110{
1111 gcv2D_TSC_DISABLE = 0,
1112 gcv2D_TSC_ENABLE = 0x00000001,
1113 gcv2D_TSC_COMPRESSED = 0x00000002,
1114 gcv2D_TSC_DOWN_SAMPLER = 0x00000004,
1115 gcv2D_TSC_2D_COMPRESSED = 0x00000008,
1116 gcv2D_TSC_TPC_COMPRESSED = 0x00000010,
1117
1118 gcv2D_TSC_DEC_COMPRESSED = 0x00000020,
1119 gcv2D_TSC_DEC_TPC = 0x00000040,
1120 gcv2D_TSC_DEC_TPC_COMPRESSED = 0x00000080,
1121
1122 gcv2D_TSC_DEC_TPC_TILED = gcv2D_TSC_DEC_COMPRESSED | gcv2D_TSC_DEC_TPC,
1123 gcv2D_TSC_DEC_TPC_TILED_COMPRESSED = gcv2D_TSC_DEC_TPC_TILED | gcv2D_TSC_DEC_TPC_COMPRESSED,
1124}
1125gce2D_TILE_STATUS_CONFIG;
1126
1127typedef enum _gce2D_QUERY
1128{
1129 gcv2D_QUERY_RGB_ADDRESS_MIN_ALIGN = 0,
1130 gcv2D_QUERY_RGB_STRIDE_MIN_ALIGN,
1131 gcv2D_QUERY_YUV_ADDRESS_MIN_ALIGN,
1132 gcv2D_QUERY_YUV_STRIDE_MIN_ALIGN,
1133}
1134gce2D_QUERY;
1135
1136typedef enum _gce2D_SUPER_TILE_VERSION
1137{
1138 gcv2D_SUPER_TILE_VERSION_V1 = 1,
1139 gcv2D_SUPER_TILE_VERSION_V2 = 2,
1140 gcv2D_SUPER_TILE_VERSION_V3 = 3,
1141}
1142gce2D_SUPER_TILE_VERSION;
1143
1144typedef enum _gce2D_STATE
1145{
1146 gcv2D_STATE_SPECIAL_FILTER_MIRROR_MODE = 1,
1147 gcv2D_STATE_SUPER_TILE_VERSION,
1148 gcv2D_STATE_EN_GAMMA,
1149 gcv2D_STATE_DE_GAMMA,
1150 gcv2D_STATE_MULTI_SRC_BLIT_UNIFIED_DST_RECT,
1151 gcv2D_STATE_PROFILE_ENABLE,
1152 gcv2D_STATE_XRGB_ENABLE,
1153
1154 gcv2D_STATE_ARRAY_EN_GAMMA = 0x10001,
1155 gcv2D_STATE_ARRAY_DE_GAMMA,
1156 gcv2D_STATE_ARRAY_CSC_YUV_TO_RGB,
1157 gcv2D_STATE_ARRAY_CSC_RGB_TO_YUV,
1158
1159 gcv2D_STATE_DEC_TPC_NV12_10BIT = 0x20001,
1160 gcv2D_STATE_ARRAY_YUV_SRC_TILE_STATUS_ADDR,
1161 gcv2D_STATE_ARRAY_YUV_DST_TILE_STATUS_ADDR,
1162}
1163gce2D_STATE;
1164
1165typedef enum _gce2D_STATE_PROFILE
1166{
1167 gcv2D_STATE_PROFILE_NONE = 0x0,
1168 gcv2D_STATE_PROFILE_COMMAND = 0x1,
1169 gcv2D_STATE_PROFILE_SURFACE = 0x2,
1170 gcv2D_STATE_PROFILE_ALL = 0xFFFF,
1171}
1172gce2D_STATE_PROFILE;
1173
1174/* Texture object types */
1175typedef enum _gceTEXTURE_TYPE
1176{
1177 gcvTEXTURE_UNKNOWN = 0,
1178 gcvTEXTURE_1D,
1179 gcvTEXTURE_2D,
1180 gcvTEXTURE_3D,
1181 gcvTEXTURE_CUBEMAP,
1182 gcvTEXTURE_1D_ARRAY,
1183 gcvTEXTURE_2D_ARRAY,
1184 gcvTEXTURE_EXTERNAL
1185}
1186gceTEXTURE_TYPE;
1187
1188
1189/* Filter types. */
1190typedef enum _gceFILTER_TYPE
1191{
1192 gcvFILTER_SYNC = 0,
1193 gcvFILTER_BLUR,
1194 gcvFILTER_USER
1195}
1196gceFILTER_TYPE;
1197
1198/* Filter pass types. */
1199typedef enum _gceFILTER_PASS_TYPE
1200{
1201 gcvFILTER_HOR_PASS = 0,
1202 gcvFILTER_VER_PASS
1203}
1204gceFILTER_PASS_TYPE;
1205
1206/* Endian hints. */
1207typedef enum _gceENDIAN_HINT
1208{
1209 gcvENDIAN_NO_SWAP = 0,
1210 gcvENDIAN_SWAP_WORD,
1211 gcvENDIAN_SWAP_DWORD
1212}
1213gceENDIAN_HINT;
1214
1215/* Tiling modes. */
1216typedef enum _gceTILING
1217{
1218 gcvINVALIDTILED = 0x0, /* Invalid tiling */
1219 /* Tiling basic modes enum'ed in power of 2. */
1220 gcvLINEAR = 0x1, /* No tiling. */
1221 gcvTILED = 0x2, /* 4x4 tiling. */
1222 gcvSUPERTILED = 0x4, /* 64x64 tiling. */
1223 gcvMINORTILED = 0x8, /* 2x2 tiling. */
1224
1225 /* Tiling special layouts. */
1226 gcvTILING_SPLIT_BUFFER = 0x100,
1227
1228 /* Tiling combination layouts. */
1229 gcvMULTI_TILED = gcvTILED
1230 | gcvTILING_SPLIT_BUFFER,
1231
1232 gcvMULTI_SUPERTILED = gcvSUPERTILED
1233 | gcvTILING_SPLIT_BUFFER,
1234}
1235gceTILING;
1236
1237/* 2D pattern type. */
1238typedef enum _gce2D_PATTERN
1239{
1240 gcv2D_PATTERN_SOLID = 0,
1241 gcv2D_PATTERN_MONO,
1242 gcv2D_PATTERN_COLOR,
1243 gcv2D_PATTERN_INVALID
1244}
1245gce2D_PATTERN;
1246
1247/* 2D source type. */
1248typedef enum _gce2D_SOURCE
1249{
1250 gcv2D_SOURCE_MASKED = 0,
1251 gcv2D_SOURCE_MONO,
1252 gcv2D_SOURCE_COLOR,
1253 gcv2D_SOURCE_INVALID
1254}
1255gce2D_SOURCE;
1256
1257/* Pipes. */
1258typedef enum _gcePIPE_SELECT
1259{
1260 gcvPIPE_INVALID = ~0,
1261 gcvPIPE_3D = 0,
1262 gcvPIPE_2D
1263}
1264gcePIPE_SELECT;
1265
1266/* Hardware type. */
1267typedef enum _gceHARDWARE_TYPE
1268{
1269 gcvHARDWARE_INVALID = 0x00,
1270 gcvHARDWARE_3D = 0x01,
1271 gcvHARDWARE_2D = 0x02,
1272 gcvHARDWARE_VG = 0x04,
1273#if gcdMULTI_GPU_AFFINITY
1274 gcvHARDWARE_OCL = 0x05,
1275#endif
1276 gcvHARDWARE_3D2D = gcvHARDWARE_3D | gcvHARDWARE_2D,
1277}
1278gceHARDWARE_TYPE;
1279
1280#define gcdCHIP_COUNT 3
1281
1282typedef enum _gceMMU_MODE
1283{
1284 gcvMMU_MODE_1K,
1285 gcvMMU_MODE_4K,
1286} gceMMU_MODE;
1287
1288/* User signal command codes. */
1289typedef enum _gceUSER_SIGNAL_COMMAND_CODES
1290{
1291 gcvUSER_SIGNAL_CREATE,
1292 gcvUSER_SIGNAL_DESTROY,
1293 gcvUSER_SIGNAL_SIGNAL,
1294 gcvUSER_SIGNAL_WAIT,
1295 gcvUSER_SIGNAL_MAP,
1296 gcvUSER_SIGNAL_UNMAP,
1297}
1298gceUSER_SIGNAL_COMMAND_CODES;
1299
1300/* Sync point command codes. */
1301typedef enum _gceSYNC_POINT_COMMAND_CODES
1302{
1303 gcvSYNC_POINT_CREATE,
1304 gcvSYNC_POINT_DESTROY,
1305 gcvSYNC_POINT_SIGNAL,
1306}
1307gceSYNC_POINT_COMMAND_CODES;
1308
1309/* Shared buffer command codes. */
1310typedef enum _gceSHBUF_COMMAND_CODES
1311{
1312 gcvSHBUF_CREATE,
1313 gcvSHBUF_DESTROY,
1314 gcvSHBUF_MAP,
1315 gcvSHBUF_WRITE,
1316 gcvSHBUF_READ,
1317}
1318gceSHBUF_COMMAND_CODES;
1319
1320/* Event locations. */
1321typedef enum _gceKERNEL_WHERE
1322{
1323 gcvKERNEL_COMMAND,
1324 gcvKERNEL_VERTEX,
1325 gcvKERNEL_TRIANGLE,
1326 gcvKERNEL_TEXTURE,
1327 gcvKERNEL_PIXEL,
1328}
1329gceKERNEL_WHERE;
1330
1331
1332/* gcdDUMP message type. */
1333typedef enum _gceDEBUG_MESSAGE_TYPE
1334{
1335 gcvMESSAGE_TEXT,
1336 gcvMESSAGE_DUMP
1337}
1338gceDEBUG_MESSAGE_TYPE;
1339
1340/* Shading format. */
1341typedef enum _gceSHADING
1342{
1343 gcvSHADING_SMOOTH,
1344 gcvSHADING_FLAT_D3D,
1345 gcvSHADING_FLAT_OPENGL,
1346}
1347gceSHADING;
1348
1349/* Culling modes. */
1350typedef enum _gceCULL
1351{
1352 gcvCULL_NONE,
1353 gcvCULL_CCW,
1354 gcvCULL_CW,
1355}
1356gceCULL;
1357
1358/* Fill modes. */
1359typedef enum _gceFILL
1360{
1361 gcvFILL_POINT,
1362 gcvFILL_WIRE_FRAME,
1363 gcvFILL_SOLID,
1364}
1365gceFILL;
1366
1367/* Compare modes. */
1368typedef enum _gceCOMPARE
1369{
1370 gcvCOMPARE_INVALID = 0,
1371 gcvCOMPARE_NEVER,
1372 gcvCOMPARE_NOT_EQUAL,
1373 gcvCOMPARE_LESS,
1374 gcvCOMPARE_LESS_OR_EQUAL,
1375 gcvCOMPARE_EQUAL,
1376 gcvCOMPARE_GREATER,
1377 gcvCOMPARE_GREATER_OR_EQUAL,
1378 gcvCOMPARE_ALWAYS,
1379}
1380gceCOMPARE;
1381
1382/* Stencil modes. */
1383typedef enum _gceSTENCIL_MODE
1384{
1385 gcvSTENCIL_NONE,
1386 gcvSTENCIL_SINGLE_SIDED,
1387 gcvSTENCIL_DOUBLE_SIDED,
1388}
1389gceSTENCIL_MODE;
1390
1391/* Stencil operations. */
1392typedef enum _gceSTENCIL_OPERATION
1393{
1394 gcvSTENCIL_KEEP,
1395 gcvSTENCIL_REPLACE,
1396 gcvSTENCIL_ZERO,
1397 gcvSTENCIL_INVERT,
1398 gcvSTENCIL_INCREMENT,
1399 gcvSTENCIL_DECREMENT,
1400 gcvSTENCIL_INCREMENT_SATURATE,
1401 gcvSTENCIL_DECREMENT_SATURATE,
1402 gcvSTENCIL_OPERATION_INVALID = -1
1403}
1404gceSTENCIL_OPERATION;
1405
1406/* Stencil selection. */
1407typedef enum _gceSTENCIL_WHERE
1408{
1409 gcvSTENCIL_FRONT,
1410 gcvSTENCIL_BACK,
1411}
1412gceSTENCIL_WHERE;
1413
1414/* Texture addressing selection. */
1415typedef enum _gceTEXTURE_WHICH
1416{
1417 gcvTEXTURE_S,
1418 gcvTEXTURE_T,
1419 gcvTEXTURE_R,
1420}
1421gceTEXTURE_WHICH;
1422
1423/* Texture addressing modes. */
1424typedef enum _gceTEXTURE_ADDRESSING
1425{
1426 gcvTEXTURE_INVALID = 0,
1427 gcvTEXTURE_CLAMP,
1428 gcvTEXTURE_WRAP,
1429 gcvTEXTURE_MIRROR,
1430 gcvTEXTURE_BORDER,
1431 gcvTEXTURE_MIRROR_ONCE,
1432}
1433gceTEXTURE_ADDRESSING;
1434
1435/* Texture filters. */
1436typedef enum _gceTEXTURE_FILTER
1437{
1438 gcvTEXTURE_NONE,
1439 gcvTEXTURE_POINT,
1440 gcvTEXTURE_LINEAR,
1441 gcvTEXTURE_ANISOTROPIC,
1442}
1443gceTEXTURE_FILTER;
1444
1445typedef enum _gceTEXTURE_COMPONENT
1446{
1447 gcvTEXTURE_COMPONENT_R,
1448 gcvTEXTURE_COMPONENT_G,
1449 gcvTEXTURE_COMPONENT_B,
1450 gcvTEXTURE_COMPONENT_A,
1451
1452 gcvTEXTURE_COMPONENT_NUM,
1453} gceTEXTURE_COMPONENT;
1454
1455/* Texture swizzle modes. */
1456typedef enum _gceTEXTURE_SWIZZLE
1457{
1458 gcvTEXTURE_SWIZZLE_R = 0,
1459 gcvTEXTURE_SWIZZLE_G,
1460 gcvTEXTURE_SWIZZLE_B,
1461 gcvTEXTURE_SWIZZLE_A,
1462 gcvTEXTURE_SWIZZLE_0,
1463 gcvTEXTURE_SWIZZLE_1,
1464
1465 gcvTEXTURE_SWIZZLE_INVALID,
1466} gceTEXTURE_SWIZZLE;
1467
1468typedef enum _gceTEXTURE_COMPARE_MODE
1469{
1470 gcvTEXTURE_COMPARE_MODE_INVALID = 0,
1471 gcvTEXTURE_COMPARE_MODE_NONE,
1472 gcvTEXTURE_COMPARE_MODE_REF,
1473} gceTEXTURE_COMPARE_MODE;
1474
1475/* Pixel output swizzle modes. */
1476typedef enum _gcePIXEL_SWIZZLE
1477{
1478 gcvPIXEL_SWIZZLE_R = gcvTEXTURE_SWIZZLE_R,
1479 gcvPIXEL_SWIZZLE_G = gcvTEXTURE_SWIZZLE_G,
1480 gcvPIXEL_SWIZZLE_B = gcvTEXTURE_SWIZZLE_B,
1481 gcvPIXEL_SWIZZLE_A = gcvTEXTURE_SWIZZLE_A,
1482
1483 gcvPIXEL_SWIZZLE_INVALID,
1484} gcePIXEL_SWIZZLE;
1485
1486/* Primitive types. */
1487typedef enum _gcePRIMITIVE
1488{
1489 gcvPRIMITIVE_POINT_LIST,
1490 gcvPRIMITIVE_LINE_LIST,
1491 gcvPRIMITIVE_LINE_STRIP,
1492 gcvPRIMITIVE_LINE_LOOP,
1493 gcvPRIMITIVE_TRIANGLE_LIST,
1494 gcvPRIMITIVE_TRIANGLE_STRIP,
1495 gcvPRIMITIVE_TRIANGLE_FAN,
1496 gcvPRIMITIVE_RECTANGLE,
1497}
1498gcePRIMITIVE;
1499
1500/* Index types. */
1501typedef enum _gceINDEX_TYPE
1502{
1503 gcvINDEX_8,
1504 gcvINDEX_16,
1505 gcvINDEX_32,
1506}
1507gceINDEX_TYPE;
1508
1509/* Multi GPU rendering modes. */
1510typedef enum _gceMULTI_GPU_RENDERING_MODE
1511{
1512 gcvMULTI_GPU_RENDERING_MODE_OFF,
1513 gcvMULTI_GPU_RENDERING_MODE_SPLIT_WIDTH,
1514 gcvMULTI_GPU_RENDERING_MODE_SPLIT_HEIGHT,
1515 gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_64x64,
1516 gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_128x64,
1517 gcvMULTI_GPU_RENDERING_MODE_INTERLEAVED_128x128
1518}
1519gceMULTI_GPU_RENDERING_MODE;
1520
1521typedef enum _gceCORE_3D_MASK
1522{
1523 gcvCORE_3D_0_MASK = (1 << 0),
1524 gcvCORE_3D_1_MASK = (1 << 1),
1525
1526 gcvCORE_3D_ALL_MASK = (0xFFFF)
1527}
1528gceCORE_3D_MASK;
1529
1530typedef enum _gceCORE_3D_ID
1531{
1532 gcvCORE_3D_0_ID = 0,
1533 gcvCORE_3D_1_ID = 1,
1534
1535 gcvCORE_3D_ID_INVALID = ~0UL
1536}
1537gceCORE_3D_ID;
1538
1539typedef enum _gceMULTI_GPU_MODE
1540{
1541 gcvMULTI_GPU_MODE_COMBINED = 0,
1542 gcvMULTI_GPU_MODE_INDEPENDENT = 1
1543}
1544gceMULTI_GPU_MODE;
1545
1546typedef enum _gceMACHINECODE
1547{
1548 gcvMACHINECODE_ANTUTU0 = 0x0,
1549
1550 gcvMACHINECODE_GLB27_RELEASE_0,
1551
1552 gcvMACHINECODE_GLB25_RELEASE_0,
1553 gcvMACHINECODE_GLB25_RELEASE_1,
1554 gcvMACHINECODE_GLB25_RELEASE_2,
1555
1556 /* keep it as the last enum */
1557 gcvMACHINECODE_COUNT
1558}
1559gceMACHINECODE;
1560
1561typedef enum _gceUNIFORMCVT
1562{
1563 gcvUNIFORMCVT_NONE = 0,
1564 gcvUNIFORMCVT_TO_BOOL,
1565 gcvUNIFORMCVT_TO_FLOAT,
1566} gceUNIFORMCVT;
1567
1568typedef enum _gceHAL_ARG_VERSION
1569{
1570 gcvHAL_ARG_VERSION_V1 = 0x0,
1571}
1572gceHAL_ARG_VERSION;
1573
1574
1575typedef enum _gceCMDBUF_TYPE
1576{
1577 /* Contiguous command buffer. */
1578 gcvCMDBUF_CONTIGUOUS,
1579 /* Virtual command buffer. */
1580 gcvCMDBUF_VIRTUAL,
1581 /* Command buffer allocated from reserved memory. */
1582 gcvCMDBUF_RESERVED,
1583}
1584gceCMDBUF_SOURCE;
1585
1586typedef enum _gceCHIP_FALG
1587{
1588 gcvCHIP_FLAG_MSAA_COHERENCEY_ECO_FIX = 1 << 0,
1589 gcvCHIP_FLAG_GC2000_R2 = 1 << 1,
1590}
1591gceCHIP_FLAG;
1592
1593/*
1594* Bit of a requirment is 1 means requirement is a must, 0 means requirement can
1595* be ignored.
1596*/
1597#define gcvALLOC_FLAG_CONTIGUOUS_BIT 0
1598#define gcvALLOC_FLAG_CACHEABLE_BIT 1
1599#define gcvALLOC_FLAG_SECURITY_BIT 2
1600#define gcvALLOC_FLAG_NON_CONTIGUOUS_BIT 3
1601#define gcvALLOC_FLAG_MEMLIMIT_BIT 4
1602#define gcvALLOC_FLAG_DMABUF_BIT 5
1603#define gcvALLOC_FLAG_USERMEMORY_BIT 6
1604
1605/* No special needs. */
1606#define gcvALLOC_FLAG_NONE (0)
1607/* Physical contiguous. */
1608#define gcvALLOC_FLAG_CONTIGUOUS (1 << gcvALLOC_FLAG_CONTIGUOUS_BIT)
1609/* Can be remapped as cacheable. */
1610#define gcvALLOC_FLAG_CACHEABLE (1 << gcvALLOC_FLAG_CACHEABLE_BIT)
1611/* Secure buffer. */
1612#define gcvALLOC_FLAG_SECURITY (1 << gcvALLOC_FLAG_SECURITY_BIT)
1613/* Physical non contiguous. */
1614#define gcvALLOC_FLAG_NON_CONTIGUOUS (1 << gcvALLOC_FLAG_NON_CONTIGUOUS_BIT)
1615
1616#define gcvALLOC_FLAG_MEMLIMIT (1 << gcvALLOC_FLAG_MEMLIMIT_BIT)
1617
1618/* Import DMABUF. */
1619#define gcvALLOC_FLAG_DMABUF (1 << gcvALLOC_FLAG_DMABUF_BIT)
1620/* Import USERMEMORY. */
1621#define gcvALLOC_FLAG_USERMEMORY (1 << gcvALLOC_FLAG_USERMEMORY_BIT)
1622
1623/* GL_VIV internal usage */
1624#ifndef GL_MAP_BUFFER_OBJ_VIV
1625#define GL_MAP_BUFFER_OBJ_VIV 0x10000
1626#endif
1627
1628/* Command buffer usage. */
1629#define gcvCOMMAND_2D (1 << 0)
1630#define gcvCOMMAND_3D (1 << 1)
1631
1632/******************************************************************************\
1633****************************** Object Declarations *****************************
1634\******************************************************************************/
1635
1636typedef struct _gckCONTEXT * gckCONTEXT;
1637typedef struct _gcoCMDBUF * gcoCMDBUF;
1638
1639typedef struct _gcsSTATE_DELTA * gcsSTATE_DELTA_PTR;
1640typedef struct _gcsQUEUE * gcsQUEUE_PTR;
1641typedef struct _gcoQUEUE * gcoQUEUE;
1642typedef struct _gcsHAL_INTERFACE * gcsHAL_INTERFACE_PTR;
1643typedef struct _gcs2D_PROFILE * gcs2D_PROFILE_PTR;
1644
1645
1646#ifdef __cplusplus
1647}
1648#endif
1649
1650#endif /* __gc_hal_enum_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_kernel_buffer.h b/src/hal/kernel/inc/gc_hal_kernel_buffer.h
new file mode 100755
index 0000000..8b71fc1
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_kernel_buffer.h
@@ -0,0 +1,259 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_buffer_h_
57#define __gc_hal_kernel_buffer_h_
58
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63/******************************************************************************\
64************************ Command Buffer and Event Objects **********************
65\******************************************************************************/
66
67/* The number of context buffers per user. */
68#define gcdCONTEXT_BUFFER_COUNT 2
69
70/* State delta record. */
71typedef struct _gcsSTATE_DELTA_RECORD * gcsSTATE_DELTA_RECORD_PTR;
72typedef struct _gcsSTATE_DELTA_RECORD
73{
74 /* State address. */
75 gctUINT address;
76
77 /* State mask. */
78 gctUINT32 mask;
79
80 /* State data. */
81 gctUINT32 data;
82}
83gcsSTATE_DELTA_RECORD;
84
85/* State delta. */
86typedef struct _gcsSTATE_DELTA
87{
88 /* For debugging: the number of delta in the order of creation. */
89#if gcmIS_DEBUG(gcdDEBUG_CODE)
90 gctUINT num;
91#endif
92
93 /* Main state delta ID. Every time state delta structure gets reinitialized,
94 main ID is incremented. If main state ID overflows, all map entry IDs get
95 reinitialized to make sure there is no potential erroneous match after
96 the overflow.*/
97 gctUINT id;
98
99 /* The number of contexts pending modification by the delta. */
100 gctINT refCount;
101
102 /* Vertex element count for the delta buffer. */
103 gctUINT elementCount;
104
105 /* Number of states currently stored in the record array. */
106 gctUINT recordCount;
107
108 /* Record array; holds all modified states in gcsSTATE_DELTA_RECORD. */
109 gctUINT64 recordArray;
110
111 /* Map entry ID is used for map entry validation. If map entry ID does not
112 match the main state delta ID, the entry and the corresponding state are
113 considered not in use. */
114 gctUINT64 mapEntryID;
115 gctUINT mapEntryIDSize;
116
117 /* If the map entry ID matches the main state delta ID, index points to
118 the state record in the record array. */
119 gctUINT64 mapEntryIndex;
120
121 /* Previous and next state deltas in gcsSTATE_DELTA. */
122 gctUINT64 prev;
123 gctUINT64 next;
124}
125gcsSTATE_DELTA;
126
127/* Command buffer patch record. */
128struct _gcsPATCH
129{
130 /* Pointer within the buffer. */
131 gctUINT32_PTR pointer;
132
133 /* 32-bit data to write at the specified offset. */
134 gctUINT32 data;
135};
136
137/* List of patches for the command buffer. */
138struct _gcsPATCH_LIST
139{
140 /* Array of patch records. */
141 struct _gcsPATCH patch[1024];
142
143 /* Number of patches in the array. */
144 gctUINT count;
145
146 /* Next item in the list. */
147 struct _gcsPATCH_LIST *next;
148};
149
150/* Command buffer object. */
151struct _gcoCMDBUF
152{
153 /* The object. */
154 gcsOBJECT object;
155
156 /* Commit count. */
157 gctUINT64 commitCount;
158
159 /* Command buffer entry and exit pipes. */
160 gcePIPE_SELECT entryPipe;
161 gcePIPE_SELECT exitPipe;
162
163 /* Feature usage flags. */
164 gctBOOL using2D;
165 gctBOOL using3D;
166 gctBOOL usingFilterBlit;
167 gctBOOL usingPalette;
168
169 /* Physical address of command buffer. Just a name. */
170 gctUINT32 physical;
171
172 /* Logical address of command buffer. */
173 gctUINT64 logical;
174
175 /* Number of bytes in command buffer. */
176 gctUINT32 bytes;
177
178 /* Start offset into the command buffer. */
179 gctUINT32 startOffset;
180
181 /* Current offset into the command buffer. */
182 gctUINT32 offset;
183
184 /* Number of free bytes in command buffer. */
185 gctUINT32 free;
186
187 /* Location of the last reserved area. */
188 gctUINT64 lastReserve;
189 gctUINT32 lastOffset;
190
191#if gcdSECURE_USER
192 /* Hint array for the current command buffer. */
193 gctUINT hintArraySize;
194 gctUINT64 hintArray;
195 gctUINT64 hintArrayTail;
196#endif
197
198#if gcmIS_DEBUG(gcdDEBUG_CODE)
199 /* Last load state command location and hardware address. */
200 gctUINT64 lastLoadStatePtr;
201 gctUINT32 lastLoadStateAddress;
202 gctUINT32 lastLoadStateCount;
203#endif
204
205 /* Completion signal. */
206 gctSIGNAL signal;
207
208 /* List of patches. */
209 struct _gcsPATCH_LIST *patchHead;
210 struct _gcsPATCH_LIST *patchTail;
211
212 /* Link to the siblings. */
213 gcoCMDBUF prev;
214 gcoCMDBUF next;
215};
216
217typedef struct _gcsQUEUE
218{
219 /* Pointer to next gcsQUEUE structure in gcsQUEUE. */
220 gctUINT64 next;
221
222 /* Event information. */
223 gcsHAL_INTERFACE iface;
224}
225gcsQUEUE;
226
227/* Event queue. */
228struct _gcoQUEUE
229{
230 /* The object. */
231 gcsOBJECT object;
232
233 /* Pointer to current event queue. */
234 gcsQUEUE_PTR head;
235 gcsQUEUE_PTR tail;
236
237 /* chunks of the records. */
238 gctPOINTER chunks;
239
240 /* List of free records. */
241 gcsQUEUE_PTR freeList;
242
243 #define gcdIN_QUEUE_RECORD_LIMIT 16
244 /* Number of records currently in queue */
245 gctUINT32 recordCount;
246};
247
248struct _gcsTEMPCMDBUF
249{
250 gctUINT32 currentByteSize;
251 gctPOINTER buffer;
252 gctBOOL inUse;
253};
254
255#ifdef __cplusplus
256}
257#endif
258
259#endif /* __gc_hal_kernel_buffer_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_mem.h b/src/hal/kernel/inc/gc_hal_mem.h
new file mode 100755
index 0000000..8ad3426
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_mem.h
@@ -0,0 +1,62 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56/*
57** Include file for the local memory management.
58*/
59
60#ifndef __gc_hal_mem_h_
61#define __gc_hal_mem_h_
62#endif /* __gc_hal_mem_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_options.h b/src/hal/kernel/inc/gc_hal_options.h
new file mode 100755
index 0000000..6ad0aec
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_options.h
@@ -0,0 +1,1329 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_options_h_
57#define __gc_hal_options_h_
58
59/*
60 gcdSECURITY
61
62*/
63#ifndef gcdSECURITY
64# define gcdSECURITY 0
65#endif
66
67/*
68 gcdPRINT_VERSION
69
70 Print HAL version.
71*/
72#ifndef gcdPRINT_VERSION
73# define gcdPRINT_VERSION 0
74#endif
75
76/*
77 USE_NEW_LINUX_SIGNAL
78
79 This define enables the Linux kernel signaling between kernel and user.
80*/
81#ifndef USE_NEW_LINUX_SIGNAL
82# define USE_NEW_LINUX_SIGNAL 0
83#endif
84
85/*
86 VIVANTE_PROFILER
87
88 This define enables the profiler.
89*/
90#ifndef VIVANTE_PROFILER
91# define VIVANTE_PROFILER 1
92#endif
93
94/*
95 VIVANTE_PROFILER_CONTEXT
96
97 This define enables the profiler according each context.
98*/
99#ifndef VIVANTE_PROFILER_CONTEXT
100# define VIVANTE_PROFILER_CONTEXT 1
101#endif
102
103#ifndef VIVANTE_PROFILER_PERDRAW
104# define VIVANTE_PROFILER_PERDRAW 0
105#endif
106
107#ifndef VIVANTE_PROFILER_NEW
108# define VIVANTE_PROFILER_NEW 0
109#endif
110
111#ifndef VIVANTE_PROFILER_PM
112# define VIVANTE_PROFILER_PM 1
113#endif
114/*
115 gcdUSE_VG
116
117 Enable VG HAL layer (only for GC350).
118*/
119#ifndef gcdUSE_VG
120# define gcdUSE_VG 0
121#endif
122
123/*
124 USE_SW_FB
125
126 Set to 1 if the frame buffer memory cannot be accessed by the GPU.
127*/
128#ifndef USE_SW_FB
129# define USE_SW_FB 0
130#endif
131
132/*
133 PROFILE_HAL_COUNTERS
134
135 This define enables HAL counter profiling support. HW and SHADER
136 counter profiling depends on this.
137*/
138#ifndef PROFILE_HAL_COUNTERS
139# define PROFILE_HAL_COUNTERS 1
140#endif
141
142/*
143 PROFILE_HW_COUNTERS
144
145 This define enables HW counter profiling support.
146*/
147#ifndef PROFILE_HW_COUNTERS
148# define PROFILE_HW_COUNTERS 1
149#endif
150
151/*
152 PROFILE_SHADER_COUNTERS
153
154 This define enables SHADER counter profiling support.
155*/
156#ifndef PROFILE_SHADER_COUNTERS
157# define PROFILE_SHADER_COUNTERS 1
158#endif
159
160/*
161 COMMAND_PROCESSOR_VERSION
162
163 The version of the command buffer and task manager.
164*/
165#define COMMAND_PROCESSOR_VERSION 1
166
167/*
168 gcdDUMP_KEY
169
170 Set this to a string that appears in 'cat /proc/<pid>/cmdline'. E.g. 'camera'.
171 HAL will create dumps for the processes matching this key.
172*/
173#ifndef gcdDUMP_KEY
174# define gcdDUMP_KEY "process"
175#endif
176
177/*
178 gcdDUMP_PATH
179
180 The dump file location. Some processes cannot write to the sdcard.
181 Try apps' data dir, e.g. /data/data/com.android.launcher
182*/
183#ifndef gcdDUMP_PATH
184#if defined(ANDROID)
185# define gcdDUMP_PATH "/mnt/sdcard/"
186#else
187# define gcdDUMP_PATH "./"
188#endif
189#endif
190
191/*
192 gcdDUMP
193
194 When set to 1, a dump of all states and memory uploads, as well as other
195 hardware related execution will be printed to the debug console. This
196 data can be used for playing back applications.
197*/
198#ifndef gcdDUMP
199# define gcdDUMP 0
200#endif
201
202/*
203 gcdDUMP_API
204
205 When set to 1, a high level dump of the EGL and GL/VG APs's are
206 captured.
207*/
208#ifndef gcdDUMP_API
209# define gcdDUMP_API 0
210#endif
211
212
213
214/*
215 gcdDEBUG_OPTION
216 When set to 1, the debug options are enabled. We must set other MACRO to enable
217 sub case.
218*/
219#ifndef gcdDEBUG_OPTION
220# define gcdDEBUG_OPTION 0
221
222#if gcdDEBUG_OPTION
223/*
224 gcdDEBUG_OPTION_KEY
225 The process name of debug application.
226*/
227#ifndef gcdDEBUG_OPTION_KEY
228# define gcdDEBUG_OPTION_KEY "process"
229# endif
230/*
231 gcdDEBUG_OPTION_NO_GL_DRAWS
232 When set to 1, all glDrawArrays and glDrawElements will be skip.
233*/
234#ifndef gcdDEBUG_OPTION_NO_GL_DRAWS
235# define gcdDEBUG_OPTION_NO_GL_DRAWS 0
236# endif
237/*
238 gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES
239 When set to 1, all DrawPrimitives will be skip.
240*/
241#ifndef gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES
242# define gcdDEBUG_OPTION_NO_DRAW_PRIMITIVES 0
243# endif
244/*
245 gcdDEBUG_OPTION_SKIP_SWAP
246 When set to 1, just one out of gcdDEBUG_OPTION_SKIP_FRAMES(such as 1/10) eglSwapBuffers will be resolve,
247 others skip.
248*/
249#ifndef gcdDEBUG_OPTION_SKIP_SWAP
250# define gcdDEBUG_OPTION_SKIP_SWAP 0
251# define gcdDEBUG_OPTION_SKIP_FRAMES 10
252# endif
253/*
254 gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET
255 When set to 1, the format of render target will force to RGB565.
256*/
257#ifndef gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET
258# define gcdDEBUG_OPTION_FORCE_16BIT_RENDER_TARGET 0
259# endif
260/*
261 gcdDEBUG_OPTION_NONE_TEXTURE
262 When set to 1, the type of texture will be set to AQ_TEXTURE_SAMPLE_MODE_TYPE_NONE.
263*/
264#ifndef gcdDEBUG_OPTION_NONE_TEXTURE
265# define gcdDEBUG_OPTION_NONE_TEXTURE 0
266# endif
267/*
268 gcdDEBUG_OPTION_NONE_DEPTH
269 When set to 1, the depth format of surface will be set to gcvSURF_UNKNOWN.
270*/
271#ifndef gcdDEBUG_OPTION_NONE_DEPTH
272# define gcdDEBUG_OPTION_NONE_DEPTH 0
273# endif
274
275# endif
276#endif
277
278/*
279 gcdDUMP_SWAP_PER_DRAW
280
281 When set to 1, dump swap command for every single draw to make simulation comparison happy.
282 Only valid for ES3 driver for now.
283*/
284#ifndef gcdDUMP_SWAP_PER_DRAW
285# define gcdDUMP_SWAP_PER_DRAW 0
286#endif
287
288/*
289 gcdDUMP_FRAMERATE
290 When set to a value other than zero, averaqe frame rate will be dumped.
291 The value set is the starting frame that the average will be calculated.
292 This is needed because sometimes first few frames are too slow to be included
293 in the average. Frame count starts from 1.
294*/
295#ifndef gcdDUMP_FRAMERATE
296# define gcdDUMP_FRAMERATE 0
297#endif
298
299/*
300 gcdENABLE_FSCALE_VAL_ADJUST
301 When non-zero, FSCALE_VAL when gcvPOWER_ON can be adjusted externally.
302 */
303#ifndef gcdENABLE_FSCALE_VAL_ADJUST
304# define gcdENABLE_FSCALE_VAL_ADJUST 1
305#endif
306
307/*
308 gcdDUMP_IN_KERNEL
309
310 When set to 1, all dumps will happen in the kernel. This is handy if
311 you want the kernel to dump its command buffers as well and the data
312 needs to be in sync.
313*/
314#ifndef gcdDUMP_IN_KERNEL
315# define gcdDUMP_IN_KERNEL 0
316#endif
317
318/*
319 gcdDUMP_COMMAND
320
321 When set to non-zero, the command queue will dump all incoming command
322 and context buffers as well as all other modifications to the command
323 queue.
324*/
325#ifndef gcdDUMP_COMMAND
326# define gcdDUMP_COMMAND 0
327#endif
328
329/*
330 gcdDUMP_2D
331
332 When set to non-zero, it will dump the 2D command and surface.
333*/
334#ifndef gcdDUMP_2D
335# define gcdDUMP_2D 0
336#endif
337
338/*
339 gcdDUMP_FRAME_TGA
340
341 When set to a value other than 0, a dump of the frame specified by the value,
342 will be done into frame.tga. Frame count starts from 1.
343 */
344#ifndef gcdDUMP_FRAME_TGA
345# define gcdDUMP_FRAME_TGA 0
346#endif
347/*
348 gcdNULL_DRIVER
349
350 Set to 1 for infinite speed hardware.
351 Set to 2 for bypassing the HAL.
352 Set to 3 for bypassing the drivers.
353*/
354#ifndef gcdNULL_DRIVER
355# define gcdNULL_DRIVER 0
356#endif
357
358/*
359 gcdENABLE_TIMEOUT_DETECTION
360
361 Enable timeout detection.
362*/
363#ifndef gcdENABLE_TIMEOUT_DETECTION
364# define gcdENABLE_TIMEOUT_DETECTION 0
365#endif
366
367/*
368 gcdCMD_BUFFER_SIZE
369
370 Number of bytes in a command buffer.
371*/
372#ifndef gcdCMD_BUFFER_SIZE
373# define gcdCMD_BUFFER_SIZE (128 << 10)
374#endif
375
376/*
377 gcdCMD_BUFFERS
378
379 Number of command buffers to use per client.
380*/
381#ifndef gcdCMD_BUFFERS
382# define gcdCMD_BUFFERS 2
383#endif
384
385/*
386 gcdMAX_CMD_BUFFERS
387
388 Maximum number of command buffers to use per client.
389*/
390#ifndef gcdMAX_CMD_BUFFERS
391# define gcdMAX_CMD_BUFFERS 8
392#endif
393
394/*
395 gcdCOMMAND_QUEUES
396
397 Number of command queues in the kernel.
398*/
399#ifndef gcdCOMMAND_QUEUES
400# define gcdCOMMAND_QUEUES 2
401#endif
402
403/*
404 gcdPOWER_CONTROL_DELAY
405
406 The delay in milliseconds required to wait until the GPU has woke up
407 from a suspend or power-down state. This is system dependent because
408 the bus clock also needs to stabalize.
409*/
410#ifndef gcdPOWER_CONTROL_DELAY
411# define gcdPOWER_CONTROL_DELAY 0
412#endif
413
414/*
415 gcdMIRROR_PAGETABLE
416
417 Enable it when GPUs with old MMU and new MMU exist at same SoC. It makes
418 each GPU use same virtual address to access same physical memory.
419*/
420#ifndef gcdMIRROR_PAGETABLE
421# define gcdMIRROR_PAGETABLE 0
422#endif
423
424/*
425 gcdMMU_SIZE
426
427 Size of the MMU page table in bytes. Each 4 bytes can hold 4kB worth of
428 virtual data.
429*/
430#ifndef gcdMMU_SIZE
431#if gcdMIRROR_PAGETABLE
432# define gcdMMU_SIZE 0x200000
433#else
434# define gcdMMU_SIZE (256 << 10)
435#endif
436#endif
437
438/*
439 gcdSECURE_USER
440
441 Use logical addresses instead of physical addresses in user land. In
442 this case a hint table is created for both command buffers and context
443 buffers, and that hint table will be used to patch up those buffers in
444 the kernel when they are ready to submit.
445*/
446#ifndef gcdSECURE_USER
447# define gcdSECURE_USER 0
448#endif
449
450/*
451 gcdSECURE_CACHE_SLOTS
452
453 Number of slots in the logical to DMA address cache table. Each time a
454 logical address needs to be translated into a DMA address for the GPU,
455 this cache will be walked. The replacement scheme is LRU.
456*/
457#ifndef gcdSECURE_CACHE_SLOTS
458# define gcdSECURE_CACHE_SLOTS 1024
459#endif
460
461/*
462 gcdSECURE_CACHE_METHOD
463
464 Replacement scheme used for Secure Cache. The following options are
465 available:
466
467 gcdSECURE_CACHE_LRU
468 A standard LRU cache.
469
470 gcdSECURE_CACHE_LINEAR
471 A linear walker with the idea that an application will always
472 render the scene in a similar way, so the next entry in the
473 cache should be a hit most of the time.
474
475 gcdSECURE_CACHE_HASH
476 A 256-entry hash table.
477
478 gcdSECURE_CACHE_TABLE
479 A simple cache but with potential of a lot of cache replacement.
480*/
481#ifndef gcdSECURE_CACHE_METHOD
482# define gcdSECURE_CACHE_METHOD gcdSECURE_CACHE_HASH
483#endif
484
485/*
486 gcdREGISTER_ACCESS_FROM_USER
487
488 Set to 1 to allow IOCTL calls to get through from user land. This
489 should only be in debug or development drops.
490*/
491#ifndef gcdREGISTER_ACCESS_FROM_USER
492# define gcdREGISTER_ACCESS_FROM_USER 1
493#endif
494
495/*
496 gcdHEAP_SIZE
497
498 Set the allocation size for the internal heaps. Each time a heap is
499 full, a new heap will be allocated with this minmimum amount of bytes.
500 The bigger this size, the fewer heaps there are to allocate, the better
501 the performance. However, heaps won't be freed until they are
502 completely free, so there might be some more memory waste if the size is
503 too big.
504*/
505#ifndef gcdHEAP_SIZE
506# define gcdHEAP_SIZE (64 << 10)
507#endif
508
509/*
510 gcdPOWER_SUSPEND_WHEN_IDLE
511
512 Set to 1 to make GPU enter gcvPOWER_SUSPEND when idle detected,
513 otherwise GPU will enter gcvPOWER_IDLE.
514*/
515#ifndef gcdPOWER_SUSPEND_WHEN_IDLE
516# define gcdPOWER_SUSPEND_WHEN_IDLE 1
517#endif
518
519#ifndef gcdFPGA_BUILD
520# define gcdFPGA_BUILD 0
521#endif
522
523/*
524 gcdGPU_TIMEOUT
525
526 This define specified the number of milliseconds the system will wait
527 before it broadcasts the GPU is stuck. In other words, it will define
528 the timeout of any operation that needs to wait for the GPU.
529
530 If the value is 0, no timeout will be checked for.
531*/
532#ifndef gcdGPU_TIMEOUT
533#if gcdFPGA_BUILD
534# define gcdGPU_TIMEOUT 0
535# define gcdGPU_2D_TIMEOUT 0
536# else
537# define gcdGPU_TIMEOUT 20000
538# define gcdGPU_2D_TIMEOUT 4000
539# endif
540#endif
541
542/*
543 gcdGPU_ADVANCETIMER
544
545 it is advance timer.
546*/
547#ifndef gcdGPU_ADVANCETIMER
548# define gcdGPU_ADVANCETIMER 250
549#endif
550
551/*
552 gcdSTATIC_LINK
553
554 This define disalbes static linking;
555*/
556#ifndef gcdSTATIC_LINK
557# define gcdSTATIC_LINK 0
558#endif
559
560/*
561 gcdUSE_NEW_HEAP
562
563 Setting this define to 1 enables new heap.
564*/
565#ifndef gcdUSE_NEW_HEAP
566# define gcdUSE_NEW_HEAP 0
567#endif
568
569/*
570 gcdCMD_NO_2D_CONTEXT
571
572 This define enables no-context 2D command buffer.
573*/
574#ifndef gcdCMD_NO_2D_CONTEXT
575# define gcdCMD_NO_2D_CONTEXT 1
576#endif
577
578/*
579 gcdENABLE_BUFFER_ALIGNMENT
580
581 When enabled, video memory is allocated with atleast 16KB aligment
582 between multiple sub-buffers.
583*/
584#ifndef gcdENABLE_BUFFER_ALIGNMENT
585# define gcdENABLE_BUFFER_ALIGNMENT 1
586#endif
587
588/*
589 gcdENABLE_BANK_ALIGNMENT
590
591 When enabled, video memory is allocated bank aligned. The vendor can modify
592 _GetSurfaceBankAlignment() and _GetBankOffsetBytes() to define how
593 different types of allocations are bank and channel aligned.
594 When disabled (default), no bank alignment is done.
595*/
596#ifndef gcdENABLE_BANK_ALIGNMENT
597# define gcdENABLE_BANK_ALIGNMENT 0
598#endif
599
600/*
601 gcdBANK_BIT_START
602
603 Specifies the start bit of the bank (inclusive).
604*/
605#ifndef gcdBANK_BIT_START
606# define gcdBANK_BIT_START 12
607#endif
608
609/*
610 gcdBANK_BIT_END
611
612 Specifies the end bit of the bank (inclusive).
613*/
614#ifndef gcdBANK_BIT_END
615# define gcdBANK_BIT_END 14
616#endif
617
618/*
619 gcdBANK_CHANNEL_BIT
620
621 When set, video memory when allocated bank aligned is allocated such that
622 render and depth buffer addresses alternate on the channel bit specified.
623 This option has an effect only when gcdENABLE_BANK_ALIGNMENT is enabled.
624 When disabled (default), no alteration is done.
625*/
626#ifndef gcdBANK_CHANNEL_BIT
627# define gcdBANK_CHANNEL_BIT 7
628#endif
629
630/*
631 gcdDYNAMIC_SPEED
632
633 When non-zero, it informs the kernel driver to use the speed throttling
634 broadcasting functions to inform the system the GPU should be spet up or
635 slowed down. It will send a broadcast for slowdown each "interval"
636 specified by this define in milliseconds
637 (gckOS_BroadcastCalibrateSpeed).
638*/
639#ifndef gcdDYNAMIC_SPEED
640# define gcdDYNAMIC_SPEED 2000
641#endif
642
643/*
644 gcdDYNAMIC_EVENT_THRESHOLD
645
646 When non-zero, it specifies the maximum number of available events at
647 which the kernel driver will issue a broadcast to speed up the GPU
648 (gckOS_BroadcastHurry).
649*/
650#ifndef gcdDYNAMIC_EVENT_THRESHOLD
651# define gcdDYNAMIC_EVENT_THRESHOLD 5
652#endif
653
654/*
655 gcdENABLE_PROFILING
656
657 Enable profiling macros.
658*/
659#ifndef gcdENABLE_PROFILING
660# define gcdENABLE_PROFILING 0
661#endif
662
663/*
664 gcdENABLE_128B_MERGE
665
666 Enable 128B merge for the BUS control.
667*/
668#ifndef gcdENABLE_128B_MERGE
669# define gcdENABLE_128B_MERGE 0
670#endif
671
672/*
673 gcdFRAME_DB
674
675 When non-zero, it specified the number of frames inside the frame
676 database. The frame DB will collect per-frame timestamps and hardware
677 counters.
678*/
679#ifndef gcdFRAME_DB
680# define gcdFRAME_DB 0
681# define gcdFRAME_DB_RESET 0
682# define gcdFRAME_DB_NAME "/var/log/frameDB.log"
683#endif
684
685/*
686 gcdDISABLE_CORES_2D3D
687 disable the 2D3D cores for 2D openVG
688*/
689#ifndef gcdDISABLE_CORES_2D3D
690# define gcdDISABLE_CORES_2D3D 0
691#endif
692
693/*
694 gcdPAGED_MEMORY_CACHEABLE
695
696 When non-zero, paged memory will be cacheable.
697
698 Normally, driver will detemines whether a video memory
699 is cacheable or not. When cacheable is not neccessary,
700 it will be writecombine.
701
702 This option is only for those SOC which can't enable
703 writecombine without enabling cacheable.
704*/
705#ifndef gcdPAGED_MEMORY_CACHEABLE
706# define gcdPAGED_MEMORY_CACHEABLE 0
707#endif
708
709/*
710 gcdNONPAGED_MEMORY_CACHEABLE
711
712 When non-zero, non paged memory will be cacheable.
713*/
714#ifndef gcdNONPAGED_MEMORY_CACHEABLE
715# define gcdNONPAGED_MEMORY_CACHEABLE 0
716#endif
717
718/*
719 gcdNONPAGED_MEMORY_BUFFERABLE
720
721 When non-zero, non paged memory will be bufferable.
722 gcdNONPAGED_MEMORY_BUFFERABLE and gcdNONPAGED_MEMORY_CACHEABLE
723 can't be set 1 at same time
724*/
725#ifndef gcdNONPAGED_MEMORY_BUFFERABLE
726# define gcdNONPAGED_MEMORY_BUFFERABLE 1
727#endif
728
729/*
730 gcdENABLE_INFINITE_SPEED_HW
731 enable the Infinte HW , this is for 2D openVG
732*/
733#ifndef gcdENABLE_INFINITE_SPEED_HW
734# define gcdENABLE_INFINITE_SPEED_HW 0
735#endif
736
737/*
738 gcdMULTI_GPU
739
740 Enable/disable multi-GPU support.
741 0 : Disable multi-GPU support
742 1 : Enable one of the 3D cores
743 [2..X] : Number of 3D GPU Cores
744*/
745#ifndef gcdMULTI_GPU
746# define gcdMULTI_GPU 0
747#endif
748
749/*
750 gcdMULTI_GPU_AFFINITY
751
752 Enable/disable the binding of a context to one GPU
753*/
754#ifndef gcdMULTI_GPU_AFFINITY
755# define gcdMULTI_GPU_AFFINITY 0
756#endif
757
758/*
759 gcdPOWEROFF_TIMEOUT
760
761 When non-zero, GPU will power off automatically from
762 idle state, and gcdPOWEROFF_TIMEOUT is also the default
763 timeout in milliseconds.
764 */
765#ifndef gcdPOWEROFF_TIMEOUT
766# define gcdPOWEROFF_TIMEOUT 300
767#endif
768
769/*
770 QNX_SINGLE_THREADED_DEBUGGING
771*/
772#ifndef QNX_SINGLE_THREADED_DEBUGGING
773# define QNX_SINGLE_THREADED_DEBUGGING 0
774#endif
775
776/*
777 gcdRENDER_THREADS
778
779 Number of render threads. Make it zero, and there will be no render
780 threads.
781*/
782#ifndef gcdRENDER_THREADS
783# define gcdRENDER_THREADS 0
784#endif
785
786/*
787 gcdSMP
788
789 This define enables SMP support.
790
791 Currently, it only works on Linux/Android,
792 Kbuild will config it according to whether
793 CONFIG_SMP is set.
794
795*/
796#ifndef gcdSMP
797#ifdef __APPLE__
798# define gcdSMP 1
799#else
800# define gcdSMP 0
801#endif
802#endif
803
804/*
805 gcdSHARED_RESOLVE_BUFFER_ENABLED
806
807 Use shared resolve buffer for all app buffers.
808*/
809#ifndef gcdSHARED_RESOLVE_BUFFER_ENABLED
810# define gcdSHARED_RESOLVE_BUFFER_ENABLED 0
811#endif
812
813/*
814 gcdUSE_TRIANGLE_STRIP_PATCH
815 */
816#ifndef gcdUSE_TRIANGLE_STRIP_PATCH
817# define gcdUSE_TRIANGLE_STRIP_PATCH 1
818#endif
819
820/*
821 gcdENABLE_OUTER_CACHE_PATCH
822
823 Enable the outer cache patch.
824*/
825#ifndef gcdENABLE_OUTER_CACHE_PATCH
826# define gcdENABLE_OUTER_CACHE_PATCH 0
827#endif
828
829/*
830 gcdPROCESS_ADDRESS_SPACE
831
832 When non-zero, every process which attaches to galcore has its own GPU
833 address space, size of which is gcdPROCESS_ADDRESS_SPACE_SIZE.
834*/
835#ifndef gcdPROCESS_ADDRESS_SPACE
836# define gcdPROCESS_ADDRESS_SPACE 0
837# define gcdPROCESS_ADDRESS_SPACE_SIZE 0x80000000
838#endif
839
840/*
841 gcdSHARED_PAGETABLE
842
843 When non-zero, multiple GPUs in one chip with same MMU use
844 one shared pagetable. So that when accessing same surface,
845 they can use same GPU virtual address.
846*/
847#ifndef gcdSHARED_PAGETABLE
848# define gcdSHARED_PAGETABLE !gcdPROCESS_ADDRESS_SPACE
849#endif
850
851#ifndef gcdUSE_PVR
852# define gcdUSE_PVR 1
853#endif
854
855/*
856 gcdSMALL_BLOCK_SIZE
857
858 When non-zero, a part of VIDMEM will be reserved for requests
859 whose requesting size is less than gcdSMALL_BLOCK_SIZE.
860
861 For Linux, it's the size of a page. If this requeset fallbacks
862 to gcvPOOL_CONTIGUOUS or gcvPOOL_VIRTUAL, memory will be wasted
863 because they allocate a page at least.
864*/
865#ifndef gcdSMALL_BLOCK_SIZE
866# define gcdSMALL_BLOCK_SIZE 4096
867# define gcdRATIO_FOR_SMALL_MEMORY 32
868#endif
869
870/*
871 gcdCONTIGUOUS_SIZE_LIMIT
872 When non-zero, size of video node from gcvPOOL_CONTIGUOUS is
873 limited by gcdCONTIGUOUS_SIZE_LIMIT.
874*/
875#ifndef gcdCONTIGUOUS_SIZE_LIMIT
876# define gcdCONTIGUOUS_SIZE_LIMIT 0
877#endif
878
879/*
880 gcdLINK_QUEUE_SIZE
881
882 When non-zero, driver maintains a queue to record information of
883 latest lined context buffer and command buffer. Data in this queue
884 is be used to debug.
885*/
886#ifndef gcdLINK_QUEUE_SIZE
887# define gcdLINK_QUEUE_SIZE 64
888#endif
889
890/* gcdALPHA_KILL_IN_SHADER
891
892 Enable alpha kill inside the shader. This will be set automatically by the
893 HAL if certain states match a criteria.
894*/
895#ifndef gcdALPHA_KILL_IN_SHADER
896# define gcdALPHA_KILL_IN_SHADER 1
897#endif
898
899
900#ifndef gcdPRINT_SWAP_TIME
901# define gcdPRINT_SWAP_TIME 0
902#endif
903
904/*
905 gcdDVFS
906
907 When non-zero, software will make use of dynamic voltage and
908 frequency feature.
909 */
910#ifndef gcdDVFS
911# define gcdDVFS 0
912# define gcdDVFS_ANAYLSE_WINDOW 4
913# define gcdDVFS_POLLING_TIME (gcdDVFS_ANAYLSE_WINDOW * 4)
914#endif
915
916#ifndef gcdSYNC
917# define gcdSYNC 1
918#endif
919
920#ifndef gcdSHADER_SRC_BY_MACHINECODE
921# define gcdSHADER_SRC_BY_MACHINECODE 1
922#endif
923
924#ifndef gcdGLB27_SHADER_REPLACE_OPTIMIZATION
925# define gcdGLB27_SHADER_REPLACE_OPTIMIZATION 1
926#endif
927
928/*
929 gcdSTREAM_OUT_BUFFER
930
931 Enable suppport for the secondary stream out buffer.
932*/
933#ifndef gcdSTREAM_OUT_BUFFER
934# define gcdSTREAM_OUT_BUFFER 0
935# define gcdSTREAM_OUT_NAIVE_SYNC 0
936#endif
937
938/*
939 gcdUSE_HARDWARE_CONFIGURATION_TABLES
940
941 Enable the use of hardware configuration tables,
942 instead of query hardware and determine the features.
943*/
944#ifndef gcdUSE_HARDWARE_CONFIGURATION_TABLES
945# define gcdUSE_HARDWARE_CONFIGURATION_TABLES 0
946#endif
947
948/*
949 gcdSUPPORT_SWAP_RECTANGLE
950
951 Support swap with a specific rectangle.
952
953 Set the rectangle with eglSetSwapRectangleVIV api.
954 Android only.
955*/
956#ifndef gcdSUPPORT_SWAP_RECTANGLE
957# define gcdSUPPORT_SWAP_RECTANGLE 0
958#endif
959
960/*
961 gcdGPU_LINEAR_BUFFER_ENABLED
962
963 Use linear buffer for GPU apps so HWC can do 2D composition.
964 Android only.
965*/
966#ifndef gcdGPU_LINEAR_BUFFER_ENABLED
967# define gcdGPU_LINEAR_BUFFER_ENABLED 1
968#endif
969
970/*
971 gcdENABLE_RENDER_INTO_WINDOW
972
973 Enable Render-Into-Window (ie, No-Resolve or direct rendering) feature.
974 NOTE that even if enabled, it still depends on hardware feature and
975 application behavior. When hardware feature or application
976 behavior can not support render into window mode, it will fail back
977 to normal mode.
978 On android, if Render-Into-Window is finally used, window back buffer
979 of applications will be allocated matching render target tiling format.
980 Otherwise buffer tiling is decided by the above option
981 'gcdGPU_LINEAR_BUFFER_ENABLED'.
982*/
983#ifndef gcdENABLE_RENDER_INTO_WINDOW
984# define gcdENABLE_RENDER_INTO_WINDOW 1
985#endif
986
987/*
988 gcdENABLE_RENDER_INTO_WINDOW_WITH_FC
989
990 Enable Direct-rendering (ie, No-Resolve) with tile status.
991 This is expremental and in development stage.
992 This will dynamically check if color compression is available.
993*/
994#ifndef gcdENABLE_RENDER_INTO_WINDOW_WITH_FC
995# define gcdENABLE_RENDER_INTO_WINDOW_WITH_FC 1
996#endif
997
998/*
999 gcdENABLE_BLIT_BUFFER_PRESERVE
1000
1001 Render-Into-Window (ie, No-Resolve) does not include preserved swap
1002 behavior. This feature can enable buffer preserve in No-Resolve mode.
1003 When enabled, previous buffer (may be part of ) will be resolve-blitted
1004 to current buffer.
1005*/
1006#ifndef gcdENABLE_BLIT_BUFFER_PRESERVE
1007# define gcdENABLE_BLIT_BUFFER_PRESERVE 1
1008#endif
1009
1010/*
1011 gcdANDROID_NATIVE_FENCE_SYNC
1012
1013 Enable android native fence sync. It is introduced since jellybean-4.2.
1014 Depends on linux kernel option: CONFIG_SYNC.
1015
1016 0: Disabled
1017 1: Build framework for native fence sync feature, and EGL extension
1018 2: Enable async swap buffers for client
1019 * Native fence sync for client 'queueBuffer' in EGL, which is
1020 'acquireFenceFd' for layer in compositor side.
1021 3. Enable async hwcomposer composition.
1022 * 'releaseFenceFd' for layer in compositor side, which is native
1023 fence sync when client 'dequeueBuffer'
1024 * Native fence sync for compositor 'queueBuffer' in EGL, which is
1025 'acquireFenceFd' for framebuffer target for DC
1026 */
1027#ifndef gcdANDROID_NATIVE_FENCE_SYNC
1028# define gcdANDROID_NATIVE_FENCE_SYNC 0
1029#endif
1030
1031/*
1032 gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
1033
1034 Enable implicit android native buffer sync.
1035
1036 For non-HW_RENDER buffer, CPU (or other hardware) and GPU can access
1037 the buffer at the same time. This is to add implicit synchronization
1038 between CPU (or the hardware) and GPU.
1039
1040 Eventually, please do not use implicit native buffer sync, but use
1041 "fence sync" or "android native fence sync" instead in libgui, which
1042 can be enabled in frameworks/native/libs/gui/Android.mk. This kind
1043 of synchronization should be done by app but not driver itself.
1044
1045 Please disable this option when either "fence sync" or
1046 "android native fence sync" is enabled.
1047 */
1048#ifndef gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
1049# define gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC 1
1050#endif
1051
1052/*
1053 * Implicit native buffer sync is not needed when ANDROID_native_fence_sync
1054 * is available.
1055 */
1056#if gcdANDROID_NATIVE_FENCE_SYNC
1057# undef gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC
1058# define gcdANDROID_IMPLICIT_NATIVE_BUFFER_SYNC 0
1059#endif
1060
1061/*
1062 gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
1063
1064 Enable source surface address adjust when composition on android.
1065 Android only.
1066*/
1067#ifndef gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
1068# define gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST 1
1069#endif
1070
1071/*
1072 gcdUSE_WCLIP_PATCH
1073
1074 Enable wclipping patch.
1075*/
1076#ifndef gcdUSE_WCLIP_PATCH
1077# define gcdUSE_WCLIP_PATCH 1
1078#endif
1079
1080#ifndef gcdUSE_NPOT_PATCH
1081# define gcdUSE_NPOT_PATCH 1
1082#endif
1083
1084/*
1085 gcd3DBLIT
1086
1087 TODO: Should be replaced by feature bit if available.
1088*/
1089#ifndef gcd3DBLIT
1090# define gcd3DBLIT 0
1091#endif
1092
1093/*
1094 gcdINTERNAL_COMMENT
1095
1096 Wrap internal comment, content wrapped by it and the macor itself
1097 will be removed in release driver.
1098*/
1099#ifndef gcdINTERNAL_COMMENT
1100# define gcdINTERNAL_COMMENT 1
1101#endif
1102
1103/*
1104 gcdRTT_DISABLE_FC
1105
1106 Disable RTT FC support. For test only.
1107*/
1108#ifndef gcdRTT_DISABLE_FC
1109# define gcdRTT_DISABLE_FC 0
1110#endif
1111
1112/*
1113 gcdFORCE_MIPMAP
1114
1115 Force generate mipmap for texture.
1116*/
1117#ifndef gcdFORCE_MIPMAP
1118# define gcdFORCE_MIPMAP 0
1119#endif
1120
1121/*
1122 gcdFORCE_BILINEAR
1123
1124 Force bilinear for mipfilter.
1125*/
1126#ifndef gcdFORCE_BILINEAR
1127# define gcdFORCE_BILINEAR 1
1128#endif
1129
1130/*
1131 gcdBINARY_TRACE
1132
1133 When non-zero, binary trace will be generated.
1134
1135 When gcdBINARY_TRACE_FILE_SIZE is non-zero, binary trace buffer will
1136 be written to a file which size is limited to
1137 gcdBINARY_TRACE_FILE_SIZE.
1138*/
1139#ifndef gcdBINARY_TRACE
1140# define gcdBINARY_TRACE 0
1141# define gcdBINARY_TRACE_FILE_SIZE 0
1142#endif
1143
1144#ifndef gcdMOVG
1145# define gcdMOVG 0
1146# define gcdENABLE_TS_DOUBLE_BUFFER 1
1147#else
1148#if gcdMOVG
1149# define gcdENABLE_TS_DOUBLE_BUFFER 0
1150#else
1151# define gcdENABLE_TS_DOUBLE_BUFFER 1
1152#endif
1153#endif
1154
1155/* gcdINTERRUPT_STATISTIC
1156 *
1157 * Monitor the event send to GPU and interrupt issued by GPU.
1158 */
1159
1160#ifndef gcdINTERRUPT_STATISTIC
1161#if defined(LINUX)
1162# define gcdINTERRUPT_STATISTIC 1
1163#else
1164# define gcdINTERRUPT_STATISTIC 0
1165#endif
1166#endif
1167
1168/*
1169 gcdYINVERTED_RENDERING
1170 When it's not zero, we will rendering display buffer
1171 with top-bottom direction. All other offscreen rendering
1172 will be bottom-top, which follow OpenGL ES spec.
1173*/
1174#ifndef gcdYINVERTED_RENDERING
1175# define gcdYINVERTED_RENDERING 1
1176#endif
1177
1178#if gcdYINVERTED_RENDERING
1179/* disable unaligned linear composition adjust in Y-inverted rendering mode. */
1180# undef gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST
1181# define gcdANDROID_UNALIGNED_LINEAR_COMPOSITION_ADJUST 0
1182#endif
1183
1184/*
1185 gcdFENCE_WAIT_LOOP_COUNT
1186 Wait fence, loop count.
1187*/
1188#ifndef gcdFENCE_WAIT_LOOP_COUNT
1189# define gcdFENCE_WAIT_LOOP_COUNT 10000
1190#endif
1191
1192/*
1193 gcdHAL_3D_DRAWBLIT
1194 When it's not zero, we will enable HAL 3D drawblit
1195 to replace client 3dblit.
1196*/
1197#ifndef gcdHAL_3D_DRAWBLIT
1198# define gcdHAL_3D_DRAWBLIT 1
1199#endif
1200
1201/*
1202 gcdPARTIAL_FAST_CLEAR
1203 When it's not zero, partial fast clear is enabled.
1204 Depends on gcdHAL_3D_DRAWBLIT, if gcdHAL_3D_DRAWBLIT is not enabled,
1205 only available when scissor box is completely aligned.
1206 Expremental, under test.
1207*/
1208#ifndef gcdPARTIAL_FAST_CLEAR
1209# define gcdPARTIAL_FAST_CLEAR 1
1210#endif
1211
1212/*
1213 gcdREMOVE_SURF_ORIENTATION
1214 When it's not zero, we will remove surface orientation function.
1215 It wil become to a parameter of resolve function.
1216*/
1217#ifndef gcdREMOVE_SURF_ORIENTATION
1218# define gcdREMOVE_SURF_ORIENTATION 0
1219#endif
1220
1221/*
1222 gcdPATTERN_FAST_PATH
1223 For pattern match
1224*/
1225#ifndef gcdPATTERN_FAST_PATH
1226# define gcdPATTERN_FAST_PATH 1
1227#endif
1228
1229/*
1230 gcdUSE_INPUT_DEVICE
1231 disable input devices usage under fb mode to support fb+vdk multi-process
1232*/
1233#ifndef gcdUSE_INPUT_DEVICE
1234# define gcdUSE_INPUT_DEVICE 1
1235#endif
1236
1237/*
1238 gcdFRAMEINFO_STATISTIC
1239 When enable, collect frame information.
1240*/
1241#ifndef gcdFRAMEINFO_STATISTIC
1242
1243#if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG) || gcdDUMP
1244# define gcdFRAMEINFO_STATISTIC 1
1245#else
1246# define gcdFRAMEINFO_STATISTIC 0
1247#endif
1248
1249#endif
1250
1251/*
1252 gcdPACKED_OUTPUT_ADDRESS
1253 When it's not zero, ps output is already packed after linked
1254*/
1255#ifndef gcdPACKED_OUTPUT_ADDRESS
1256# define gcdPACKED_OUTPUT_ADDRESS 1
1257#endif
1258
1259/*
1260 gcdENABLE_THIRD_PARTY_OPERATION
1261 Enable third party operation like tpc or not.
1262 This macro can only be enabled by special customer.
1263*/
1264#ifndef gcdENABLE_THIRD_PARTY_OPERATION
1265# define gcdENABLE_THIRD_PARTY_OPERATION 0
1266#endif
1267
1268/*
1269 gcdENABLE_DEC_COMPRESSION
1270 Enable DEC TPC compression or not.
1271*/
1272#ifndef gcdENABLE_DEC_COMPRESSION
1273# define gcdENABLE_DEC_COMPRESSION 0
1274#ifndef gcdDEC_ENABLE_AHB
1275# define gcdDEC_ENABLE_AHB 0
1276#endif
1277#endif
1278
1279/*
1280 Core configurations. By default enable all cores.
1281*/
1282#ifndef gcdENABLE_3D
1283# define gcdENABLE_3D 1
1284#endif
1285
1286#ifndef gcdENABLE_2D
1287# define gcdENABLE_2D 1
1288#endif
1289
1290#ifndef gcdENABLE_VG
1291# define gcdENABLE_VG 0
1292#endif
1293
1294#ifndef gcdGC355_PROFILER
1295# define gcdGC355_PROFILER 0
1296#endif
1297
1298#ifndef gcdGC355_MEM_PRINT
1299# define gcdGC355_MEM_PRINT 0
1300#else
1301#if (!((gcdENABLE_3D == 0) && (gcdENABLE_2D == 0) && (gcdENABLE_VG == 1)))
1302# undef gcdGC355_MEM_PRINT
1303# define gcdGC355_MEM_PRINT 0
1304# endif
1305#endif
1306
1307#ifndef gcdENABLE_UNIFIED_CONSTANT
1308# define gcdENABLE_UNIFIED_CONSTANT 1
1309#endif
1310
1311/*
1312 gcdRECORD_COMMAND
1313*/
1314#ifndef gcdRECORD_COMMAND
1315# define gcdRECORD_COMMAND 0
1316#endif
1317
1318/*
1319 gcdALLOC_CMD_FROM_RESERVE
1320
1321 Provide a way by which location of command buffer can be
1322 specified. This is a DEBUG option to limit command buffer
1323 to some memory range.
1324*/
1325#ifndef gcdALLOC_CMD_FROM_RESERVE
1326# define gcdALLOC_CMD_FROM_RESERVE 0
1327#endif
1328
1329#endif /* __gc_hal_options_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_profiler.h b/src/hal/kernel/inc/gc_hal_profiler.h
new file mode 100755
index 0000000..fee3c31
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_profiler.h
@@ -0,0 +1,619 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_profiler_h_
57#define __gc_hal_profiler_h_
58
59#if VIVANTE_PROFILER_NEW
60#include "gc_hal_engine.h"
61#endif
62
63#ifdef __cplusplus
64extern "C" {
65#endif
66
67#define GLVERTEX_OBJECT 10
68#define GLVERTEX_OBJECT_BYTES 11
69
70#define GLINDEX_OBJECT 20
71#define GLINDEX_OBJECT_BYTES 21
72
73#define GLTEXTURE_OBJECT 30
74#define GLTEXTURE_OBJECT_BYTES 31
75
76#define GLBUFOBJ_OBJECT 40
77#define GLBUFOBJ_OBJECT_BYTES 41
78
79#if VIVANTE_PROFILER
80#define gcmPROFILE_GC(Enum, Value) gcoPROFILER_Count(gcvNULL, Enum, Value)
81#else
82#define gcmPROFILE_GC(Enum, Value) do { } while (gcvFALSE)
83#endif
84
85#ifndef gcdNEW_PROFILER_FILE
86#define gcdNEW_PROFILER_FILE 1
87#endif
88
89#define ES11_CALLS 151
90#define ES11_DRAWCALLS (ES11_CALLS + 1)
91#define ES11_STATECHANGECALLS (ES11_DRAWCALLS + 1)
92#define ES11_POINTCOUNT (ES11_STATECHANGECALLS + 1)
93#define ES11_LINECOUNT (ES11_POINTCOUNT + 1)
94#define ES11_TRIANGLECOUNT (ES11_LINECOUNT + 1)
95
96#define ES30_CALLS 159
97#define ES30_DRAWCALLS (ES30_CALLS + 1)
98#define ES30_STATECHANGECALLS (ES30_DRAWCALLS + 1)
99#define ES30_POINTCOUNT (ES30_STATECHANGECALLS + 1)
100#define ES30_LINECOUNT (ES30_POINTCOUNT + 1)
101#define ES30_TRIANGLECOUNT (ES30_LINECOUNT + 1)
102
103#define VG11_CALLS 88
104#define VG11_DRAWCALLS (VG11_CALLS + 1)
105#define VG11_STATECHANGECALLS (VG11_DRAWCALLS + 1)
106#define VG11_FILLCOUNT (VG11_STATECHANGECALLS + 1)
107#define VG11_STROKECOUNT (VG11_FILLCOUNT + 1)
108/* End of Driver API ID Definitions. */
109
110/* HAL & MISC IDs. */
111#define HAL_VERTBUFNEWBYTEALLOC 1
112#define HAL_VERTBUFTOTALBYTEALLOC (HAL_VERTBUFNEWBYTEALLOC + 1)
113#define HAL_VERTBUFNEWOBJALLOC (HAL_VERTBUFTOTALBYTEALLOC + 1)
114#define HAL_VERTBUFTOTALOBJALLOC (HAL_VERTBUFNEWOBJALLOC + 1)
115#define HAL_INDBUFNEWBYTEALLOC (HAL_VERTBUFTOTALOBJALLOC + 1)
116#define HAL_INDBUFTOTALBYTEALLOC (HAL_INDBUFNEWBYTEALLOC + 1)
117#define HAL_INDBUFNEWOBJALLOC (HAL_INDBUFTOTALBYTEALLOC + 1)
118#define HAL_INDBUFTOTALOBJALLOC (HAL_INDBUFNEWOBJALLOC + 1)
119#define HAL_TEXBUFNEWBYTEALLOC (HAL_INDBUFTOTALOBJALLOC + 1)
120#define HAL_TEXBUFTOTALBYTEALLOC (HAL_TEXBUFNEWBYTEALLOC + 1)
121#define HAL_TEXBUFNEWOBJALLOC (HAL_TEXBUFTOTALBYTEALLOC + 1)
122#define HAL_TEXBUFTOTALOBJALLOC (HAL_TEXBUFNEWOBJALLOC + 1)
123
124#define GPU_CYCLES 1
125#define GPU_READ64BYTE (GPU_CYCLES + 1)
126#define GPU_WRITE64BYTE (GPU_READ64BYTE + 1)
127#define GPU_TOTALCYCLES (GPU_WRITE64BYTE + 1)
128#define GPU_IDLECYCLES (GPU_TOTALCYCLES + 1)
129
130#define VS_INSTCOUNT 1
131#define VS_BRANCHINSTCOUNT (VS_INSTCOUNT + 1)
132#define VS_TEXLDINSTCOUNT (VS_BRANCHINSTCOUNT + 1)
133#define VS_RENDEREDVERTCOUNT (VS_TEXLDINSTCOUNT + 1)
134#define VS_SOURCE (VS_RENDEREDVERTCOUNT + 1)
135
136#define PS_INSTCOUNT 1
137#define PS_BRANCHINSTCOUNT (PS_INSTCOUNT + 1)
138#define PS_TEXLDINSTCOUNT (PS_BRANCHINSTCOUNT + 1)
139#define PS_RENDEREDPIXCOUNT (PS_TEXLDINSTCOUNT + 1)
140#define PS_SOURCE (PS_RENDEREDPIXCOUNT + 1)
141
142#define PA_INVERTCOUNT 1
143#define PA_INPRIMCOUNT (PA_INVERTCOUNT + 1)
144#define PA_OUTPRIMCOUNT (PA_INPRIMCOUNT + 1)
145#define PA_DEPTHCLIPCOUNT (PA_OUTPRIMCOUNT + 1)
146#define PA_TRIVIALREJCOUNT (PA_DEPTHCLIPCOUNT + 1)
147#define PA_CULLCOUNT (PA_TRIVIALREJCOUNT + 1)
148
149#define SE_TRIANGLECOUNT 1
150#define SE_LINECOUNT (SE_TRIANGLECOUNT + 1)
151
152#define RA_VALIDPIXCOUNT 1
153#define RA_TOTALQUADCOUNT (RA_VALIDPIXCOUNT + 1)
154#define RA_VALIDQUADCOUNTEZ (RA_TOTALQUADCOUNT + 1)
155#define RA_TOTALPRIMCOUNT (RA_VALIDQUADCOUNTEZ + 1)
156#define RA_PIPECACHEMISSCOUNT (RA_TOTALPRIMCOUNT + 1)
157#define RA_PREFCACHEMISSCOUNT (RA_PIPECACHEMISSCOUNT + 1)
158#define RA_EEZCULLCOUNT (RA_PREFCACHEMISSCOUNT + 1)
159
160#define TX_TOTBILINEARREQ 1
161#define TX_TOTTRILINEARREQ (TX_TOTBILINEARREQ + 1)
162#define TX_TOTDISCARDTEXREQ (TX_TOTTRILINEARREQ + 1)
163#define TX_TOTTEXREQ (TX_TOTDISCARDTEXREQ + 1)
164#define TX_MEMREADCOUNT (TX_TOTTEXREQ + 1)
165#define TX_MEMREADIN8BCOUNT (TX_MEMREADCOUNT + 1)
166#define TX_CACHEMISSCOUNT (TX_MEMREADIN8BCOUNT + 1)
167#define TX_CACHEHITTEXELCOUNT (TX_CACHEMISSCOUNT + 1)
168#define TX_CACHEMISSTEXELCOUNT (TX_CACHEHITTEXELCOUNT + 1)
169
170#define PE_KILLEDBYCOLOR 1
171#define PE_KILLEDBYDEPTH (PE_KILLEDBYCOLOR + 1)
172#define PE_DRAWNBYCOLOR (PE_KILLEDBYDEPTH + 1)
173#define PE_DRAWNBYDEPTH (PE_DRAWNBYCOLOR + 1)
174
175#define MC_READREQ8BPIPE 1
176#define MC_READREQ8BIP (MC_READREQ8BPIPE + 1)
177#define MC_WRITEREQ8BPIPE (MC_READREQ8BIP + 1)
178
179#define AXI_READREQSTALLED 1
180#define AXI_WRITEREQSTALLED (AXI_READREQSTALLED + 1)
181#define AXI_WRITEDATASTALLED (AXI_WRITEREQSTALLED + 1)
182
183#define PVS_INSTRCOUNT 1
184#define PVS_ALUINSTRCOUNT (PVS_INSTRCOUNT + 1)
185#define PVS_TEXINSTRCOUNT (PVS_ALUINSTRCOUNT + 1)
186#define PVS_ATTRIBCOUNT (PVS_TEXINSTRCOUNT + 1)
187#define PVS_UNIFORMCOUNT (PVS_ATTRIBCOUNT + 1)
188#define PVS_FUNCTIONCOUNT (PVS_UNIFORMCOUNT + 1)
189#define PVS_SOURCE (PVS_FUNCTIONCOUNT + 1)
190
191#define PPS_INSTRCOUNT 1
192#define PPS_ALUINSTRCOUNT (PPS_INSTRCOUNT + 1)
193#define PPS_TEXINSTRCOUNT (PPS_ALUINSTRCOUNT + 1)
194#define PPS_ATTRIBCOUNT (PPS_TEXINSTRCOUNT + 1)
195#define PPS_UNIFORMCOUNT (PPS_ATTRIBCOUNT + 1)
196#define PPS_FUNCTIONCOUNT (PPS_UNIFORMCOUNT + 1)
197#define PPS_SOURCE (PPS_FUNCTIONCOUNT + 1)
198/* End of MISC Counter IDs. */
199
200#ifdef gcdNEW_PROFILER_FILE
201
202/* Category Constants. */
203#define VPHEADER 0x010000
204#define VPG_INFO 0x020000
205#define VPG_TIME 0x030000
206#define VPG_MEM 0x040000
207#define VPG_ES11 0x050000
208#define VPG_ES30 0x060000
209#define VPG_VG11 0x070000
210#define VPG_HAL 0x080000
211#define VPG_HW 0x090000
212#define VPG_GPU 0x0a0000
213#define VPG_VS 0x0b0000
214#define VPG_PS 0x0c0000
215#define VPG_PA 0x0d0000
216#define VPG_SETUP 0x0e0000
217#define VPG_RA 0x0f0000
218#define VPG_TX 0x100000
219#define VPG_PE 0x110000
220#define VPG_MC 0x120000
221#define VPG_AXI 0x130000
222#define VPG_PROG 0x140000
223#define VPG_PVS 0x150000
224#define VPG_PPS 0x160000
225#define VPG_ES11_TIME 0x170000
226#define VPG_ES30_TIME 0x180000
227#define VPG_FRAME 0x190000
228#define VPG_ES11_DRAW 0x200000
229#define VPG_ES30_DRAW 0x210000
230#define VPG_VG11_TIME 0x220000
231#define VPG_END 0xff0000
232
233/* Info. */
234#define VPC_INFOCOMPANY (VPG_INFO + 1)
235#define VPC_INFOVERSION (VPC_INFOCOMPANY + 1)
236#define VPC_INFORENDERER (VPC_INFOVERSION + 1)
237#define VPC_INFOREVISION (VPC_INFORENDERER + 1)
238#define VPC_INFODRIVER (VPC_INFOREVISION + 1)
239#define VPC_INFODRIVERMODE (VPC_INFODRIVER + 1)
240#define VPC_INFOSCREENSIZE (VPC_INFODRIVERMODE + 1)
241
242/* Counter Constants. */
243#define VPC_ELAPSETIME (VPG_TIME + 1)
244#define VPC_CPUTIME (VPC_ELAPSETIME + 1)
245
246#define VPC_MEMMAXRES (VPG_MEM + 1)
247#define VPC_MEMSHARED (VPC_MEMMAXRES + 1)
248#define VPC_MEMUNSHAREDDATA (VPC_MEMSHARED + 1)
249#define VPC_MEMUNSHAREDSTACK (VPC_MEMUNSHAREDDATA + 1)
250
251/* OpenGL ES11 Statics Counter IDs. */
252#define VPC_ES11CALLS (VPG_ES11 + ES11_CALLS)
253#define VPC_ES11DRAWCALLS (VPG_ES11 + ES11_DRAWCALLS)
254#define VPC_ES11STATECHANGECALLS (VPG_ES11 + ES11_STATECHANGECALLS)
255#define VPC_ES11POINTCOUNT (VPG_ES11 + ES11_POINTCOUNT)
256#define VPC_ES11LINECOUNT (VPG_ES11 + ES11_LINECOUNT)
257#define VPC_ES11TRIANGLECOUNT (VPG_ES11 + ES11_TRIANGLECOUNT)
258
259/* OpenGL ES30 Statistics Counter IDs. */
260#define VPC_ES30CALLS (VPG_ES30 + ES30_CALLS)
261#define VPC_ES30DRAWCALLS (VPG_ES30 + ES30_DRAWCALLS)
262#define VPC_ES30STATECHANGECALLS (VPG_ES30 + ES30_STATECHANGECALLS)
263#define VPC_ES30POINTCOUNT (VPG_ES30 + ES30_POINTCOUNT)
264#define VPC_ES30LINECOUNT (VPG_ES30 + ES30_LINECOUNT)
265#define VPC_ES30TRIANGLECOUNT (VPG_ES30 + ES30_TRIANGLECOUNT)
266
267/* OpenVG Statistics Counter IDs. */
268#define VPC_VG11CALLS (VPG_VG11 + VG11_CALLS)
269#define VPC_VG11DRAWCALLS (VPG_VG11 + VG11_DRAWCALLS)
270#define VPC_VG11STATECHANGECALLS (VPG_VG11 + VG11_STATECHANGECALLS)
271#define VPC_VG11FILLCOUNT (VPG_VG11 + VG11_FILLCOUNT)
272#define VPC_VG11STROKECOUNT (VPG_VG11 + VG11_STROKECOUNT)
273
274/* HAL Counters. */
275#define VPC_HALVERTBUFNEWBYTEALLOC (VPG_HAL + HAL_VERTBUFNEWBYTEALLOC)
276#define VPC_HALVERTBUFTOTALBYTEALLOC (VPG_HAL + HAL_VERTBUFTOTALBYTEALLOC)
277#define VPC_HALVERTBUFNEWOBJALLOC (VPG_HAL + HAL_VERTBUFNEWOBJALLOC)
278#define VPC_HALVERTBUFTOTALOBJALLOC (VPG_HAL + HAL_VERTBUFTOTALOBJALLOC)
279#define VPC_HALINDBUFNEWBYTEALLOC (VPG_HAL + HAL_INDBUFNEWBYTEALLOC)
280#define VPC_HALINDBUFTOTALBYTEALLOC (VPG_HAL + HAL_INDBUFTOTALBYTEALLOC)
281#define VPC_HALINDBUFNEWOBJALLOC (VPG_HAL + HAL_INDBUFNEWOBJALLOC)
282#define VPC_HALINDBUFTOTALOBJALLOC (VPG_HAL + HAL_INDBUFTOTALOBJALLOC)
283#define VPC_HALTEXBUFNEWBYTEALLOC (VPG_HAL + HAL_TEXBUFNEWBYTEALLOC)
284#define VPC_HALTEXBUFTOTALBYTEALLOC (VPG_HAL + HAL_TEXBUFTOTALBYTEALLOC)
285#define VPC_HALTEXBUFNEWOBJALLOC (VPG_HAL + HAL_TEXBUFNEWOBJALLOC)
286#define VPC_HALTEXBUFTOTALOBJALLOC (VPG_HAL + HAL_TEXBUFTOTALOBJALLOC)
287
288/* HW: GPU Counters. */
289#define VPC_GPUCYCLES (VPG_GPU + GPU_CYCLES)
290#define VPC_GPUREAD64BYTE (VPG_GPU + GPU_READ64BYTE)
291#define VPC_GPUWRITE64BYTE (VPG_GPU + GPU_WRITE64BYTE)
292#define VPC_GPUTOTALCYCLES (VPG_GPU + GPU_TOTALCYCLES)
293#define VPC_GPUIDLECYCLES (VPG_GPU + GPU_IDLECYCLES)
294
295/* HW: Shader Counters. */
296#define VPC_VSINSTCOUNT (VPG_VS + VS_INSTCOUNT)
297#define VPC_VSBRANCHINSTCOUNT (VPG_VS + VS_BRANCHINSTCOUNT)
298#define VPC_VSTEXLDINSTCOUNT (VPG_VS + VS_TEXLDINSTCOUNT)
299#define VPC_VSRENDEREDVERTCOUNT (VPG_VS + VS_RENDEREDVERTCOUNT)
300/* HW: PS Count. */
301#define VPC_PSINSTCOUNT (VPG_PS + PS_INSTCOUNT)
302#define VPC_PSBRANCHINSTCOUNT (VPG_PS + PS_BRANCHINSTCOUNT)
303#define VPC_PSTEXLDINSTCOUNT (VPG_PS + PS_TEXLDINSTCOUNT)
304#define VPC_PSRENDEREDPIXCOUNT (VPG_PS + PS_RENDEREDPIXCOUNT)
305
306
307/* HW: PA Counters. */
308#define VPC_PAINVERTCOUNT (VPG_PA + PA_INVERTCOUNT)
309#define VPC_PAINPRIMCOUNT (VPG_PA + PA_INPRIMCOUNT)
310#define VPC_PAOUTPRIMCOUNT (VPG_PA + PA_OUTPRIMCOUNT)
311#define VPC_PADEPTHCLIPCOUNT (VPG_PA + PA_DEPTHCLIPCOUNT)
312#define VPC_PATRIVIALREJCOUNT (VPG_PA + PA_TRIVIALREJCOUNT)
313#define VPC_PACULLCOUNT (VPG_PA + PA_CULLCOUNT)
314
315/* HW: Setup Counters. */
316#define VPC_SETRIANGLECOUNT (VPG_SETUP + SE_TRIANGLECOUNT)
317#define VPC_SELINECOUNT (VPG_SETUP + SE_LINECOUNT)
318
319/* HW: RA Counters. */
320#define VPC_RAVALIDPIXCOUNT (VPG_RA + RA_VALIDPIXCOUNT)
321#define VPC_RATOTALQUADCOUNT (VPG_RA + RA_TOTALQUADCOUNT)
322#define VPC_RAVALIDQUADCOUNTEZ (VPG_RA + RA_VALIDQUADCOUNTEZ)
323#define VPC_RATOTALPRIMCOUNT (VPG_RA + RA_TOTALPRIMCOUNT)
324#define VPC_RAPIPECACHEMISSCOUNT (VPG_RA + RA_PIPECACHEMISSCOUNT)
325#define VPC_RAPREFCACHEMISSCOUNT (VPG_RA + RA_PREFCACHEMISSCOUNT)
326#define VPC_RAEEZCULLCOUNT (VPG_RA + RA_EEZCULLCOUNT)
327
328/* HW: TEX Counters. */
329#define VPC_TXTOTBILINEARREQ (VPG_TX + TX_TOTBILINEARREQ)
330#define VPC_TXTOTTRILINEARREQ (VPG_TX + TX_TOTTRILINEARREQ)
331#define VPC_TXTOTDISCARDTEXREQ (VPG_TX + TX_TOTDISCARDTEXREQ)
332#define VPC_TXTOTTEXREQ (VPG_TX + TX_TOTTEXREQ)
333#define VPC_TXMEMREADCOUNT (VPG_TX + TX_MEMREADCOUNT)
334#define VPC_TXMEMREADIN8BCOUNT (VPG_TX + TX_MEMREADIN8BCOUNT)
335#define VPC_TXCACHEMISSCOUNT (VPG_TX + TX_CACHEMISSCOUNT)
336#define VPC_TXCACHEHITTEXELCOUNT (VPG_TX + TX_CACHEHITTEXELCOUNT)
337#define VPC_TXCACHEMISSTEXELCOUNT (VPG_TX + TX_CACHEMISSTEXELCOUNT)
338
339/* HW: PE Counters. */
340#define VPC_PEKILLEDBYCOLOR (VPG_PE + PE_KILLEDBYCOLOR)
341#define VPC_PEKILLEDBYDEPTH (VPG_PE + PE_KILLEDBYDEPTH)
342#define VPC_PEDRAWNBYCOLOR (VPG_PE + PE_DRAWNBYCOLOR)
343#define VPC_PEDRAWNBYDEPTH (VPG_PE + PE_DRAWNBYDEPTH)
344
345/* HW: MC Counters. */
346#define VPC_MCREADREQ8BPIPE (VPG_MC + MC_READREQ8BPIPE)
347#define VPC_MCREADREQ8BIP (VPG_MC + MC_READREQ8BIP)
348#define VPC_MCWRITEREQ8BPIPE (VPG_MC + MC_WRITEREQ8BPIPE)
349
350/* HW: AXI Counters. */
351#define VPC_AXIREADREQSTALLED (VPG_AXI + AXI_READREQSTALLED)
352#define VPC_AXIWRITEREQSTALLED (VPG_AXI + AXI_WRITEREQSTALLED)
353#define VPC_AXIWRITEDATASTALLED (VPG_AXI + AXI_WRITEDATASTALLED)
354
355/* PROGRAM: Shader program counters. */
356#define VPC_PVSINSTRCOUNT (VPG_PVS + PVS_INSTRCOUNT)
357#define VPC_PVSALUINSTRCOUNT (VPG_PVS + PVS_ALUINSTRCOUNT)
358#define VPC_PVSTEXINSTRCOUNT (VPG_PVS + PVS_TEXINSTRCOUNT)
359#define VPC_PVSATTRIBCOUNT (VPG_PVS + PVS_ATTRIBCOUNT)
360#define VPC_PVSUNIFORMCOUNT (VPG_PVS + PVS_UNIFORMCOUNT)
361#define VPC_PVSFUNCTIONCOUNT (VPG_PVS + PVS_FUNCTIONCOUNT)
362#define VPC_PVSSOURCE (VPG_PVS + PVS_SOURCE)
363
364#define VPC_PPSINSTRCOUNT (VPG_PPS + PPS_INSTRCOUNT)
365#define VPC_PPSALUINSTRCOUNT (VPG_PPS + PPS_ALUINSTRCOUNT)
366#define VPC_PPSTEXINSTRCOUNT (VPG_PPS + PPS_TEXINSTRCOUNT)
367#define VPC_PPSATTRIBCOUNT (VPG_PPS + PPS_ATTRIBCOUNT)
368#define VPC_PPSUNIFORMCOUNT (VPG_PPS + PPS_UNIFORMCOUNT)
369#define VPC_PPSFUNCTIONCOUNT (VPG_PPS + PPS_FUNCTIONCOUNT)
370#define VPC_PPSSOURCE (VPG_PPS + PPS_SOURCE)
371
372#define VPC_PROGRAMHANDLE (VPG_PROG + 1)
373
374#define VPC_ES30_DRAW_NO (VPG_ES30_DRAW + 1)
375#define VPC_ES11_DRAW_NO (VPG_ES11_DRAW + 1)
376#endif
377
378
379/* HW profile information. */
380typedef struct _gcsPROFILER_COUNTERS
381{
382 /* HW static counters. */
383 gctUINT32 gpuClock;
384 gctUINT32 axiClock;
385 gctUINT32 shaderClock;
386
387 /* HW vairable counters. */
388 gctUINT32 gpuClockStart;
389 gctUINT32 gpuClockEnd;
390
391 /* HW vairable counters. */
392 gctUINT32 gpuCyclesCounter;
393 gctUINT32 gpuTotalCyclesCounter;
394 gctUINT32 gpuIdleCyclesCounter;
395 gctUINT32 gpuTotalRead64BytesPerFrame;
396 gctUINT32 gpuTotalWrite64BytesPerFrame;
397
398 /* PE */
399 gctUINT32 pe_pixel_count_killed_by_color_pipe;
400 gctUINT32 pe_pixel_count_killed_by_depth_pipe;
401 gctUINT32 pe_pixel_count_drawn_by_color_pipe;
402 gctUINT32 pe_pixel_count_drawn_by_depth_pipe;
403
404 /* SH */
405 gctUINT32 ps_inst_counter;
406 gctUINT32 rendered_pixel_counter;
407 gctUINT32 vs_inst_counter;
408 gctUINT32 rendered_vertice_counter;
409 gctUINT32 vtx_branch_inst_counter;
410 gctUINT32 vtx_texld_inst_counter;
411 gctUINT32 pxl_branch_inst_counter;
412 gctUINT32 pxl_texld_inst_counter;
413
414 /* PA */
415 gctUINT32 pa_input_vtx_counter;
416 gctUINT32 pa_input_prim_counter;
417 gctUINT32 pa_output_prim_counter;
418 gctUINT32 pa_depth_clipped_counter;
419 gctUINT32 pa_trivial_rejected_counter;
420 gctUINT32 pa_culled_counter;
421
422 /* SE */
423 gctUINT32 se_culled_triangle_count;
424 gctUINT32 se_culled_lines_count;
425
426 /* RA */
427 gctUINT32 ra_valid_pixel_count;
428 gctUINT32 ra_total_quad_count;
429 gctUINT32 ra_valid_quad_count_after_early_z;
430 gctUINT32 ra_total_primitive_count;
431 gctUINT32 ra_pipe_cache_miss_counter;
432 gctUINT32 ra_prefetch_cache_miss_counter;
433 gctUINT32 ra_eez_culled_counter;
434
435 /* TX */
436 gctUINT32 tx_total_bilinear_requests;
437 gctUINT32 tx_total_trilinear_requests;
438 gctUINT32 tx_total_discarded_texture_requests;
439 gctUINT32 tx_total_texture_requests;
440 gctUINT32 tx_mem_read_count;
441 gctUINT32 tx_mem_read_in_8B_count;
442 gctUINT32 tx_cache_miss_count;
443 gctUINT32 tx_cache_hit_texel_count;
444 gctUINT32 tx_cache_miss_texel_count;
445
446 /* MC */
447 gctUINT32 mc_total_read_req_8B_from_pipeline;
448 gctUINT32 mc_total_read_req_8B_from_IP;
449 gctUINT32 mc_total_write_req_8B_from_pipeline;
450
451 /* HI */
452 gctUINT32 hi_axi_cycles_read_request_stalled;
453 gctUINT32 hi_axi_cycles_write_request_stalled;
454 gctUINT32 hi_axi_cycles_write_data_stalled;
455}
456gcsPROFILER_COUNTERS;
457
458#if VIVANTE_PROFILER_NEW
459#define NumOfDrawBuf 64
460#endif
461
462/* HAL profile information. */
463typedef struct _gcsPROFILER
464{
465 gctUINT32 enable;
466 gctBOOL enableHal;
467 gctBOOL enableHW;
468 gctBOOL enableSH;
469 gctBOOL isSyncMode;
470 gctBOOL disableOutputCounter;
471
472 gctBOOL useSocket;
473 gctINT sockFd;
474
475 gctFILE file;
476
477 /* Aggregate Information */
478
479 /* Clock Info */
480 gctUINT64 frameStart;
481 gctUINT64 frameEnd;
482
483 /* Current frame information */
484 gctUINT32 frameNumber;
485 gctUINT64 frameStartTimeusec;
486 gctUINT64 frameEndTimeusec;
487 gctUINT64 frameStartCPUTimeusec;
488 gctUINT64 frameEndCPUTimeusec;
489
490#if PROFILE_HAL_COUNTERS
491 gctUINT32 vertexBufferTotalBytesAlloc;
492 gctUINT32 vertexBufferNewBytesAlloc;
493 int vertexBufferTotalObjectsAlloc;
494 int vertexBufferNewObjectsAlloc;
495
496 gctUINT32 indexBufferTotalBytesAlloc;
497 gctUINT32 indexBufferNewBytesAlloc;
498 int indexBufferTotalObjectsAlloc;
499 int indexBufferNewObjectsAlloc;
500
501 gctUINT32 textureBufferTotalBytesAlloc;
502 gctUINT32 textureBufferNewBytesAlloc;
503 int textureBufferTotalObjectsAlloc;
504 int textureBufferNewObjectsAlloc;
505
506 gctUINT32 numCommits;
507 gctUINT32 drawPointCount;
508 gctUINT32 drawLineCount;
509 gctUINT32 drawTriangleCount;
510 gctUINT32 drawVertexCount;
511 gctUINT32 redundantStateChangeCalls;
512#endif
513
514 gctUINT32 prevVSInstCount;
515 gctUINT32 prevVSBranchInstCount;
516 gctUINT32 prevVSTexInstCount;
517 gctUINT32 prevVSVertexCount;
518 gctUINT32 prevPSInstCount;
519 gctUINT32 prevPSBranchInstCount;
520 gctUINT32 prevPSTexInstCount;
521 gctUINT32 prevPSPixelCount;
522
523#if VIVANTE_PROFILER_NEW
524 gcoBUFOBJ newCounterBuf[NumOfDrawBuf];
525 gctUINT32 curBufId;
526#endif
527
528}
529gcsPROFILER;
530
531/* Memory profile information. */
532struct _gcsMemProfile
533{
534 /* Memory Usage */
535 gctUINT32 videoMemUsed;
536 gctUINT32 systemMemUsed;
537 gctUINT32 commitBufferSize;
538 gctUINT32 contextBufferCopyBytes;
539};
540
541/* Shader profile information. */
542struct _gcsSHADER_PROFILER
543{
544 gctUINT32 shaderLength;
545 gctUINT32 shaderALUCycles;
546 gctUINT32 shaderTexLoadCycles;
547 gctUINT32 shaderTempRegCount;
548 gctUINT32 shaderSamplerRegCount;
549 gctUINT32 shaderInputRegCount;
550 gctUINT32 shaderOutputRegCount;
551};
552
553/* Initialize the gcsProfiler. */
554gceSTATUS
555gcoPROFILER_Initialize(
556 IN gcoHAL Hal,
557 IN gctBOOL Enable
558 );
559
560/* Destroy the gcProfiler. */
561gceSTATUS
562gcoPROFILER_Destroy(
563 IN gcoHAL Hal
564 );
565
566/* Write data to profiler. */
567gceSTATUS
568gcoPROFILER_Write(
569 IN gcoHAL Hal,
570 IN gctSIZE_T ByteCount,
571 IN gctCONST_POINTER Data
572 );
573
574/* Flush data out. */
575gceSTATUS
576gcoPROFILER_Flush(
577 IN gcoHAL Hal
578 );
579
580/* Call to signal end of frame. */
581gceSTATUS
582gcoPROFILER_EndFrame(
583 IN gcoHAL Hal
584 );
585
586/* Call to signal end of draw. */
587gceSTATUS
588gcoPROFILER_EndDraw(
589 IN gcoHAL Hal,
590 IN gctBOOL FirstDraw
591 );
592
593/* Increase profile counter Enum by Value. */
594gceSTATUS
595gcoPROFILER_Count(
596 IN gcoHAL Hal,
597 IN gctUINT32 Enum,
598 IN gctINT Value
599 );
600
601/* Profile input vertex shader. */
602gceSTATUS
603gcoPROFILER_ShaderVS(
604 IN gcoHAL Hal,
605 IN gctPOINTER Vs
606 );
607
608/* Profile input fragment shader. */
609gceSTATUS
610gcoPROFILER_ShaderFS(
611 IN gcoHAL Hal,
612 IN gctPOINTER Fs
613 );
614
615#ifdef __cplusplus
616}
617#endif
618
619#endif /* __gc_hal_profiler_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_raster.h b/src/hal/kernel/inc/gc_hal_raster.h
new file mode 100755
index 0000000..03d170f
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_raster.h
@@ -0,0 +1,1078 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_raster_h_
57#define __gc_hal_raster_h_
58
59#include "gc_hal_enum.h"
60#include "gc_hal_types.h"
61
62#ifdef __cplusplus
63extern "C" {
64#endif
65
66/******************************************************************************\
67****************************** Object Declarations *****************************
68\******************************************************************************/
69
70typedef struct _gcoBRUSH * gcoBRUSH;
71typedef struct _gcoBRUSH_CACHE * gcoBRUSH_CACHE;
72
73/******************************************************************************\
74******************************** gcoBRUSH Object *******************************
75\******************************************************************************/
76
77/* Create a new solid color gcoBRUSH object. */
78gceSTATUS
79gcoBRUSH_ConstructSingleColor(
80 IN gcoHAL Hal,
81 IN gctUINT32 ColorConvert,
82 IN gctUINT32 Color,
83 IN gctUINT64 Mask,
84 gcoBRUSH * Brush
85 );
86
87/* Create a new monochrome gcoBRUSH object. */
88gceSTATUS
89gcoBRUSH_ConstructMonochrome(
90 IN gcoHAL Hal,
91 IN gctUINT32 OriginX,
92 IN gctUINT32 OriginY,
93 IN gctUINT32 ColorConvert,
94 IN gctUINT32 FgColor,
95 IN gctUINT32 BgColor,
96 IN gctUINT64 Bits,
97 IN gctUINT64 Mask,
98 gcoBRUSH * Brush
99 );
100
101/* Create a color gcoBRUSH object. */
102gceSTATUS
103gcoBRUSH_ConstructColor(
104 IN gcoHAL Hal,
105 IN gctUINT32 OriginX,
106 IN gctUINT32 OriginY,
107 IN gctPOINTER Address,
108 IN gceSURF_FORMAT Format,
109 IN gctUINT64 Mask,
110 gcoBRUSH * Brush
111 );
112
113/* Destroy an gcoBRUSH object. */
114gceSTATUS
115gcoBRUSH_Destroy(
116 IN gcoBRUSH Brush
117 );
118
119/******************************************************************************\
120******************************** gcoSURF Object *******************************
121\******************************************************************************/
122
123/* Set cipping rectangle. */
124gceSTATUS
125gcoSURF_SetClipping(
126 IN gcoSURF Surface
127 );
128
129/* Clear one or more rectangular areas. */
130gceSTATUS
131gcoSURF_Clear2D(
132 IN gcoSURF DestSurface,
133 IN gctUINT32 RectCount,
134 IN gcsRECT_PTR DestRect,
135 IN gctUINT32 LoColor,
136 IN gctUINT32 HiColor
137 );
138
139/* Draw one or more Bresenham lines. */
140gceSTATUS
141gcoSURF_Line(
142 IN gcoSURF Surface,
143 IN gctUINT32 LineCount,
144 IN gcsRECT_PTR Position,
145 IN gcoBRUSH Brush,
146 IN gctUINT8 FgRop,
147 IN gctUINT8 BgRop
148 );
149
150/* Generic rectangular blit. */
151gceSTATUS
152gcoSURF_Blit(
153 IN OPTIONAL gcoSURF SrcSurface,
154 IN gcoSURF DestSurface,
155 IN gctUINT32 RectCount,
156 IN OPTIONAL gcsRECT_PTR SrcRect,
157 IN gcsRECT_PTR DestRect,
158 IN OPTIONAL gcoBRUSH Brush,
159 IN gctUINT8 FgRop,
160 IN gctUINT8 BgRop,
161 IN OPTIONAL gceSURF_TRANSPARENCY Transparency,
162 IN OPTIONAL gctUINT32 TransparencyColor,
163 IN OPTIONAL gctPOINTER Mask,
164 IN OPTIONAL gceSURF_MONOPACK MaskPack
165 );
166
167/* Monochrome blit. */
168gceSTATUS
169gcoSURF_MonoBlit(
170 IN gcoSURF DestSurface,
171 IN gctPOINTER Source,
172 IN gceSURF_MONOPACK SourcePack,
173 IN gcsPOINT_PTR SourceSize,
174 IN gcsPOINT_PTR SourceOrigin,
175 IN gcsRECT_PTR DestRect,
176 IN OPTIONAL gcoBRUSH Brush,
177 IN gctUINT8 FgRop,
178 IN gctUINT8 BgRop,
179 IN gctBOOL ColorConvert,
180 IN gctUINT8 MonoTransparency,
181 IN gceSURF_TRANSPARENCY Transparency,
182 IN gctUINT32 FgColor,
183 IN gctUINT32 BgColor
184 );
185
186/* Filter blit. */
187gceSTATUS
188gcoSURF_FilterBlit(
189 IN gcoSURF SrcSurface,
190 IN gcoSURF DestSurface,
191 IN gcsRECT_PTR SrcRect,
192 IN gcsRECT_PTR DestRect,
193 IN gcsRECT_PTR DestSubRect
194 );
195
196/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
197gceSTATUS
198gcoSURF_EnableAlphaBlend(
199 IN gcoSURF Surface,
200 IN gctUINT8 SrcGlobalAlphaValue,
201 IN gctUINT8 DstGlobalAlphaValue,
202 IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
203 IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
204 IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
205 IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
206 IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
207 IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
208 IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
209 IN gceSURF_PIXEL_COLOR_MODE DstColorMode
210 );
211
212/* Disable alpha blending engine in the hardware and engage the ROP engine. */
213gceSTATUS
214gcoSURF_DisableAlphaBlend(
215 IN gcoSURF Surface
216 );
217
218/* Copy a rectangular area with format conversion. */
219gceSTATUS
220gcoSURF_CopyPixels(
221 IN gcoSURF Source,
222 IN gcoSURF Target,
223 IN gctINT SourceX,
224 IN gctINT SourceY,
225 IN gctINT TargetX,
226 IN gctINT TargetY,
227 IN gctINT Width,
228 IN gctINT Height
229 );
230
231/* Read surface pixel. */
232gceSTATUS
233gcoSURF_ReadPixel(
234 IN gcoSURF Surface,
235 IN gctPOINTER Memory,
236 IN gctINT X,
237 IN gctINT Y,
238 IN gceSURF_FORMAT Format,
239 OUT gctPOINTER PixelValue
240 );
241
242/* Write surface pixel. */
243gceSTATUS
244gcoSURF_WritePixel(
245 IN gcoSURF Surface,
246 IN gctPOINTER Memory,
247 IN gctINT X,
248 IN gctINT Y,
249 IN gceSURF_FORMAT Format,
250 IN gctPOINTER PixelValue
251 );
252
253gceSTATUS
254gcoSURF_SetDither(
255 IN gcoSURF Surface,
256 IN gctBOOL Dither
257 );
258
259gceSTATUS
260gcoSURF_Set2DSource(
261 gcoSURF Surface,
262 gceSURF_ROTATION Rotation
263 );
264
265gceSTATUS
266gcoSURF_Set2DTarget(
267 gcoSURF Surface,
268 gceSURF_ROTATION Rotation
269 );
270
271/******************************************************************************\
272********************************** gco2D Object *********************************
273\******************************************************************************/
274
275/* Construct a new gco2D object. */
276gceSTATUS
277gco2D_Construct(
278 IN gcoHAL Hal,
279 OUT gco2D * Hardware
280 );
281
282/* Destroy an gco2D object. */
283gceSTATUS
284gco2D_Destroy(
285 IN gco2D Hardware
286 );
287
288/* Sets the maximum number of brushes in the brush cache. */
289gceSTATUS
290gco2D_SetBrushLimit(
291 IN gco2D Hardware,
292 IN gctUINT MaxCount
293 );
294
295/* Flush the brush. */
296gceSTATUS
297gco2D_FlushBrush(
298 IN gco2D Engine,
299 IN gcoBRUSH Brush,
300 IN gceSURF_FORMAT Format
301 );
302
303/* Program the specified solid color brush. */
304gceSTATUS
305gco2D_LoadSolidBrush(
306 IN gco2D Engine,
307 IN gceSURF_FORMAT Format,
308 IN gctUINT32 ColorConvert,
309 IN gctUINT32 Color,
310 IN gctUINT64 Mask
311 );
312
313gceSTATUS
314gco2D_LoadMonochromeBrush(
315 IN gco2D Engine,
316 IN gctUINT32 OriginX,
317 IN gctUINT32 OriginY,
318 IN gctUINT32 ColorConvert,
319 IN gctUINT32 FgColor,
320 IN gctUINT32 BgColor,
321 IN gctUINT64 Bits,
322 IN gctUINT64 Mask
323 );
324
325gceSTATUS
326gco2D_LoadColorBrush(
327 IN gco2D Engine,
328 IN gctUINT32 OriginX,
329 IN gctUINT32 OriginY,
330 IN gctUINT32 Address,
331 IN gceSURF_FORMAT Format,
332 IN gctUINT64 Mask
333 );
334
335/* Configure monochrome source. */
336gceSTATUS
337gco2D_SetMonochromeSource(
338 IN gco2D Engine,
339 IN gctBOOL ColorConvert,
340 IN gctUINT8 MonoTransparency,
341 IN gceSURF_MONOPACK DataPack,
342 IN gctBOOL CoordRelative,
343 IN gceSURF_TRANSPARENCY Transparency,
344 IN gctUINT32 FgColor,
345 IN gctUINT32 BgColor
346 );
347
348/* Configure color source. */
349gceSTATUS
350gco2D_SetColorSource(
351 IN gco2D Engine,
352 IN gctUINT32 Address,
353 IN gctUINT32 Stride,
354 IN gceSURF_FORMAT Format,
355 IN gceSURF_ROTATION Rotation,
356 IN gctUINT32 SurfaceWidth,
357 IN gctBOOL CoordRelative,
358 IN gceSURF_TRANSPARENCY Transparency,
359 IN gctUINT32 TransparencyColor
360 );
361
362/* Configure color source extension for full rotation. */
363gceSTATUS
364gco2D_SetColorSourceEx(
365 IN gco2D Engine,
366 IN gctUINT32 Address,
367 IN gctUINT32 Stride,
368 IN gceSURF_FORMAT Format,
369 IN gceSURF_ROTATION Rotation,
370 IN gctUINT32 SurfaceWidth,
371 IN gctUINT32 SurfaceHeight,
372 IN gctBOOL CoordRelative,
373 IN gceSURF_TRANSPARENCY Transparency,
374 IN gctUINT32 TransparencyColor
375 );
376
377/* Configure color source. */
378gceSTATUS
379gco2D_SetColorSourceAdvanced(
380 IN gco2D Engine,
381 IN gctUINT32 Address,
382 IN gctUINT32 Stride,
383 IN gceSURF_FORMAT Format,
384 IN gceSURF_ROTATION Rotation,
385 IN gctUINT32 SurfaceWidth,
386 IN gctUINT32 SurfaceHeight,
387 IN gctBOOL CoordRelative
388 );
389
390gceSTATUS
391gco2D_SetColorSourceN(
392 IN gco2D Engine,
393 IN gctUINT32 Address,
394 IN gctUINT32 Stride,
395 IN gceSURF_FORMAT Format,
396 IN gceSURF_ROTATION Rotation,
397 IN gctUINT32 SurfaceWidth,
398 IN gctUINT32 SurfaceHeight,
399 IN gctUINT32 SurfaceNumber
400 );
401
402/* Configure masked color source. */
403gceSTATUS
404gco2D_SetMaskedSource(
405 IN gco2D Engine,
406 IN gctUINT32 Address,
407 IN gctUINT32 Stride,
408 IN gceSURF_FORMAT Format,
409 IN gctBOOL CoordRelative,
410 IN gceSURF_MONOPACK MaskPack
411 );
412
413/* Configure masked color source extension for full rotation. */
414gceSTATUS
415gco2D_SetMaskedSourceEx(
416 IN gco2D Engine,
417 IN gctUINT32 Address,
418 IN gctUINT32 Stride,
419 IN gceSURF_FORMAT Format,
420 IN gctBOOL CoordRelative,
421 IN gceSURF_MONOPACK MaskPack,
422 IN gceSURF_ROTATION Rotation,
423 IN gctUINT32 SurfaceWidth,
424 IN gctUINT32 SurfaceHeight
425 );
426
427/* Setup the source rectangle. */
428gceSTATUS
429gco2D_SetSource(
430 IN gco2D Engine,
431 IN gcsRECT_PTR SrcRect
432 );
433
434/* Set clipping rectangle. */
435gceSTATUS
436gco2D_SetClipping(
437 IN gco2D Engine,
438 IN gcsRECT_PTR Rect
439 );
440
441/* Configure destination. */
442gceSTATUS
443gco2D_SetTarget(
444 IN gco2D Engine,
445 IN gctUINT32 Address,
446 IN gctUINT32 Stride,
447 IN gceSURF_ROTATION Rotation,
448 IN gctUINT32 SurfaceWidth
449 );
450
451/* Configure destination extension for full rotation. */
452gceSTATUS
453gco2D_SetTargetEx(
454 IN gco2D Engine,
455 IN gctUINT32 Address,
456 IN gctUINT32 Stride,
457 IN gceSURF_ROTATION Rotation,
458 IN gctUINT32 SurfaceWidth,
459 IN gctUINT32 SurfaceHeight
460 );
461
462/* Calculate and program the stretch factors. */
463gceSTATUS
464gco2D_CalcStretchFactor(
465 IN gco2D Engine,
466 IN gctINT32 SrcSize,
467 IN gctINT32 DestSize,
468 OUT gctUINT32_PTR Factor
469 );
470
471gceSTATUS
472gco2D_SetStretchFactors(
473 IN gco2D Engine,
474 IN gctUINT32 HorFactor,
475 IN gctUINT32 VerFactor
476 );
477
478/* Calculate and program the stretch factors based on the rectangles. */
479gceSTATUS
480gco2D_SetStretchRectFactors(
481 IN gco2D Engine,
482 IN gcsRECT_PTR SrcRect,
483 IN gcsRECT_PTR DestRect
484 );
485
486/* Create a new solid color gcoBRUSH object. */
487gceSTATUS
488gco2D_ConstructSingleColorBrush(
489 IN gco2D Engine,
490 IN gctUINT32 ColorConvert,
491 IN gctUINT32 Color,
492 IN gctUINT64 Mask,
493 gcoBRUSH * Brush
494 );
495
496/* Create a new monochrome gcoBRUSH object. */
497gceSTATUS
498gco2D_ConstructMonochromeBrush(
499 IN gco2D Engine,
500 IN gctUINT32 OriginX,
501 IN gctUINT32 OriginY,
502 IN gctUINT32 ColorConvert,
503 IN gctUINT32 FgColor,
504 IN gctUINT32 BgColor,
505 IN gctUINT64 Bits,
506 IN gctUINT64 Mask,
507 gcoBRUSH * Brush
508 );
509
510/* Create a color gcoBRUSH object. */
511gceSTATUS
512gco2D_ConstructColorBrush(
513 IN gco2D Engine,
514 IN gctUINT32 OriginX,
515 IN gctUINT32 OriginY,
516 IN gctPOINTER Address,
517 IN gceSURF_FORMAT Format,
518 IN gctUINT64 Mask,
519 gcoBRUSH * Brush
520 );
521
522/* Clear one or more rectangular areas. */
523gceSTATUS
524gco2D_Clear(
525 IN gco2D Engine,
526 IN gctUINT32 RectCount,
527 IN gcsRECT_PTR Rect,
528 IN gctUINT32 Color32,
529 IN gctUINT8 FgRop,
530 IN gctUINT8 BgRop,
531 IN gceSURF_FORMAT DestFormat
532 );
533
534/* Draw one or more Bresenham lines. */
535gceSTATUS
536gco2D_Line(
537 IN gco2D Engine,
538 IN gctUINT32 LineCount,
539 IN gcsRECT_PTR Position,
540 IN gcoBRUSH Brush,
541 IN gctUINT8 FgRop,
542 IN gctUINT8 BgRop,
543 IN gceSURF_FORMAT DestFormat
544 );
545
546/* Draw one or more Bresenham lines based on the 32-bit color. */
547gceSTATUS
548gco2D_ColorLine(
549 IN gco2D Engine,
550 IN gctUINT32 LineCount,
551 IN gcsRECT_PTR Position,
552 IN gctUINT32 Color32,
553 IN gctUINT8 FgRop,
554 IN gctUINT8 BgRop,
555 IN gceSURF_FORMAT DestFormat
556 );
557
558/* Generic blit. */
559gceSTATUS
560gco2D_Blit(
561 IN gco2D Engine,
562 IN gctUINT32 RectCount,
563 IN gcsRECT_PTR Rect,
564 IN gctUINT8 FgRop,
565 IN gctUINT8 BgRop,
566 IN gceSURF_FORMAT DestFormat
567 );
568
569gceSTATUS
570gco2D_Blend(
571 IN gco2D Engine,
572 IN gctUINT32 SrcCount,
573 IN gctUINT32 RectCount,
574 IN gcsRECT_PTR Rect,
575 IN gctUINT8 FgRop,
576 IN gctUINT8 BgRop,
577 IN gceSURF_FORMAT DestFormat
578 );
579
580/* Batch blit. */
581gceSTATUS
582gco2D_BatchBlit(
583 IN gco2D Engine,
584 IN gctUINT32 RectCount,
585 IN gcsRECT_PTR SrcRect,
586 IN gcsRECT_PTR DestRect,
587 IN gctUINT8 FgRop,
588 IN gctUINT8 BgRop,
589 IN gceSURF_FORMAT DestFormat
590 );
591
592/* Stretch blit. */
593gceSTATUS
594gco2D_StretchBlit(
595 IN gco2D Engine,
596 IN gctUINT32 RectCount,
597 IN gcsRECT_PTR Rect,
598 IN gctUINT8 FgRop,
599 IN gctUINT8 BgRop,
600 IN gceSURF_FORMAT DestFormat
601 );
602
603/* Monochrome blit. */
604gceSTATUS
605gco2D_MonoBlit(
606 IN gco2D Engine,
607 IN gctPOINTER StreamBits,
608 IN gcsPOINT_PTR StreamSize,
609 IN gcsRECT_PTR StreamRect,
610 IN gceSURF_MONOPACK SrcStreamPack,
611 IN gceSURF_MONOPACK DestStreamPack,
612 IN gcsRECT_PTR DestRect,
613 IN gctUINT32 FgRop,
614 IN gctUINT32 BgRop,
615 IN gceSURF_FORMAT DestFormat
616 );
617
618gceSTATUS
619gco2D_MonoBlitEx(
620 IN gco2D Engine,
621 IN gctPOINTER StreamBits,
622 IN gctINT32 StreamStride,
623 IN gctINT32 StreamWidth,
624 IN gctINT32 StreamHeight,
625 IN gctINT32 StreamX,
626 IN gctINT32 StreamY,
627 IN gctUINT32 FgColor,
628 IN gctUINT32 BgColor,
629 IN gcsRECT_PTR SrcRect,
630 IN gcsRECT_PTR DstRect,
631 IN gctUINT8 FgRop,
632 IN gctUINT8 BgRop
633 );
634
635/* Set kernel size. */
636gceSTATUS
637gco2D_SetKernelSize(
638 IN gco2D Engine,
639 IN gctUINT8 HorKernelSize,
640 IN gctUINT8 VerKernelSize
641 );
642
643/* Set filter type. */
644gceSTATUS
645gco2D_SetFilterType(
646 IN gco2D Engine,
647 IN gceFILTER_TYPE FilterType
648 );
649
650/* Set the filter kernel by user. */
651gceSTATUS
652gco2D_SetUserFilterKernel(
653 IN gco2D Engine,
654 IN gceFILTER_PASS_TYPE PassType,
655 IN gctUINT16_PTR KernelArray
656 );
657
658/* Select the pass(es) to be done for user defined filter. */
659gceSTATUS
660gco2D_EnableUserFilterPasses(
661 IN gco2D Engine,
662 IN gctBOOL HorPass,
663 IN gctBOOL VerPass
664 );
665
666/* Frees the temporary buffer allocated by filter blit operation. */
667gceSTATUS
668gco2D_FreeFilterBuffer(
669 IN gco2D Engine
670 );
671
672/* Filter blit. */
673gceSTATUS
674gco2D_FilterBlit(
675 IN gco2D Engine,
676 IN gctUINT32 SrcAddress,
677 IN gctUINT SrcStride,
678 IN gctUINT32 SrcUAddress,
679 IN gctUINT SrcUStride,
680 IN gctUINT32 SrcVAddress,
681 IN gctUINT SrcVStride,
682 IN gceSURF_FORMAT SrcFormat,
683 IN gceSURF_ROTATION SrcRotation,
684 IN gctUINT32 SrcSurfaceWidth,
685 IN gcsRECT_PTR SrcRect,
686 IN gctUINT32 DestAddress,
687 IN gctUINT DestStride,
688 IN gceSURF_FORMAT DestFormat,
689 IN gceSURF_ROTATION DestRotation,
690 IN gctUINT32 DestSurfaceWidth,
691 IN gcsRECT_PTR DestRect,
692 IN gcsRECT_PTR DestSubRect
693 );
694
695/* Filter blit extension for full rotation. */
696gceSTATUS
697gco2D_FilterBlitEx(
698 IN gco2D Engine,
699 IN gctUINT32 SrcAddress,
700 IN gctUINT SrcStride,
701 IN gctUINT32 SrcUAddress,
702 IN gctUINT SrcUStride,
703 IN gctUINT32 SrcVAddress,
704 IN gctUINT SrcVStride,
705 IN gceSURF_FORMAT SrcFormat,
706 IN gceSURF_ROTATION SrcRotation,
707 IN gctUINT32 SrcSurfaceWidth,
708 IN gctUINT32 SrcSurfaceHeight,
709 IN gcsRECT_PTR SrcRect,
710 IN gctUINT32 DestAddress,
711 IN gctUINT DestStride,
712 IN gceSURF_FORMAT DestFormat,
713 IN gceSURF_ROTATION DestRotation,
714 IN gctUINT32 DestSurfaceWidth,
715 IN gctUINT32 DestSurfaceHeight,
716 IN gcsRECT_PTR DestRect,
717 IN gcsRECT_PTR DestSubRect
718 );
719
720gceSTATUS
721gco2D_FilterBlitEx2(
722 IN gco2D Engine,
723 IN gctUINT32_PTR SrcAddresses,
724 IN gctUINT32 SrcAddressNum,
725 IN gctUINT32_PTR SrcStrides,
726 IN gctUINT32 SrcStrideNum,
727 IN gceTILING SrcTiling,
728 IN gceSURF_FORMAT SrcFormat,
729 IN gceSURF_ROTATION SrcRotation,
730 IN gctUINT32 SrcSurfaceWidth,
731 IN gctUINT32 SrcSurfaceHeight,
732 IN gcsRECT_PTR SrcRect,
733 IN gctUINT32_PTR DestAddresses,
734 IN gctUINT32 DestAddressNum,
735 IN gctUINT32_PTR DestStrides,
736 IN gctUINT32 DestStrideNum,
737 IN gceTILING DestTiling,
738 IN gceSURF_FORMAT DestFormat,
739 IN gceSURF_ROTATION DestRotation,
740 IN gctUINT32 DestSurfaceWidth,
741 IN gctUINT32 DestSurfaceHeight,
742 IN gcsRECT_PTR DestRect,
743 IN gcsRECT_PTR DestSubRect
744 );
745
746/* Enable alpha blending engine in the hardware and disengage the ROP engine. */
747gceSTATUS
748gco2D_EnableAlphaBlend(
749 IN gco2D Engine,
750 IN gctUINT8 SrcGlobalAlphaValue,
751 IN gctUINT8 DstGlobalAlphaValue,
752 IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
753 IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
754 IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
755 IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
756 IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
757 IN gceSURF_BLEND_FACTOR_MODE DstFactorMode,
758 IN gceSURF_PIXEL_COLOR_MODE SrcColorMode,
759 IN gceSURF_PIXEL_COLOR_MODE DstColorMode
760 );
761
762/* Enable alpha blending engine in the hardware. */
763gceSTATUS
764gco2D_EnableAlphaBlendAdvanced(
765 IN gco2D Engine,
766 IN gceSURF_PIXEL_ALPHA_MODE SrcAlphaMode,
767 IN gceSURF_PIXEL_ALPHA_MODE DstAlphaMode,
768 IN gceSURF_GLOBAL_ALPHA_MODE SrcGlobalAlphaMode,
769 IN gceSURF_GLOBAL_ALPHA_MODE DstGlobalAlphaMode,
770 IN gceSURF_BLEND_FACTOR_MODE SrcFactorMode,
771 IN gceSURF_BLEND_FACTOR_MODE DstFactorMode
772 );
773
774/* Enable alpha blending engine with Porter Duff rule. */
775gceSTATUS
776gco2D_SetPorterDuffBlending(
777 IN gco2D Engine,
778 IN gce2D_PORTER_DUFF_RULE Rule
779 );
780
781/* Disable alpha blending engine in the hardware and engage the ROP engine. */
782gceSTATUS
783gco2D_DisableAlphaBlend(
784 IN gco2D Engine
785 );
786
787/* Retrieve the maximum number of 32-bit data chunks for a single DE command. */
788gctUINT32
789gco2D_GetMaximumDataCount(
790 void
791 );
792
793/* Retrieve the maximum number of rectangles, that can be passed in a single DE command. */
794gctUINT32
795gco2D_GetMaximumRectCount(
796 void
797 );
798
799/* Returns the pixel alignment of the surface. */
800gceSTATUS
801gco2D_GetPixelAlignment(
802 gceSURF_FORMAT Format,
803 gcsPOINT_PTR Alignment
804 );
805
806/* Retrieve monochrome stream pack size. */
807gceSTATUS
808gco2D_GetPackSize(
809 IN gceSURF_MONOPACK StreamPack,
810 OUT gctUINT32 * PackWidth,
811 OUT gctUINT32 * PackHeight
812 );
813
814/* Flush the 2D pipeline. */
815gceSTATUS
816gco2D_Flush(
817 IN gco2D Engine
818 );
819
820/* Load 256-entry color table for INDEX8 source surfaces. */
821gceSTATUS
822gco2D_LoadPalette(
823 IN gco2D Engine,
824 IN gctUINT FirstIndex,
825 IN gctUINT IndexCount,
826 IN gctPOINTER ColorTable,
827 IN gctBOOL ColorConvert
828 );
829
830/* Enable/disable 2D BitBlt mirrorring. */
831gceSTATUS
832gco2D_SetBitBlitMirror(
833 IN gco2D Engine,
834 IN gctBOOL HorizontalMirror,
835 IN gctBOOL VerticalMirror
836 );
837
838/*
839 * Set the transparency for source, destination and pattern.
840 * It also enable or disable the DFB color key mode.
841 */
842gceSTATUS
843gco2D_SetTransparencyAdvancedEx(
844 IN gco2D Engine,
845 IN gce2D_TRANSPARENCY SrcTransparency,
846 IN gce2D_TRANSPARENCY DstTransparency,
847 IN gce2D_TRANSPARENCY PatTransparency,
848 IN gctBOOL EnableDFBColorKeyMode
849 );
850
851/* Set the transparency for source, destination and pattern. */
852gceSTATUS
853gco2D_SetTransparencyAdvanced(
854 IN gco2D Engine,
855 IN gce2D_TRANSPARENCY SrcTransparency,
856 IN gce2D_TRANSPARENCY DstTransparency,
857 IN gce2D_TRANSPARENCY PatTransparency
858 );
859
860/* Set the source color key. */
861gceSTATUS
862gco2D_SetSourceColorKeyAdvanced(
863 IN gco2D Engine,
864 IN gctUINT32 ColorKey
865 );
866
867/* Set the source color key range. */
868gceSTATUS
869gco2D_SetSourceColorKeyRangeAdvanced(
870 IN gco2D Engine,
871 IN gctUINT32 ColorKeyLow,
872 IN gctUINT32 ColorKeyHigh
873 );
874
875/* Set the target color key. */
876gceSTATUS
877gco2D_SetTargetColorKeyAdvanced(
878 IN gco2D Engine,
879 IN gctUINT32 ColorKey
880 );
881
882/* Set the target color key range. */
883gceSTATUS
884gco2D_SetTargetColorKeyRangeAdvanced(
885 IN gco2D Engine,
886 IN gctUINT32 ColorKeyLow,
887 IN gctUINT32 ColorKeyHigh
888 );
889
890/* Set the YUV color space mode. */
891gceSTATUS
892gco2D_SetYUVColorMode(
893 IN gco2D Engine,
894 IN gce2D_YUV_COLOR_MODE Mode
895 );
896
897/* Setup the source global color value in ARGB8 format. */
898gceSTATUS gco2D_SetSourceGlobalColorAdvanced(
899 IN gco2D Engine,
900 IN gctUINT32 Color32
901 );
902
903/* Setup the target global color value in ARGB8 format. */
904gceSTATUS gco2D_SetTargetGlobalColorAdvanced(
905 IN gco2D Engine,
906 IN gctUINT32 Color32
907 );
908
909/* Setup the source and target pixel multiply modes. */
910gceSTATUS
911gco2D_SetPixelMultiplyModeAdvanced(
912 IN gco2D Engine,
913 IN gce2D_PIXEL_COLOR_MULTIPLY_MODE SrcPremultiplySrcAlpha,
914 IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstPremultiplyDstAlpha,
915 IN gce2D_GLOBAL_COLOR_MULTIPLY_MODE SrcPremultiplyGlobalMode,
916 IN gce2D_PIXEL_COLOR_MULTIPLY_MODE DstDemultiplyDstAlpha
917 );
918
919/* Set the GPU clock cycles after which the idle engine will keep auto-flushing. */
920gceSTATUS
921gco2D_SetAutoFlushCycles(
922 IN gco2D Engine,
923 IN gctUINT32 Cycles
924 );
925
926#if VIVANTE_PROFILER
927/* Read the profile registers available in the 2D engine and sets them in the profile.
928 The function will also reset the pixelsRendered counter every time.
929*/
930gceSTATUS
931gco2D_ProfileEngine(
932 IN gco2D Engine,
933 OPTIONAL gcs2D_PROFILE_PTR Profile
934 );
935#endif
936
937/* Enable or disable 2D dithering. */
938gceSTATUS
939gco2D_EnableDither(
940 IN gco2D Engine,
941 IN gctBOOL Enable
942 );
943
944gceSTATUS
945gco2D_SetGenericSource(
946 IN gco2D Engine,
947 IN gctUINT32_PTR Addresses,
948 IN gctUINT32 AddressNum,
949 IN gctUINT32_PTR Strides,
950 IN gctUINT32 StrideNum,
951 IN gceTILING Tiling,
952 IN gceSURF_FORMAT Format,
953 IN gceSURF_ROTATION Rotation,
954 IN gctUINT32 SurfaceWidth,
955 IN gctUINT32 SurfaceHeight
956);
957
958gceSTATUS
959gco2D_SetGenericTarget(
960 IN gco2D Engine,
961 IN gctUINT32_PTR Addresses,
962 IN gctUINT32 AddressNum,
963 IN gctUINT32_PTR Strides,
964 IN gctUINT32 StrideNum,
965 IN gceTILING Tiling,
966 IN gceSURF_FORMAT Format,
967 IN gceSURF_ROTATION Rotation,
968 IN gctUINT32 SurfaceWidth,
969 IN gctUINT32 SurfaceHeight
970);
971
972gceSTATUS
973gco2D_SetCurrentSourceIndex(
974 IN gco2D Engine,
975 IN gctUINT32 SrcIndex
976 );
977
978gceSTATUS
979gco2D_MultiSourceBlit(
980 IN gco2D Engine,
981 IN gctUINT32 SourceMask,
982 IN gcsRECT_PTR DestRect,
983 IN gctUINT32 RectCount
984 );
985
986gceSTATUS
987gco2D_SetROP(
988 IN gco2D Engine,
989 IN gctUINT8 FgRop,
990 IN gctUINT8 BgRop
991 );
992
993gceSTATUS
994gco2D_SetGdiStretchMode(
995 IN gco2D Engine,
996 IN gctBOOL Enable
997 );
998
999gceSTATUS
1000gco2D_SetSourceTileStatus(
1001 IN gco2D Engine,
1002 IN gce2D_TILE_STATUS_CONFIG TSControl,
1003 IN gceSURF_FORMAT CompressedFormat,
1004 IN gctUINT32 ClearValue,
1005 IN gctUINT32 GpuAddress
1006 );
1007
1008gceSTATUS
1009gco2D_SetTargetTileStatus(
1010 IN gco2D Engine,
1011 IN gce2D_TILE_STATUS_CONFIG TileStatusConfig,
1012 IN gceSURF_FORMAT CompressedFormat,
1013 IN gctUINT32 ClearValue,
1014 IN gctUINT32 GpuAddress
1015 );
1016
1017gceSTATUS
1018gco2D_QueryU32(
1019 IN gco2D Engine,
1020 IN gce2D_QUERY Item,
1021 OUT gctUINT32_PTR Value
1022 );
1023
1024gceSTATUS
1025gco2D_SetStateU32(
1026 IN gco2D Engine,
1027 IN gce2D_STATE State,
1028 IN gctUINT32 Value
1029 );
1030
1031gceSTATUS
1032gco2D_SetStateArrayI32(
1033 IN gco2D Engine,
1034 IN gce2D_STATE State,
1035 IN gctINT32_PTR Array,
1036 IN gctINT32 ArraySize
1037 );
1038
1039gceSTATUS
1040gco2D_SetStateArrayU32(
1041 IN gco2D Engine,
1042 IN gce2D_STATE State,
1043 IN gctUINT32_PTR Array,
1044 IN gctINT32 ArraySize
1045 );
1046
1047gceSTATUS
1048gco2D_SetTargetRect(
1049 IN gco2D Engine,
1050 IN gcsRECT_PTR Rect
1051 );
1052
1053gceSTATUS
1054gco2D_Set2DEngine(
1055 IN gco2D Engine
1056 );
1057
1058gceSTATUS
1059gco2D_UnSet2DEngine(
1060 IN gco2D Engine
1061 );
1062
1063gceSTATUS
1064gco2D_Get2DEngine(
1065 OUT gco2D * Engine
1066 );
1067
1068gceSTATUS
1069gco2D_Commit(
1070 IN gco2D Engine,
1071 IN gctBOOL Stall
1072 );
1073
1074#ifdef __cplusplus
1075}
1076#endif
1077
1078#endif /* __gc_hal_raster_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_rename.h b/src/hal/kernel/inc/gc_hal_rename.h
new file mode 100755
index 0000000..75c2658
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_rename.h
@@ -0,0 +1,277 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_rename_h_
57#define __gc_hal_rename_h_
58
59
60#if defined(_HAL2D_APPENDIX)
61
62#define _HAL2D_RENAME_2(api, appendix) api ## appendix
63#define _HAL2D_RENAME_1(api, appendix) _HAL2D_RENAME_2(api, appendix)
64#define gcmHAL2D(api) _HAL2D_RENAME_1(api, _HAL2D_APPENDIX)
65
66
67#define gckOS_Construct gcmHAL2D(gckOS_Construct)
68#define gckOS_Destroy gcmHAL2D(gckOS_Destroy)
69#define gckOS_QueryVideoMemory gcmHAL2D(gckOS_QueryVideoMemory)
70#define gckOS_Allocate gcmHAL2D(gckOS_Allocate)
71#define gckOS_Free gcmHAL2D(gckOS_Free)
72#define gckOS_AllocateMemory gcmHAL2D(gckOS_AllocateMemory)
73#define gckOS_FreeMemory gcmHAL2D(gckOS_FreeMemory)
74#define gckOS_AllocatePagedMemory gcmHAL2D(gckOS_AllocatePagedMemory)
75#define gckOS_AllocatePagedMemoryEx gcmHAL2D(gckOS_AllocatePagedMemoryEx)
76#define gckOS_LockPages gcmHAL2D(gckOS_LockPages)
77#define gckOS_MapPages gcmHAL2D(gckOS_MapPages)
78#define gckOS_UnlockPages gcmHAL2D(gckOS_UnlockPages)
79#define gckOS_FreePagedMemory gcmHAL2D(gckOS_FreePagedMemory)
80#define gckOS_AllocateNonPagedMemory gcmHAL2D(gckOS_AllocateNonPagedMemory)
81#define gckOS_FreeNonPagedMemory gcmHAL2D(gckOS_FreeNonPagedMemory)
82#define gckOS_AllocateContiguous gcmHAL2D(gckOS_AllocateContiguous)
83#define gckOS_FreeContiguous gcmHAL2D(gckOS_FreeContiguous)
84#define gckOS_GetPageSize gcmHAL2D(gckOS_GetPageSize)
85#define gckOS_GetPhysicalAddress gcmHAL2D(gckOS_GetPhysicalAddress)
86#define gckOS_UserLogicalToPhysical gcmHAL2D(gckOS_UserLogicalToPhysical)
87#define gckOS_GetPhysicalAddressProcess gcmHAL2D(gckOS_GetPhysicalAddressProcess)
88#define gckOS_MapPhysical gcmHAL2D(gckOS_MapPhysical)
89#define gckOS_UnmapPhysical gcmHAL2D(gckOS_UnmapPhysical)
90#define gckOS_ReadRegister gcmHAL2D(gckOS_ReadRegister)
91#define gckOS_WriteRegister gcmHAL2D(gckOS_WriteRegister)
92#define gckOS_WriteMemory gcmHAL2D(gckOS_WriteMemory)
93#define gckOS_MapMemory gcmHAL2D(gckOS_MapMemory)
94#define gckOS_UnmapMemory gcmHAL2D(gckOS_UnmapMemory)
95#define gckOS_UnmapMemoryEx gcmHAL2D(gckOS_UnmapMemoryEx)
96#define gckOS_CreateMutex gcmHAL2D(gckOS_CreateMutex)
97#define gckOS_DeleteMutex gcmHAL2D(gckOS_DeleteMutex)
98#define gckOS_AcquireMutex gcmHAL2D(gckOS_AcquireMutex)
99#define gckOS_ReleaseMutex gcmHAL2D(gckOS_ReleaseMutex)
100#define gckOS_AtomicExchange gcmHAL2D(gckOS_AtomicExchange)
101#define gckOS_AtomicExchangePtr gcmHAL2D(gckOS_AtomicExchangePtr)
102#define gckOS_AtomConstruct gcmHAL2D(gckOS_AtomConstruct)
103#define gckOS_AtomDestroy gcmHAL2D(gckOS_AtomDestroy)
104#define gckOS_AtomGet gcmHAL2D(gckOS_AtomGet)
105#define gckOS_AtomIncrement gcmHAL2D(gckOS_AtomIncrement)
106#define gckOS_AtomDecrement gcmHAL2D(gckOS_AtomDecrement)
107#define gckOS_Delay gcmHAL2D(gckOS_Delay)
108#define gckOS_GetTime gcmHAL2D(gckOS_GetTime)
109#define gckOS_MemoryBarrier gcmHAL2D(gckOS_MemoryBarrier)
110#define gckOS_MapUserPointer gcmHAL2D(gckOS_MapUserPointer)
111#define gckOS_UnmapUserPointer gcmHAL2D(gckOS_UnmapUserPointer)
112#define gckOS_QueryNeedCopy gcmHAL2D(gckOS_QueryNeedCopy)
113#define gckOS_CopyFromUserData gcmHAL2D(gckOS_CopyFromUserData)
114#define gckOS_CopyToUserData gcmHAL2D(gckOS_CopyToUserData)
115#define gckOS_SuspendInterrupt gcmHAL2D(gckOS_SuspendInterrupt)
116#define gckOS_ResumeInterrupt gcmHAL2D(gckOS_ResumeInterrupt)
117#define gckOS_GetBaseAddress gcmHAL2D(gckOS_GetBaseAddress)
118#define gckOS_MemCopy gcmHAL2D(gckOS_MemCopy)
119#define gckOS_ZeroMemory gcmHAL2D(gckOS_ZeroMemory)
120#define gckOS_DeviceControl gcmHAL2D(gckOS_DeviceControl)
121#define gckOS_GetProcessID gcmHAL2D(gckOS_GetProcessID)
122#define gckOS_GetThreadID gcmHAL2D(gckOS_GetThreadID)
123#define gckOS_CreateSignal gcmHAL2D(gckOS_CreateSignal)
124#define gckOS_DestroySignal gcmHAL2D(gckOS_DestroySignal)
125#define gckOS_Signal gcmHAL2D(gckOS_Signal)
126#define gckOS_WaitSignal gcmHAL2D(gckOS_WaitSignal)
127#define gckOS_MapSignal gcmHAL2D(gckOS_MapSignal)
128#define gckOS_MapUserMemory gcmHAL2D(gckOS_MapUserMemory)
129#define gckOS_UnmapUserMemory gcmHAL2D(gckOS_UnmapUserMemory)
130#define gckOS_CreateUserSignal gcmHAL2D(gckOS_CreateUserSignal)
131#define gckOS_DestroyUserSignal gcmHAL2D(gckOS_DestroyUserSignal)
132#define gckOS_WaitUserSignal gcmHAL2D(gckOS_WaitUserSignal)
133#define gckOS_SignalUserSignal gcmHAL2D(gckOS_SignalUserSignal)
134#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
135#define gckOS_UserSignal gcmHAL2D(gckOS_UserSignal)
136#define gckOS_CacheClean gcmHAL2D(gckOS_CacheClean)
137#define gckOS_CacheFlush gcmHAL2D(gckOS_CacheFlush)
138#define gckOS_SetDebugLevel gcmHAL2D(gckOS_SetDebugLevel)
139#define gckOS_SetDebugZone gcmHAL2D(gckOS_SetDebugZone)
140#define gckOS_SetDebugLevelZone gcmHAL2D(gckOS_SetDebugLevelZone)
141#define gckOS_SetDebugZones gcmHAL2D(gckOS_SetDebugZones)
142#define gckOS_SetDebugFile gcmHAL2D(gckOS_SetDebugFile)
143#define gckOS_Broadcast gcmHAL2D(gckOS_Broadcast)
144#define gckOS_SetGPUPower gcmHAL2D(gckOS_SetGPUPower)
145#define gckOS_CreateSemaphore gcmHAL2D(gckOS_CreateSemaphore)
146#define gckOS_DestroySemaphore gcmHAL2D(gckOS_DestroySemaphore)
147#define gckOS_AcquireSemaphore gcmHAL2D(gckOS_AcquireSemaphore)
148#define gckOS_ReleaseSemaphore gcmHAL2D(gckOS_ReleaseSemaphore)
149#define gckHEAP_Construct gcmHAL2D(gckHEAP_Construct)
150#define gckHEAP_Destroy gcmHAL2D(gckHEAP_Destroy)
151#define gckHEAP_Allocate gcmHAL2D(gckHEAP_Allocate)
152#define gckHEAP_Free gcmHAL2D(gckHEAP_Free)
153#define gckHEAP_ProfileStart gcmHAL2D(gckHEAP_ProfileStart)
154#define gckHEAP_ProfileEnd gcmHAL2D(gckHEAP_ProfileEnd)
155#define gckHEAP_Test gcmHAL2D(gckHEAP_Test)
156#define gckVIDMEM_Construct gcmHAL2D(gckVIDMEM_Construct)
157#define gckVIDMEM_Destroy gcmHAL2D(gckVIDMEM_Destroy)
158#define gckVIDMEM_Allocate gcmHAL2D(gckVIDMEM_Allocate)
159#define gckVIDMEM_AllocateLinear gcmHAL2D(gckVIDMEM_AllocateLinear)
160#define gckVIDMEM_Free gcmHAL2D(gckVIDMEM_Free)
161#define gckVIDMEM_Lock gcmHAL2D(gckVIDMEM_Lock)
162#define gckVIDMEM_Unlock gcmHAL2D(gckVIDMEM_Unlock)
163#define gckVIDMEM_ConstructVirtual gcmHAL2D(gckVIDMEM_ConstructVirtual)
164#define gckVIDMEM_DestroyVirtual gcmHAL2D(gckVIDMEM_DestroyVirtual)
165#define gckKERNEL_Construct gcmHAL2D(gckKERNEL_Construct)
166#define gckKERNEL_Destroy gcmHAL2D(gckKERNEL_Destroy)
167#define gckKERNEL_Dispatch gcmHAL2D(gckKERNEL_Dispatch)
168#define gckKERNEL_QueryVideoMemory gcmHAL2D(gckKERNEL_QueryVideoMemory)
169#define gckKERNEL_GetVideoMemoryPool gcmHAL2D(gckKERNEL_GetVideoMemoryPool)
170#define gckKERNEL_MapVideoMemory gcmHAL2D(gckKERNEL_MapVideoMemory)
171#define gckKERNEL_UnmapVideoMemory gcmHAL2D(gckKERNEL_UnmapVideoMemory)
172#define gckKERNEL_MapMemory gcmHAL2D(gckKERNEL_MapMemory)
173#define gckKERNEL_UnmapMemory gcmHAL2D(gckKERNEL_UnmapMemory)
174#define gckKERNEL_Notify gcmHAL2D(gckKERNEL_Notify)
175#define gckKERNEL_QuerySettings gcmHAL2D(gckKERNEL_QuerySettings)
176#define gckKERNEL_Recovery gcmHAL2D(gckKERNEL_Recovery)
177#define gckKERNEL_OpenUserData gcmHAL2D(gckKERNEL_OpenUserData)
178#define gckKERNEL_CloseUserData gcmHAL2D(gckKERNEL_CloseUserData)
179#define gckHARDWARE_Construct gcmHAL2D(gckHARDWARE_Construct)
180#define gckHARDWARE_Destroy gcmHAL2D(gckHARDWARE_Destroy)
181#define gckHARDWARE_QuerySystemMemory gcmHAL2D(gckHARDWARE_QuerySystemMemory)
182#define gckHARDWARE_BuildVirtualAddress gcmHAL2D(gckHARDWARE_BuildVirtualAddress)
183#define gckHARDWARE_QueryCommandBuffer gcmHAL2D(gckHARDWARE_QueryCommandBuffer)
184#define gckHARDWARE_WaitLink gcmHAL2D(gckHARDWARE_WaitLink)
185#define gckHARDWARE_Execute gcmHAL2D(gckHARDWARE_Execute)
186#define gckHARDWARE_End gcmHAL2D(gckHARDWARE_End)
187#define gckHARDWARE_Nop gcmHAL2D(gckHARDWARE_Nop)
188#define gckHARDWARE_PipeSelect gcmHAL2D(gckHARDWARE_PipeSelect)
189#define gckHARDWARE_Link gcmHAL2D(gckHARDWARE_Link)
190#define gckHARDWARE_Event gcmHAL2D(gckHARDWARE_Event)
191#define gckHARDWARE_QueryMemory gcmHAL2D(gckHARDWARE_QueryMemory)
192#define gckHARDWARE_QueryChipIdentity gcmHAL2D(gckHARDWARE_QueryChipIdentity)
193#define gckHARDWARE_QueryChipSpecs gcmHAL2D(gckHARDWARE_QueryChipSpecs)
194#define gckHARDWARE_QueryShaderCaps gcmHAL2D(gckHARDWARE_QueryShaderCaps)
195#define gckHARDWARE_ConvertFormat gcmHAL2D(gckHARDWARE_ConvertFormat)
196#define gckHARDWARE_SplitMemory gcmHAL2D(gckHARDWARE_SplitMemory)
197#define gckHARDWARE_AlignToTile gcmHAL2D(gckHARDWARE_AlignToTile)
198#define gckHARDWARE_UpdateQueueTail gcmHAL2D(gckHARDWARE_UpdateQueueTail)
199#define gckHARDWARE_ConvertLogical gcmHAL2D(gckHARDWARE_ConvertLogical)
200#define gckHARDWARE_Interrupt gcmHAL2D(gckHARDWARE_Interrupt)
201#define gckHARDWARE_SetMMU gcmHAL2D(gckHARDWARE_SetMMU)
202#define gckHARDWARE_FlushMMU gcmHAL2D(gckHARDWARE_FlushMMU)
203#define gckHARDWARE_GetIdle gcmHAL2D(gckHARDWARE_GetIdle)
204#define gckHARDWARE_Flush gcmHAL2D(gckHARDWARE_Flush)
205#define gckHARDWARE_SetFastClear gcmHAL2D(gckHARDWARE_SetFastClear)
206#define gckHARDWARE_ReadInterrupt gcmHAL2D(gckHARDWARE_ReadInterrupt)
207#define gckHARDWARE_SetPowerManagementState gcmHAL2D(gckHARDWARE_SetPowerManagementState)
208#define gckHARDWARE_QueryPowerManagementState gcmHAL2D(gckHARDWARE_QueryPowerManagementState)
209#define gckHARDWARE_ProfileEngine2D gcmHAL2D(gckHARDWARE_ProfileEngine2D)
210#define gckHARDWARE_InitializeHardware gcmHAL2D(gckHARDWARE_InitializeHardware)
211#define gckHARDWARE_Reset gcmHAL2D(gckHARDWARE_Reset)
212#define gckINTERRUPT_Construct gcmHAL2D(gckINTERRUPT_Construct)
213#define gckINTERRUPT_Destroy gcmHAL2D(gckINTERRUPT_Destroy)
214#define gckINTERRUPT_SetHandler gcmHAL2D(gckINTERRUPT_SetHandler)
215#define gckINTERRUPT_Notify gcmHAL2D(gckINTERRUPT_Notify)
216#define gckEVENT_Construct gcmHAL2D(gckEVENT_Construct)
217#define gckEVENT_Destroy gcmHAL2D(gckEVENT_Destroy)
218#define gckEVENT_AddList gcmHAL2D(gckEVENT_AddList)
219#define gckEVENT_FreeNonPagedMemory gcmHAL2D(gckEVENT_FreeNonPagedMemory)
220#define gckEVENT_FreeContiguousMemory gcmHAL2D(gckEVENT_FreeContiguousMemory)
221#define gckEVENT_FreeVideoMemory gcmHAL2D(gckEVENT_FreeVideoMemory)
222#define gckEVENT_Signal gcmHAL2D(gckEVENT_Signal)
223#define gckEVENT_Unlock gcmHAL2D(gckEVENT_Unlock)
224#define gckEVENT_Submit gcmHAL2D(gckEVENT_Submit)
225#define gckEVENT_Commit gcmHAL2D(gckEVENT_Commit)
226#define gckEVENT_Notify gcmHAL2D(gckEVENT_Notify)
227#define gckEVENT_Interrupt gcmHAL2D(gckEVENT_Interrupt)
228#define gckCOMMAND_Construct gcmHAL2D(gckCOMMAND_Construct)
229#define gckCOMMAND_Destroy gcmHAL2D(gckCOMMAND_Destroy)
230#define gckCOMMAND_EnterCommit gcmHAL2D(gckCOMMAND_EnterCommit)
231#define gckCOMMAND_ExitCommit gcmHAL2D(gckCOMMAND_ExitCommit)
232#define gckCOMMAND_Start gcmHAL2D(gckCOMMAND_Start)
233#define gckCOMMAND_Stop gcmHAL2D(gckCOMMAND_Stop)
234#define gckCOMMAND_Commit gcmHAL2D(gckCOMMAND_Commit)
235#define gckCOMMAND_Reserve gcmHAL2D(gckCOMMAND_Reserve)
236#define gckCOMMAND_Execute gcmHAL2D(gckCOMMAND_Execute)
237#define gckCOMMAND_Stall gcmHAL2D(gckCOMMAND_Stall)
238#define gckCOMMAND_Attach gcmHAL2D(gckCOMMAND_Attach)
239#define gckCOMMAND_Detach gcmHAL2D(gckCOMMAND_Detach)
240#define gckMMU_Construct gcmHAL2D(gckMMU_Construct)
241#define gckMMU_Destroy gcmHAL2D(gckMMU_Destroy)
242#define gckMMU_AllocatePages gcmHAL2D(gckMMU_AllocatePages)
243#define gckMMU_FreePages gcmHAL2D(gckMMU_FreePages)
244#define gckMMU_Test gcmHAL2D(gckMMU_Test)
245#define gckHARDWARE_QueryProfileRegisters gcmHAL2D(gckHARDWARE_QueryProfileRegisters)
246
247
248#define FindMdlMap gcmHAL2D(FindMdlMap)
249#define OnProcessExit gcmHAL2D(OnProcessExit)
250
251#define gckGALDEVICE_Destroy gcmHAL2D(gckGALDEVICE_Destroy)
252#define gckOS_Print gcmHAL2D(gckOS_Print)
253#define gckGALDEVICE_FreeMemory gcmHAL2D(gckGALDEVICE_FreeMemory)
254#define gckGALDEVICE_AllocateMemory gcmHAL2D(gckGALDEVICE_AllocateMemory)
255#define gckOS_DebugBreak gcmHAL2D(gckOS_DebugBreak)
256#define gckGALDEVICE_Release_ISR gcmHAL2D(gckGALDEVICE_Release_ISR)
257#define gckOS_Verify gcmHAL2D(gckOS_Verify)
258#define gckCOMMAND_Release gcmHAL2D(gckCOMMAND_Release)
259#define gckGALDEVICE_Stop gcmHAL2D(gckGALDEVICE_Stop)
260#define gckGALDEVICE_Construct gcmHAL2D(gckGALDEVICE_Construct)
261#define gckOS_DebugFatal gcmHAL2D(gckOS_DebugFatal)
262#define gckOS_DebugTrace gcmHAL2D(gckOS_DebugTrace)
263#define gckHARDWARE_GetBaseAddress gcmHAL2D(gckHARDWARE_GetBaseAddress)
264#define gckGALDEVICE_Setup_ISR gcmHAL2D(gckGALDEVICE_Setup_ISR)
265#define gckKERNEL_AttachProcess gcmHAL2D(gckKERNEL_AttachProcess)
266#define gckKERNEL_AttachProcessEx gcmHAL2D(gckKERNEL_AttachProcessEx)
267#define gckGALDEVICE_Start_Thread gcmHAL2D(gckGALDEVICE_Start_Thread)
268#define gckHARDWARE_QueryIdle gcmHAL2D(gckHARDWARE_QueryIdle)
269#define gckGALDEVICE_Start gcmHAL2D(gckGALDEVICE_Start)
270#define gckOS_GetKernelLogical gcmHAL2D(gckOS_GetKernelLogical)
271#define gckOS_DebugTraceZone gcmHAL2D(gckOS_DebugTraceZone)
272#define gckGALDEVICE_Stop_Thread gcmHAL2D(gckGALDEVICE_Stop_Thread)
273#define gckHARDWARE_NeedBaseAddress gcmHAL2D(gckHARDWARE_NeedBaseAddress)
274
275#endif
276
277#endif /* __gc_hal_rename_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_security_interface.h b/src/hal/kernel/inc/gc_hal_security_interface.h
new file mode 100755
index 0000000..27f91f0
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_security_interface.h
@@ -0,0 +1,171 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef _GC_HAL_SECURITY_INTERFACE_H_
57#define _GC_HAL_SECURITY_INTERFACE_H_
58/*!
59 @brief Command codes between kernel module and TrustZone
60 @discussion
61 Critical services must be done in TrustZone to avoid sensitive content leak. Most of kernel module is kept in non-Secure os to minimize
62 code in TrustZone.
63 */
64typedef enum kernel_packet_command {
65 KERNEL_START_COMMAND,
66 KERNEL_SUBMIT,
67 KERNEL_MAP_MEMORY, /* */
68 KERNEL_UNMAP_MEMORY,
69 KERNEL_ALLOCATE_SECRUE_MEMORY, /*! Security memory management. */
70 KERNEL_FREE_SECURE_MEMORY,
71 KERNEL_EXECUTE, /* Execute a command buffer. */
72} kernel_packet_command_t;
73
74/*!
75 @brief gckCOMMAND Object requests TrustZone to start FE.
76 @discussion
77 DMA enabled register can only be written in TrustZone to avoid GPU from jumping to a hacked code.
78 Kernel module need use these command to ask TrustZone start command parser.
79 */
80struct kernel_start_command {
81 kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
82 gctUINT8 gpu; /*! Which GPU. */
83};
84
85/*!
86 @brief gckCOMMAND Object requests TrustZone to submit command buffer.
87 @discussion
88 Code in trustzone will check content of command buffer after copying command buffer to TrustZone.
89 */
90struct kernel_submit {
91 kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
92 gctUINT8 gpu; /*! Which GPU. */
93 gctUINT8 kernel_command; /*! Whether it is a kernel command. */
94 gctUINT32 command_buffer_handle; /*! Handle to command buffer. */
95 gctUINT32 offset; /* Offset in command buffer. */
96 gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
97 gctUINT32 command_buffer_length; /*! Length of command buffer. */
98};
99
100
101/*!
102 @brief gckVIDMEM Object requests TrustZone to allocate security memory.
103 @discussion
104 Allocate a buffer from security GPU memory.
105 */
106struct kernel_allocate_security_memory {
107 kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
108 gctUINT32 bytes; /*! Requested bytes. */
109 gctUINT32 memory_handle; /*! Handle of allocated memory. */
110};
111
112/*!
113 @brief gckVIDMEM Object requests TrustZone to allocate security memory.
114 @discussion
115 Free a video memory buffer from security GPU memory.
116 */
117struct kernel_free_security_memory {
118 kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
119 gctUINT32 memory_handle; /*! Handle of allocated memory. */
120};
121
122struct kernel_execute {
123 kernel_packet_command_t command; /*! The command (always needs to be the first entry in a structure). */
124 gctUINT8 gpu; /*! Which GPU. */
125 gctUINT8 kernel_command; /*! Whether it is a kernel command. */
126 gctUINT32 * command_buffer; /*! Content of command buffer need to be submit. */
127 gctUINT32 command_buffer_length; /*! Length of command buffer. */
128};
129
130typedef struct kernel_map_scatter_gather {
131 gctUINT32 bytes;
132 gctUINT32 physical;
133 struct kernel_map_scatter_gather *next;
134}
135kernel_map_scatter_gather_t;
136
137struct kernel_map_memory {
138 kernel_packet_command_t command;
139 kernel_map_scatter_gather_t *scatter;
140 gctUINT32 *physicals;
141 gctUINT32 pageCount;
142 gctUINT32 gpuAddress;
143};
144
145struct kernel_unmap_memory {
146 gctUINT32 gpuAddress;
147 gctUINT32 pageCount;
148};
149
150typedef struct _gcsTA_INTERFACE {
151 kernel_packet_command_t command;
152 union {
153 struct kernel_submit Submit;
154 struct kernel_start_command StartCommand;
155 struct kernel_allocate_security_memory AllocateSecurityMemory;
156 struct kernel_execute Execute;
157 struct kernel_map_memory MapMemory;
158 struct kernel_unmap_memory UnmapMemory;
159 } u;
160 gceSTATUS result;
161} gcsTA_INTERFACE;
162
163enum {
164 gcvTA_COMMAND_INIT,
165 gcvTA_COMMAND_DISPATCH,
166
167 gcvTA_CALLBACK_ALLOC_SECURE_MEM,
168 gcvTA_CALLBACK_FREE_SECURE_MEM,
169};
170
171#endif
diff --git a/src/hal/kernel/inc/gc_hal_types.h b/src/hal/kernel/inc/gc_hal_types.h
new file mode 100755
index 0000000..f79f9ad
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_types.h
@@ -0,0 +1,976 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_types_h_
57#define __gc_hal_types_h_
58
59#include "gc_hal_version.h"
60#include "gc_hal_options.h"
61
62#if !defined(VIV_KMD)
63#if defined(__KERNEL__)
64#include "linux/version.h"
65#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
66 typedef unsigned long uintptr_t;
67# endif
68# include "linux/types.h"
69#elif defined(UNDER_CE)
70#include <crtdefs.h>
71#elif defined(_MSC_VER) && (_MSC_VER <= 1500)
72#include <crtdefs.h>
73#include "vadefs.h"
74#elif defined(__QNXNTO__)
75#define _QNX_SOURCE
76#include <stdint.h>
77#include <stddef.h>
78#else
79#include <stdlib.h>
80#include <stddef.h>
81#include <stdint.h>
82#endif
83#endif
84
85#ifdef _WIN32
86#pragma warning(disable:4127) /* Conditional expression is constant (do { }
87 ** while(0)). */
88#pragma warning(disable:4100) /* Unreferenced formal parameter. */
89#pragma warning(disable:4204) /* Non-constant aggregate initializer (C99). */
90#pragma warning(disable:4131) /* Uses old-style declarator (for Bison and
91 ** Flex generated files). */
92#pragma warning(disable:4206) /* Translation unit is empty. */
93#pragma warning(disable:4214) /* Nonstandard extension used :
94 ** bit field types other than int. */
95#endif
96
97#ifdef __cplusplus
98extern "C" {
99#endif
100
101/******************************************************************************\
102** Platform macros.
103*/
104
105#if defined(__GNUC__)
106# define gcdHAS_ELLIPSIS 1 /* GCC always has it. */
107#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
108# define gcdHAS_ELLIPSIS 1 /* C99 has it. */
109#elif defined(_MSC_VER) && (_MSC_VER >= 1500)
110# define gcdHAS_ELLIPSIS 1 /* MSVC 2007+ has it. */
111#elif defined(UNDER_CE)
112#if UNDER_CE >= 600
113# define gcdHAS_ELLIPSIS 1
114# else
115# define gcdHAS_ELLIPSIS 0
116# endif
117#else
118# error "gcdHAS_ELLIPSIS: Platform could not be determined"
119#endif
120
121/******************************************************************************\
122************************************ Keyword ***********************************
123\******************************************************************************/
124#if defined(ANDROID) && defined(__BIONIC_FORTIFY)
125# define gcmINLINE __inline__ __attribute__ ((always_inline)) __attribute__ ((gnu_inline)) __attribute__ ((artificial))
126#elif ((defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || defined(__APPLE__))
127# define gcmINLINE inline /* C99 keyword. */
128#elif defined(__GNUC__)
129# define gcmINLINE __inline__ /* GNU keyword. */
130#elif defined(_MSC_VER) || defined(UNDER_CE)
131# define gcmINLINE __inline /* Internal keyword. */
132#else
133# error "gcmINLINE: Platform could not be determined"
134#endif
135
136/* Possible debug flags. */
137#define gcdDEBUG_NONE 0
138#define gcdDEBUG_ALL (1 << 0)
139#define gcdDEBUG_FATAL (1 << 1)
140#define gcdDEBUG_TRACE (1 << 2)
141#define gcdDEBUG_BREAK (1 << 3)
142#define gcdDEBUG_ASSERT (1 << 4)
143#define gcdDEBUG_CODE (1 << 5)
144#define gcdDEBUG_STACK (1 << 6)
145
146#define gcmIS_DEBUG(flag) ( gcdDEBUG & (flag | gcdDEBUG_ALL) )
147
148#ifndef gcdDEBUG
149#if (defined(DBG) && DBG) || defined(DEBUG) || defined(_DEBUG)
150# define gcdDEBUG gcdDEBUG_ALL
151# else
152# define gcdDEBUG gcdDEBUG_NONE
153# endif
154#endif
155
156#ifdef _USRDLL
157#ifdef _MSC_VER
158#ifdef HAL_EXPORTS
159# define HALAPI __declspec(dllexport)
160# else
161# define HALAPI __declspec(dllimport)
162# endif
163# define HALDECL __cdecl
164# else
165#ifdef HAL_EXPORTS
166# define HALAPI
167# else
168# define HALAPI extern
169# endif
170# endif
171#else
172# define HALAPI
173# define HALDECL
174#endif
175
176/******************************************************************************\
177********************************** Common Types ********************************
178\******************************************************************************/
179
180#define gcvFALSE 0
181#define gcvTRUE 1
182
183#define gcvINFINITE ((gctUINT32) ~0U)
184
185#define gcvINVALID_HANDLE ((gctHANDLE) ~0U)
186
187typedef int gctBOOL;
188typedef gctBOOL * gctBOOL_PTR;
189
190typedef int gctINT;
191typedef signed char gctINT8;
192typedef signed short gctINT16;
193typedef signed int gctINT32;
194typedef signed long long gctINT64;
195
196typedef gctINT * gctINT_PTR;
197typedef gctINT8 * gctINT8_PTR;
198typedef gctINT16 * gctINT16_PTR;
199typedef gctINT32 * gctINT32_PTR;
200typedef gctINT64 * gctINT64_PTR;
201
202typedef unsigned int gctUINT;
203typedef unsigned char gctUINT8;
204typedef unsigned short gctUINT16;
205typedef unsigned int gctUINT32;
206typedef unsigned long long gctUINT64;
207typedef uintptr_t gctUINTPTR_T;
208
209typedef gctUINT * gctUINT_PTR;
210typedef gctUINT8 * gctUINT8_PTR;
211typedef gctUINT16 * gctUINT16_PTR;
212typedef gctUINT32 * gctUINT32_PTR;
213typedef gctUINT64 * gctUINT64_PTR;
214
215typedef size_t gctSIZE_T;
216typedef gctSIZE_T * gctSIZE_T_PTR;
217typedef gctUINT32 gctTRACE;
218
219#ifdef __cplusplus
220# define gcvNULL 0
221#else
222# define gcvNULL ((void *) 0)
223#endif
224
225#define gcvMAXINT8 0x7f
226#define gcvMININT8 0x80
227#define gcvMAXINT16 0x7fff
228#define gcvMININT16 0x8000
229#define gcvMAXINT32 0x7fffffff
230#define gcvMININT32 0x80000000
231#define gcvMAXINT64 0x7fffffffffffffff
232#define gcvMININT64 0x8000000000000000
233#define gcvMAXUINT8 0xff
234#define gcvMINUINT8 0x0
235#define gcvMAXUINT16 0xffff
236#define gcvMINUINT16 0x8000
237#define gcvMAXUINT32 0xffffffff
238#define gcvMINUINT32 0x80000000
239#define gcvMAXUINT64 0xffffffffffffffff
240#define gcvMINUINT64 0x8000000000000000
241#define gcvMAXUINTPTR_T (~(gctUINTPTR_T)0)
242
243typedef float gctFLOAT;
244typedef signed int gctFIXED_POINT;
245typedef float * gctFLOAT_PTR;
246
247typedef void * gctPHYS_ADDR;
248typedef void * gctHANDLE;
249typedef void * gctFILE;
250typedef void * gctSIGNAL;
251typedef void * gctWINDOW;
252typedef void * gctIMAGE;
253typedef void * gctSYNC_POINT;
254typedef void * gctSHBUF;
255
256typedef void * gctSEMAPHORE;
257
258typedef void * gctPOINTER;
259typedef const void * gctCONST_POINTER;
260
261typedef char gctCHAR;
262typedef char * gctSTRING;
263typedef const char * gctCONST_STRING;
264
265typedef gctUINT64 gctPHYS_ADDR_T;
266
267typedef struct _gcsCOUNT_STRING
268{
269 gctSIZE_T Length;
270 gctCONST_STRING String;
271}
272gcsCOUNT_STRING;
273
274typedef union _gcuFLOAT_UINT32
275{
276 gctFLOAT f;
277 gctUINT32 u;
278}
279gcuFLOAT_UINT32;
280
281/* Fixed point constants. */
282#define gcvZERO_X ((gctFIXED_POINT) 0x00000000)
283#define gcvHALF_X ((gctFIXED_POINT) 0x00008000)
284#define gcvONE_X ((gctFIXED_POINT) 0x00010000)
285#define gcvNEGONE_X ((gctFIXED_POINT) 0xFFFF0000)
286#define gcvTWO_X ((gctFIXED_POINT) 0x00020000)
287
288
289
290#define gcmFIXEDCLAMP_NEG1_TO_1(_x) \
291 (((_x) < gcvNEGONE_X) \
292 ? gcvNEGONE_X \
293 : (((_x) > gcvONE_X) \
294 ? gcvONE_X \
295 : (_x)))
296
297#define gcmFLOATCLAMP_NEG1_TO_1(_f) \
298 (((_f) < -1.0f) \
299 ? -1.0f \
300 : (((_f) > 1.0f) \
301 ? 1.0f \
302 : (_f)))
303
304
305#define gcmFIXEDCLAMP_0_TO_1(_x) \
306 (((_x) < 0) \
307 ? 0 \
308 : (((_x) > gcvONE_X) \
309 ? gcvONE_X \
310 : (_x)))
311
312#define gcmFLOATCLAMP_0_TO_1(_f) \
313 (((_f) < 0.0f) \
314 ? 0.0f \
315 : (((_f) > 1.0f) \
316 ? 1.0f \
317 : (_f)))
318
319
320/******************************************************************************\
321******************************* Multicast Values *******************************
322\******************************************************************************/
323
324/* Value types. */
325typedef enum _gceVALUE_TYPE
326{
327 gcvVALUE_UINT = 0x0,
328 gcvVALUE_FIXED,
329 gcvVALUE_FLOAT,
330 gcvVALUE_INT,
331
332 /*
333 ** The value need be unsigned denormalized. clamp (0.0-1.0) should be done first.
334 */
335 gcvVALUE_FLAG_UNSIGNED_DENORM = 0x00010000,
336
337 /*
338 ** The value need be signed denormalized. clamp (-1.0-1.0) should be done first.
339 */
340 gcvVALUE_FLAG_SIGNED_DENORM = 0x00020000,
341
342 /*
343 ** The value need to gammar
344 */
345 gcvVALUE_FLAG_GAMMAR = 0x00040000,
346
347 /*
348 ** The value need to convert from float to float16
349 */
350 gcvVALUE_FLAG_FLOAT_TO_FLOAT16 = 0x0080000,
351
352 /*
353 ** Mask for flag field.
354 */
355 gcvVALUE_FLAG_MASK = 0xFFFF0000,
356}
357gceVALUE_TYPE;
358
359/* Value unions. */
360typedef union _gcuVALUE
361{
362 gctUINT uintValue;
363 gctFIXED_POINT fixedValue;
364 gctFLOAT floatValue;
365 gctINT intValue;
366}
367gcuVALUE;
368
369
370
371
372/* Stringizing macro. */
373#define gcmSTRING(Value) #Value
374
375/******************************************************************************\
376******************************* Fixed Point Math *******************************
377\******************************************************************************/
378
379#define gcmXMultiply(x1, x2) gcoMATH_MultiplyFixed(x1, x2)
380#define gcmXDivide(x1, x2) gcoMATH_DivideFixed(x1, x2)
381#define gcmXMultiplyDivide(x1, x2, x3) gcoMATH_MultiplyDivideFixed(x1, x2, x3)
382
383/* 2D Engine profile. */
384typedef struct _gcs2D_PROFILE
385{
386 /* Cycle count.
387 32bit counter incremented every 2D clock cycle.
388 Wraps back to 0 when the counter overflows.
389 */
390 gctUINT32 cycleCount;
391
392 /* Pixels rendered by the 2D engine.
393 Resets to 0 every time it is read. */
394 gctUINT32 pixelsRendered;
395}
396gcs2D_PROFILE;
397
398/* Macro to combine four characters into a Charcater Code. */
399#define gcmCC(c1, c2, c3, c4) \
400( \
401 (char) (c1) \
402 | \
403 ((char) (c2) << 8) \
404 | \
405 ((char) (c3) << 16) \
406 | \
407 ((char) (c4) << 24) \
408)
409
410#define gcmPRINTABLE(c) ((((c) >= ' ') && ((c) <= '}')) ? ((c) != '%' ? (c) : ' ') : ' ')
411
412#define gcmCC_PRINT(cc) \
413 gcmPRINTABLE((char) ( (cc) & 0xFF)), \
414 gcmPRINTABLE((char) (((cc) >> 8) & 0xFF)), \
415 gcmPRINTABLE((char) (((cc) >> 16) & 0xFF)), \
416 gcmPRINTABLE((char) (((cc) >> 24) & 0xFF))
417
418/******************************************************************************\
419****************************** Function Parameters *****************************
420\******************************************************************************/
421
422#define IN
423#define OUT
424#define INOUT
425#define OPTIONAL
426
427/******************************************************************************\
428********************************* Status Codes *********************************
429\******************************************************************************/
430
431typedef enum _gceSTATUS
432{
433 gcvSTATUS_OK = 0,
434 gcvSTATUS_FALSE = 0,
435 gcvSTATUS_TRUE = 1,
436 gcvSTATUS_NO_MORE_DATA = 2,
437 gcvSTATUS_CACHED = 3,
438 gcvSTATUS_MIPMAP_TOO_LARGE = 4,
439 gcvSTATUS_NAME_NOT_FOUND = 5,
440 gcvSTATUS_NOT_OUR_INTERRUPT = 6,
441 gcvSTATUS_MISMATCH = 7,
442 gcvSTATUS_MIPMAP_TOO_SMALL = 8,
443 gcvSTATUS_LARGER = 9,
444 gcvSTATUS_SMALLER = 10,
445 gcvSTATUS_CHIP_NOT_READY = 11,
446 gcvSTATUS_NEED_CONVERSION = 12,
447 gcvSTATUS_SKIP = 13,
448 gcvSTATUS_DATA_TOO_LARGE = 14,
449 gcvSTATUS_INVALID_CONFIG = 15,
450 gcvSTATUS_CHANGED = 16,
451 gcvSTATUS_NOT_SUPPORT_DITHER = 17,
452 gcvSTATUS_EXECUTED = 18,
453 gcvSTATUS_TERMINATE = 19,
454
455 gcvSTATUS_INVALID_ARGUMENT = -1,
456 gcvSTATUS_INVALID_OBJECT = -2,
457 gcvSTATUS_OUT_OF_MEMORY = -3,
458 gcvSTATUS_MEMORY_LOCKED = -4,
459 gcvSTATUS_MEMORY_UNLOCKED = -5,
460 gcvSTATUS_HEAP_CORRUPTED = -6,
461 gcvSTATUS_GENERIC_IO = -7,
462 gcvSTATUS_INVALID_ADDRESS = -8,
463 gcvSTATUS_CONTEXT_LOSSED = -9,
464 gcvSTATUS_TOO_COMPLEX = -10,
465 gcvSTATUS_BUFFER_TOO_SMALL = -11,
466 gcvSTATUS_INTERFACE_ERROR = -12,
467 gcvSTATUS_NOT_SUPPORTED = -13,
468 gcvSTATUS_MORE_DATA = -14,
469 gcvSTATUS_TIMEOUT = -15,
470 gcvSTATUS_OUT_OF_RESOURCES = -16,
471 gcvSTATUS_INVALID_DATA = -17,
472 gcvSTATUS_INVALID_MIPMAP = -18,
473 gcvSTATUS_NOT_FOUND = -19,
474 gcvSTATUS_NOT_ALIGNED = -20,
475 gcvSTATUS_INVALID_REQUEST = -21,
476 gcvSTATUS_GPU_NOT_RESPONDING = -22,
477 gcvSTATUS_TIMER_OVERFLOW = -23,
478 gcvSTATUS_VERSION_MISMATCH = -24,
479 gcvSTATUS_LOCKED = -25,
480 gcvSTATUS_INTERRUPTED = -26,
481 gcvSTATUS_DEVICE = -27,
482 gcvSTATUS_NOT_MULTI_PIPE_ALIGNED = -28,
483
484 /* Linker errors. */
485 gcvSTATUS_GLOBAL_TYPE_MISMATCH = -1000,
486 gcvSTATUS_TOO_MANY_ATTRIBUTES = -1001,
487 gcvSTATUS_TOO_MANY_UNIFORMS = -1002,
488 gcvSTATUS_TOO_MANY_VARYINGS = -1003,
489 gcvSTATUS_UNDECLARED_VARYING = -1004,
490 gcvSTATUS_VARYING_TYPE_MISMATCH = -1005,
491 gcvSTATUS_MISSING_MAIN = -1006,
492 gcvSTATUS_NAME_MISMATCH = -1007,
493 gcvSTATUS_INVALID_INDEX = -1008,
494 gcvSTATUS_UNIFORM_MISMATCH = -1009,
495 gcvSTATUS_UNSAT_LIB_SYMBOL = -1010,
496 gcvSTATUS_TOO_MANY_SHADERS = -1011,
497 gcvSTATUS_LINK_INVALID_SHADERS = -1012,
498 gcvSTATUS_CS_NO_WORKGROUP_SIZE = -1013,
499 gcvSTATUS_LINK_LIB_ERROR = -1014,
500 gcvSTATUS_SHADER_VERSION_MISMATCH = -1015,
501 gcvSTATUS_TOO_MANY_INSTRUCTION = -1016,
502 gcvSTATUS_SSBO_MISMATCH = -1017,
503 gcvSTATUS_TOO_MANY_OUTPUT = -1018,
504 gcvSTATUS_TOO_MANY_INPUT = -1019,
505 gcvSTATUS_NOT_SUPPORT_CL = -1020,
506 gcvSTATUS_NOT_SUPPORT_INTEGER = -1021,
507 gcvSTATUS_UNIFORM_TYPE_MISMATCH = -1022,
508 gcvSTATUS_TOO_MANY_SAMPLER = -1023,
509
510 /* Compiler errors. */
511 gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR = -2000,
512 gcvSTATUS_COMPILER_FE_PARSER_ERROR = -2001,
513
514 /* Recompilation Errors */
515 gcvSTATUS_RECOMPILER_CONVERT_UNIMPLEMENTED = -3000,
516}
517gceSTATUS;
518
519/******************************************************************************\
520********************************* Status Macros ********************************
521\******************************************************************************/
522
523#define gcmIS_ERROR(status) (status < 0)
524#define gcmNO_ERROR(status) (status >= 0)
525#define gcmIS_SUCCESS(status) (status == gcvSTATUS_OK)
526
527/******************************************************************************\
528********************************* Field Macros *********************************
529\******************************************************************************/
530
531#define __gcmSTART(reg_field) \
532 (0 ? reg_field)
533
534#define __gcmEND(reg_field) \
535 (1 ? reg_field)
536
537#define __gcmGETSIZE(reg_field) \
538 (__gcmEND(reg_field) - __gcmSTART(reg_field) + 1)
539
540#define __gcmALIGN(data, reg_field) \
541 (((gctUINT32) (data)) << __gcmSTART(reg_field))
542
543#define __gcmMASK(reg_field) \
544 ((gctUINT32) ((__gcmGETSIZE(reg_field) == 32) \
545 ? ~0 \
546 : (~(~0 << __gcmGETSIZE(reg_field)))))
547
548/*******************************************************************************
549**
550** gcmFIELDMASK
551**
552** Get aligned field mask.
553**
554** ARGUMENTS:
555**
556** reg Name of register.
557** field Name of field within register.
558*/
559#define gcmFIELDMASK(reg, field) \
560( \
561 __gcmALIGN(__gcmMASK(reg##_##field), reg##_##field) \
562)
563
564/*******************************************************************************
565**
566** gcmGETFIELD
567**
568** Extract the value of a field from specified data.
569**
570** ARGUMENTS:
571**
572** data Data value.
573** reg Name of register.
574** field Name of field within register.
575*/
576#define gcmGETFIELD(data, reg, field) \
577( \
578 ((((gctUINT32) (data)) >> __gcmSTART(reg##_##field)) \
579 & __gcmMASK(reg##_##field)) \
580)
581
582/*******************************************************************************
583**
584** gcmSETFIELD
585**
586** Set the value of a field within specified data.
587**
588** ARGUMENTS:
589**
590** data Data value.
591** reg Name of register.
592** field Name of field within register.
593** value Value for field.
594*/
595#define gcmSETFIELD(data, reg, field, value) \
596( \
597 (((gctUINT32) (data)) \
598 & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
599 | __gcmALIGN((gctUINT32) (value) \
600 & __gcmMASK(reg##_##field), reg##_##field) \
601)
602
603/*******************************************************************************
604**
605** gcmSETFIELDVALUE
606**
607** Set the value of a field within specified data with a
608** predefined value.
609**
610** ARGUMENTS:
611**
612** data Data value.
613** reg Name of register.
614** field Name of field within register.
615** value Name of the value within the field.
616*/
617#define gcmSETFIELDVALUE(data, reg, field, value) \
618( \
619 (((gctUINT32) (data)) \
620 & ~__gcmALIGN(__gcmMASK(reg##_##field), reg##_##field)) \
621 | __gcmALIGN(reg##_##field##_##value \
622 & __gcmMASK(reg##_##field), reg##_##field) \
623)
624
625/*******************************************************************************
626**
627** gcmGETMASKEDFIELDMASK
628**
629** Determine field mask of a masked field.
630**
631** ARGUMENTS:
632**
633** reg Name of register.
634** field Name of field within register.
635*/
636#define gcmGETMASKEDFIELDMASK(reg, field) \
637( \
638 gcmSETFIELD(0, reg, field, ~0) | \
639 gcmSETFIELD(0, reg, MASK_ ## field, ~0) \
640)
641
642/*******************************************************************************
643**
644** gcmSETMASKEDFIELD
645**
646** Set the value of a masked field with specified data.
647**
648** ARGUMENTS:
649**
650** reg Name of register.
651** field Name of field within register.
652** value Value for field.
653*/
654#define gcmSETMASKEDFIELD(reg, field, value) \
655( \
656 gcmSETFIELD (~0, reg, field, value) & \
657 gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
658)
659
660/*******************************************************************************
661**
662** gcmSETMASKEDFIELDVALUE
663**
664** Set the value of a masked field with specified data.
665**
666** ARGUMENTS:
667**
668** reg Name of register.
669** field Name of field within register.
670** value Value for field.
671*/
672#define gcmSETMASKEDFIELDVALUE(reg, field, value) \
673( \
674 gcmSETFIELDVALUE(~0, reg, field, value) & \
675 gcmSETFIELDVALUE(~0, reg, MASK_ ## field, ENABLED) \
676)
677
678/*******************************************************************************
679**
680** gcmVERIFYFIELDVALUE
681**
682** Verify if the value of a field within specified data equals a
683** predefined value.
684**
685** ARGUMENTS:
686**
687** data Data value.
688** reg Name of register.
689** field Name of field within register.
690** value Name of the value within the field.
691*/
692#define gcmVERIFYFIELDVALUE(data, reg, field, value) \
693( \
694 (((gctUINT32) (data)) >> __gcmSTART(reg##_##field) & \
695 __gcmMASK(reg##_##field)) \
696 == \
697 (reg##_##field##_##value & __gcmMASK(reg##_##field)) \
698)
699
700/*******************************************************************************
701** Bit field macros.
702*/
703
704#define __gcmSTARTBIT(Field) \
705 ( 1 ? Field )
706
707#define __gcmBITSIZE(Field) \
708 ( 0 ? Field )
709
710#define __gcmBITMASK(Field) \
711( \
712 (1 << __gcmBITSIZE(Field)) - 1 \
713)
714
715#define gcmGETBITS(Value, Type, Field) \
716( \
717 ( ((Type) (Value)) >> __gcmSTARTBIT(Field) ) \
718 & \
719 __gcmBITMASK(Field) \
720)
721
722#define gcmSETBITS(Value, Type, Field, NewValue) \
723( \
724 ( ((Type) (Value)) \
725 & ~(__gcmBITMASK(Field) << __gcmSTARTBIT(Field)) \
726 ) \
727 | \
728 ( ( ((Type) (NewValue)) \
729 & __gcmBITMASK(Field) \
730 ) << __gcmSTARTBIT(Field) \
731 ) \
732)
733
734/*******************************************************************************
735**
736** gcmISINREGRANGE
737**
738** Verify whether the specified address is in the register range.
739**
740** ARGUMENTS:
741**
742** Address Address to be verified.
743** Name Name of a register.
744*/
745
746#define gcmISINREGRANGE(Address, Name) \
747( \
748 ((Address & (~0U << Name ## _LSB)) == (Name ## _Address >> 2)) \
749)
750
751/******************************************************************************\
752******************************** Ceiling Macro ********************************
753\******************************************************************************/
754#define gcmCEIL(x) ((x - (gctUINT32)x) == 0 ? (gctUINT32)x : (gctUINT32)x + 1)
755
756/******************************************************************************\
757******************************** Min/Max Macros ********************************
758\******************************************************************************/
759
760#define gcmMIN(x, y) (((x) <= (y)) ? (x) : (y))
761#define gcmMAX(x, y) (((x) >= (y)) ? (x) : (y))
762#define gcmCLAMP(x, min, max) (((x) < (min)) ? (min) : \
763 ((x) > (max)) ? (max) : (x))
764#define gcmABS(x) (((x) < 0) ? -(x) : (x))
765#define gcmNEG(x) (((x) < 0) ? (x) : -(x))
766
767/******************************************************************************\
768******************************** Bit Macro ********************************
769\******************************************************************************/
770#define gcmBITSET(x, y) ((x) & (y))
771/*******************************************************************************
772**
773** gcmPTR2INT
774**
775** Convert a pointer to an integer value.
776**
777** ARGUMENTS:
778**
779** p Pointer value.
780*/
781#define gcmPTR2INT(p) \
782( \
783 (gctUINTPTR_T) (p) \
784)
785
786#define gcmPTR2INT32(p) \
787( \
788 (gctUINT32)(gctUINTPTR_T) (p) \
789)
790
791/*******************************************************************************
792**
793** gcmINT2PTR
794**
795** Convert an integer value into a pointer.
796**
797** ARGUMENTS:
798**
799** v Integer value.
800*/
801
802#define gcmINT2PTR(i) \
803( \
804 (gctPOINTER) (gctUINTPTR_T)(i) \
805)
806
807/*******************************************************************************
808**
809** gcmOFFSETOF
810**
811** Compute the byte offset of a field inside a structure.
812**
813** ARGUMENTS:
814**
815** s Structure name.
816** field Field name.
817*/
818#define gcmOFFSETOF(s, field) \
819( \
820 gcmPTR2INT32(& (((struct s *) 0)->field)) \
821)
822
823/*******************************************************************************
824**
825** gcmSWAB32
826**
827** Return a value with all bytes in the 32 bit argument swapped.
828*/
829#define gcmSWAB32(x) ((gctUINT32)( \
830 (((gctUINT32)(x) & (gctUINT32)0x000000FFUL) << 24) | \
831 (((gctUINT32)(x) & (gctUINT32)0x0000FF00UL) << 8) | \
832 (((gctUINT32)(x) & (gctUINT32)0x00FF0000UL) >> 8) | \
833 (((gctUINT32)(x) & (gctUINT32)0xFF000000UL) >> 24)))
834
835/*******************************************************************************
836***** Database ****************************************************************/
837
838typedef struct _gcsDATABASE_COUNTERS
839{
840 /* Number of currently allocated bytes. */
841 gctUINT64 bytes;
842
843 /* Maximum number of bytes allocated (memory footprint). */
844 gctUINT64 maxBytes;
845
846 /* Total number of bytes allocated. */
847 gctUINT64 totalBytes;
848
849 /* The numbers of times video memory was allocated. */
850 gctUINT32 allocCount;
851
852 /* The numbers of times video memory was freed. */
853 gctUINT32 freeCount;
854}
855gcsDATABASE_COUNTERS;
856
857typedef struct _gcuDATABASE_INFO
858{
859 /* Counters. */
860 gcsDATABASE_COUNTERS counters;
861
862 /* Time value. */
863 gctUINT64 time;
864}
865gcuDATABASE_INFO;
866
867/*******************************************************************************
868***** Frame database **********************************************************/
869
870/* gcsHAL_FRAME_INFO */
871typedef struct _gcsHAL_FRAME_INFO
872{
873 /* Current timer tick. */
874 OUT gctUINT64 ticks;
875
876 /* Bandwidth counters. */
877 OUT gctUINT readBytes8[8];
878 OUT gctUINT writeBytes8[8];
879
880 /* Counters. */
881 OUT gctUINT cycles[8];
882 OUT gctUINT idleCycles[8];
883 OUT gctUINT mcCycles[8];
884 OUT gctUINT readRequests[8];
885 OUT gctUINT writeRequests[8];
886
887 /* 3D counters. */
888 OUT gctUINT vertexCount;
889 OUT gctUINT primitiveCount;
890 OUT gctUINT rejectedPrimitives;
891 OUT gctUINT culledPrimitives;
892 OUT gctUINT clippedPrimitives;
893 OUT gctUINT outPrimitives;
894 OUT gctUINT inPrimitives;
895 OUT gctUINT culledQuadCount;
896 OUT gctUINT totalQuadCount;
897 OUT gctUINT quadCount;
898 OUT gctUINT totalPixelCount;
899
900 /* PE counters. */
901 OUT gctUINT colorKilled[8];
902 OUT gctUINT colorDrawn[8];
903 OUT gctUINT depthKilled[8];
904 OUT gctUINT depthDrawn[8];
905
906 /* Shader counters. */
907 OUT gctUINT shaderCycles;
908 OUT gctUINT vsInstructionCount;
909 OUT gctUINT vsTextureCount;
910 OUT gctUINT psInstructionCount;
911 OUT gctUINT psTextureCount;
912
913 /* Texture counters. */
914 OUT gctUINT bilinearRequests;
915 OUT gctUINT trilinearRequests;
916 OUT gctUINT txBytes8;
917 OUT gctUINT txHitCount;
918 OUT gctUINT txMissCount;
919}
920gcsHAL_FRAME_INFO;
921
922#if gcdLINK_QUEUE_SIZE
923typedef struct _gckLINKDATA * gckLINKDATA;
924struct _gckLINKDATA
925{
926 gctUINT32 start;
927 gctUINT32 end;
928 gctUINT32 pid;
929 gctUINT32 linkLow;
930 gctUINT32 linkHigh;
931};
932
933typedef struct _gckLINKQUEUE * gckLINKQUEUE;
934struct _gckLINKQUEUE
935{
936 struct _gckLINKDATA data[gcdLINK_QUEUE_SIZE];
937 gctUINT32 rear;
938 gctUINT32 front;
939 gctUINT32 count;
940};
941#endif
942
943#define gcdENTRY_QUEUE_SIZE 256
944typedef struct _gckENTRYDATA * gckENTRYDATA;
945struct _gckENTRYDATA
946{
947 gctUINT32 physical;
948 gctUINT32 bytes;
949};
950
951typedef struct _gckENTRYQUEUE * gckENTRYQUEUE;
952struct _gckENTRYQUEUE
953{
954 struct _gckENTRYDATA data[gcdENTRY_QUEUE_SIZE];
955 gctUINT32 rear;
956 gctUINT32 front;
957 gctUINT32 count;
958};
959
960typedef enum _gceTRACEMODE
961{
962 gcvTRACEMODE_NONE = 0,
963 gcvTRACEMODE_FULL = 1,
964 gcvTRACEMODE_LOGGER = 2,
965 gcvTRACEMODE_PRE = 3,
966 gcvTRACEMODE_POST = 4,
967 gcvTRACEMODE_SYSTRACE = 5,
968
969} gceTRACEMODE;
970
971
972#ifdef __cplusplus
973}
974#endif
975
976#endif /* __gc_hal_types_h_ */
diff --git a/src/hal/kernel/inc/gc_hal_version.h b/src/hal/kernel/inc/gc_hal_version.h
new file mode 100755
index 0000000..ed77d1a
--- /dev/null
+++ b/src/hal/kernel/inc/gc_hal_version.h
@@ -0,0 +1,69 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_version_h_
57#define __gc_hal_version_h_
58
59#define gcvVERSION_MAJOR 5
60
61#define gcvVERSION_MINOR 0
62
63#define gcvVERSION_PATCH 11
64
65#define gcvVERSION_BUILD 33433
66
67#define gcvVERSION_STRING "5.0.11.p7.33433"
68
69#endif /* __gc_hal_version_h_ */
diff --git a/src/hal/kernel/makefile.linux b/src/hal/kernel/makefile.linux
new file mode 100755
index 0000000..187fe7d
--- /dev/null
+++ b/src/hal/kernel/makefile.linux
@@ -0,0 +1,97 @@
1##############################################################################
2#
3# The MIT License (MIT)
4#
5# Copyright (c) 2014 Vivante Corporation
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25##############################################################################
26#
27# The GPL License (GPL)
28#
29# Copyright (C) 2014 Vivante Corporation
30#
31# This program is free software; you can redistribute it and/or
32# modify it under the terms of the GNU General Public License
33# as published by the Free Software Foundation; either version 2
34# of the License, or (at your option) any later version.
35#
36# This program is distributed in the hope that it will be useful,
37# but WITHOUT ANY WARRANTY; without even the implied warranty of
38# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39# GNU General Public License for more details.
40#
41# You should have received a copy of the GNU General Public License
42# along with this program; if not, write to the Free Software Foundation,
43# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44#
45##############################################################################
46#
47# Note: This software is released under dual MIT and GPL licenses. A
48# recipient may use this file under the terms of either the MIT license or
49# GPL License. If you wish to use only one license not the other, you can
50# indicate your decision by deleting one of the above license notices in your
51# version of this file.
52#
53##############################################################################
54
55
56#
57# Linux build file for architecture dependent kernel HAL layer.
58#
59#
60
61
62################################################################################
63# Include common definitions.
64
65include $(AQROOT)/makefile.linux.def
66
67################################################################################
68# Define a shortcut for the main target.
69
70STATIC = 1
71TARGET_NAME = libhalkernel.a
72
73################################################################################
74# Supply additional include directories.
75
76INCLUDE += -I$(AQROOT)/hal/kernel/inc
77INCLUDE += -I$(AQROOT)/hal/kernel/inc
78INCLUDE += -I$(AQROOT)/hal/kernel/arch
79INCLUDE += -I$(AQROOT)/hal/kernel
80INCLUDE += -I$(AQROOT)/hal/os/linux/kernel
81
82CFLAGS += $(INCLUDE) -Werror -ansi
83
84################################################################################
85# Describe object files.
86
87OBJECTS = $(OBJ_DIR)/gc_hal_kernel_command.o \
88 $(OBJ_DIR)/gc_hal_kernel_db.o \
89 $(OBJ_DIR)/gc_hal_kernel_debug.o \
90 $(OBJ_DIR)/gc_hal_kernel_event.o \
91 $(OBJ_DIR)/gc_hal_kernel_heap.o \
92 $(OBJ_DIR)/gc_hal_kernel.o \
93 $(OBJ_DIR)/gc_hal_kernel_mmu.o \
94 $(OBJ_DIR)/gc_hal_kernel_video_memory.o
95
96
97include $(AQROOT)/common.target
diff --git a/src/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h b/src/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h
new file mode 100755
index 0000000..b1df099
--- /dev/null
+++ b/src/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_array.h
@@ -0,0 +1,84 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_allocator_array_h_
57#define __gc_hal_kernel_allocator_array_h_
58
59extern gceSTATUS
60_DefaultAlloctorInit(
61 IN gckOS Os,
62 OUT gckALLOCATOR * Allocator
63 );
64
65#ifdef CONFIG_DMA_SHARED_BUFFER
66extern gceSTATUS
67_DmabufAlloctorInit(
68 IN gckOS Os,
69 OUT gckALLOCATOR * Allocator
70 );
71#endif
72
73gcsALLOCATOR_DESC allocatorArray[] =
74{
75 /* Default allocator. */
76 gcmkDEFINE_ALLOCATOR_DESC("default", _DefaultAlloctorInit),
77
78#ifdef CONFIG_DMA_SHARED_BUFFER
79 /* Dmabuf allocator. */
80 gcmkDEFINE_ALLOCATOR_DESC("dmabuf", _DmabufAlloctorInit),
81#endif
82};
83
84#endif
diff --git a/src/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c b/src/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
new file mode 100755
index 0000000..023ca2e
--- /dev/null
+++ b/src/hal/os/linux/kernel/allocator/default/gc_hal_kernel_allocator_dmabuf.c
@@ -0,0 +1,353 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include "gc_hal_kernel_allocator.h"
58
59#include <linux/pagemap.h>
60#include <linux/seq_file.h>
61#include <linux/mman.h>
62#include <asm/atomic.h>
63#include <linux/dma-mapping.h>
64
65#include <linux/dma-buf.h>
66#include <linux/platform_device.h>
67
68#define _GC_OBJ_ZONE gcvZONE_OS
69
70/* Descriptor of a dma_buf imported. */
71typedef struct _gcsDMABUF
72{
73 struct dma_buf *dmabuf;
74 struct dma_buf_attachment *attachment;
75 struct sg_table *sgtable;
76 unsigned long *pagearray;
77 int handle;
78 int fd;
79}
80gcsDMABUF;
81
82static gceSTATUS
83_DmabufAttach(
84 IN gckALLOCATOR Allocator,
85 IN gcsATTACH_DESC_PTR Desc,
86 IN PLINUX_MDL Mdl
87 )
88{
89 gceSTATUS status;
90
91 gckOS os = Allocator->os;
92
93 int fd = (int) Desc->handle;
94
95 struct dma_buf *dmabuf = NULL;
96 struct sg_table *sgt = NULL;
97 struct dma_buf_attachment *attachment = NULL;
98 int npages = 0;
99 unsigned long *pagearray = NULL;
100 int i, j, k = 0;
101 struct scatterlist *s;
102 gcsDMABUF *gcdmabuf = NULL;
103
104 gcmkHEADER();
105
106 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
107
108 /* Import dma buf handle. */
109 dmabuf = dma_buf_get(fd);
110
111 if (!dmabuf)
112 {
113 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
114 }
115
116 attachment = dma_buf_attach(dmabuf, &os->device->platform->device->dev);
117
118 if (!attachment)
119 {
120 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
121 }
122
123 sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
124
125 if (!sgt)
126 {
127 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
128 }
129
130 /* Prepare page array. */
131 /* Get number of pages. */
132 for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
133 {
134 npages += (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE;
135 }
136
137 /* Allocate page arrary. */
138 gcmkONERROR(gckOS_Allocate(os, npages * gcmSIZEOF(*pagearray), (gctPOINTER *)&pagearray));
139
140 /* Fill page arrary. */
141 for_each_sg(sgt->sgl, s, sgt->orig_nents, i)
142 {
143 for (j = 0; j < (sg_dma_len(s) + PAGE_SIZE - 1) / PAGE_SIZE; j++)
144 {
145 pagearray[k++] = sg_dma_address(s) + j * PAGE_SIZE;
146 }
147 }
148
149 /* Prepare descriptor. */
150 gcmkONERROR(gckOS_Allocate(os, sizeof(gcsDMABUF), (gctPOINTER *)&gcdmabuf));
151
152 gcdmabuf->fd = fd;
153 gcdmabuf->dmabuf = dmabuf;
154 gcdmabuf->pagearray = pagearray;
155 gcdmabuf->attachment = attachment;
156 gcdmabuf->sgtable = sgt;
157
158 /* Record page number. */
159 Mdl->numPages = npages;
160
161 Mdl->priv = gcdmabuf;
162
163 gcmkFOOTER_NO();
164 return gcvSTATUS_OK;
165
166OnError:
167 gcmkFOOTER();
168 return status;
169}
170
171
172static void
173_DmabufFree(
174 IN gckALLOCATOR Allocator,
175 IN PLINUX_MDL Mdl
176 )
177{
178 gcsDMABUF *gcdmabuf = Mdl->priv;
179 gckOS os = Allocator->os;
180
181 dma_buf_unmap_attachment(gcdmabuf->attachment, gcdmabuf->sgtable, DMA_BIDIRECTIONAL);
182
183 dma_buf_detach(gcdmabuf->dmabuf, gcdmabuf->attachment);
184
185 dma_buf_put(gcdmabuf->dmabuf);
186
187 gckOS_Free(os, gcdmabuf->pagearray);
188
189 gckOS_Free(os, gcdmabuf);
190}
191
192static gctINT
193_DmabufMapUser(
194 IN gckALLOCATOR Allocator,
195 IN PLINUX_MDL Mdl,
196 IN PLINUX_MDL_MAP MdlMap,
197 IN gctBOOL Cacheable
198 )
199{
200 gcsDMABUF *gcdmabuf = Mdl->priv;
201 gceSTATUS status;
202 PLINUX_MDL mdl = Mdl;
203 PLINUX_MDL_MAP mdlMap = MdlMap;
204 struct file * file = gcdmabuf->dmabuf->file;
205
206 mdlMap->vmaAddr = (gctSTRING)vm_mmap(file,
207 0L,
208 mdl->numPages * PAGE_SIZE,
209 PROT_READ | PROT_WRITE,
210 MAP_SHARED,
211 0);
212
213 if (IS_ERR(mdlMap->vmaAddr))
214 {
215 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
216 }
217
218 down_write(&current->mm->mmap_sem);
219
220 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
221
222 up_write(&current->mm->mmap_sem);
223
224 if (mdlMap->vma == gcvNULL)
225 {
226 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
227 }
228
229 return 0;
230
231OnError:
232 return status;
233}
234
235static void
236_DmabufUnmapUser(
237 IN gckALLOCATOR Allocator,
238 IN gctPOINTER Logical,
239 IN gctUINT32 Size
240 )
241{
242 if (unlikely(current->mm == gcvNULL))
243 {
244 /* Do nothing if process is exiting. */
245 return;
246 }
247
248 vm_munmap((unsigned long)Logical, Size);
249}
250
251static gceSTATUS
252_DmabufMapKernel(
253 IN gckALLOCATOR Allocator,
254 IN PLINUX_MDL Mdl,
255 OUT gctPOINTER *Logical
256 )
257{
258 /* Kernel doesn't acess video memory. */
259 return gcvSTATUS_NOT_SUPPORTED;
260
261}
262
263static gceSTATUS
264_DmabufUnmapKernel(
265 IN gckALLOCATOR Allocator,
266 IN PLINUX_MDL Mdl,
267 IN gctPOINTER Logical
268 )
269{
270 /* Kernel doesn't acess video memory. */
271 return gcvSTATUS_NOT_SUPPORTED;
272}
273
274static gceSTATUS
275_DmabufLogicalToPhysical(
276 IN gckALLOCATOR Allocator,
277 IN PLINUX_MDL Mdl,
278 IN gctPOINTER Logical,
279 IN gctUINT32 ProcessID,
280 OUT gctPHYS_ADDR_T * Physical
281 )
282{
283 return gcvSTATUS_NOT_SUPPORTED;
284}
285
286
287static gceSTATUS
288_DmabufCache(
289 IN gckALLOCATOR Allocator,
290 IN PLINUX_MDL Mdl,
291 IN gctPOINTER Logical,
292 IN gctUINT32 Physical,
293 IN gctUINT32 Bytes,
294 IN gceCACHEOPERATION Operation
295 )
296{
297 return gcvSTATUS_OK;
298}
299
300
301static gceSTATUS
302_DmabufPhysical(
303 IN gckALLOCATOR Allocator,
304 IN PLINUX_MDL Mdl,
305 IN gctUINT32 Offset,
306 OUT gctPHYS_ADDR_T * Physical
307 )
308{
309 gcsDMABUF *gcdmabuf = Mdl->priv;
310
311 *Physical = gcdmabuf->pagearray[Offset];
312
313
314 return gcvSTATUS_OK;
315}
316
317/* Default allocator operations. */
318static gcsALLOCATOR_OPERATIONS DmabufAllocatorOperations =
319{
320 .Attach = _DmabufAttach,
321 .Free = _DmabufFree,
322 .MapUser = _DmabufMapUser,
323 .UnmapUser = _DmabufUnmapUser,
324 .MapKernel = _DmabufMapKernel,
325 .UnmapKernel = _DmabufUnmapKernel,
326 .LogicalToPhysical = _DmabufLogicalToPhysical,
327 .Cache = _DmabufCache,
328 .Physical = _DmabufPhysical,
329};
330
331/* Default allocator entry. */
332gceSTATUS
333_DmabufAlloctorInit(
334 IN gckOS Os,
335 OUT gckALLOCATOR * Allocator
336 )
337{
338 gceSTATUS status;
339 gckALLOCATOR allocator;
340
341 gcmkONERROR(
342 gckALLOCATOR_Construct(Os, &DmabufAllocatorOperations, &allocator));
343
344 allocator->capability = gcvALLOC_FLAG_DMABUF;
345
346 *Allocator = allocator;
347
348 return gcvSTATUS_OK;
349
350OnError:
351 return status;
352}
353
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_allocator.c b/src/hal/os/linux/kernel/gc_hal_kernel_allocator.c
new file mode 100755
index 0000000..11c7add
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_allocator.c
@@ -0,0 +1,972 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include "gc_hal_kernel_allocator.h"
58#include <linux/pagemap.h>
59#include <linux/seq_file.h>
60#include <linux/mman.h>
61#include <asm/atomic.h>
62#include <linux/dma-mapping.h>
63#include <linux/slab.h>
64
65#include "gc_hal_kernel_allocator_array.h"
66#include "gc_hal_kernel_platform.h"
67
68#define _GC_OBJ_ZONE gcvZONE_OS
69
70typedef struct _gcsDEFAULT_PRIV * gcsDEFAULT_PRIV_PTR;
71typedef struct _gcsDEFAULT_PRIV {
72 gctUINT32 low;
73 gctUINT32 high;
74}
75gcsDEFAULT_PRIV;
76
77/******************************************************************************\
78************************** Default Allocator Debugfs ***************************
79\******************************************************************************/
80
81int gc_usage_show(struct seq_file* m, void* data)
82{
83 gcsINFO_NODE *node = m->private;
84 gckALLOCATOR Allocator = node->device;
85 gcsDEFAULT_PRIV_PTR priv = Allocator->privateData;
86
87 seq_printf(m, "low: %u bytes\n", priv->low);
88 seq_printf(m, "high: %u bytes\n", priv->high);
89
90 return 0;
91}
92
93static gcsINFO InfoList[] =
94{
95 {"lowHighUsage", gc_usage_show},
96};
97
98static void
99_DefaultAllocatorDebugfsInit(
100 IN gckALLOCATOR Allocator,
101 IN gckDEBUGFS_DIR Root
102 )
103{
104 gcmkVERIFY_OK(
105 gckDEBUGFS_DIR_Init(&Allocator->debugfsDir, Root->root, "default"));
106
107 gcmkVERIFY_OK(gckDEBUGFS_DIR_CreateFiles(
108 &Allocator->debugfsDir,
109 InfoList,
110 gcmCOUNTOF(InfoList),
111 Allocator
112 ));
113}
114
115static void
116_DefaultAllocatorDebugfsCleanup(
117 IN gckALLOCATOR Allocator
118 )
119{
120 gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(
121 &Allocator->debugfsDir,
122 InfoList,
123 gcmCOUNTOF(InfoList)
124 ));
125
126 gckDEBUGFS_DIR_Deinit(&Allocator->debugfsDir);
127}
128
129
130static void
131_NonContiguousFree(
132 IN struct page ** Pages,
133 IN gctUINT32 NumPages
134 )
135{
136 gctINT i;
137
138 gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
139
140 gcmkASSERT(Pages != gcvNULL);
141
142 for (i = 0; i < NumPages; i++)
143 {
144 __free_page(Pages[i]);
145 }
146
147 if (is_vmalloc_addr(Pages))
148 {
149 vfree(Pages);
150 }
151 else
152 {
153 kfree(Pages);
154 }
155
156 gcmkFOOTER_NO();
157}
158
159static struct page **
160_NonContiguousAlloc(
161 IN gctUINT32 NumPages
162 )
163{
164 struct page ** pages;
165 struct page *p;
166 gctINT i, size;
167
168 gcmkHEADER_ARG("NumPages=%lu", NumPages);
169
170#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
171 if (NumPages > totalram_pages)
172#else
173 if (NumPages > num_physpages)
174#endif
175 {
176 gcmkFOOTER_NO();
177 return gcvNULL;
178 }
179
180 size = NumPages * sizeof(struct page *);
181
182 pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
183
184 if (!pages)
185 {
186 pages = vmalloc(size);
187
188 if (!pages)
189 {
190 gcmkFOOTER_NO();
191 return gcvNULL;
192 }
193 }
194
195 for (i = 0; i < NumPages; i++)
196 {
197 p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
198
199 if (!p)
200 {
201 _NonContiguousFree(pages, i);
202 gcmkFOOTER_NO();
203 return gcvNULL;
204 }
205
206 pages[i] = p;
207 }
208
209 gcmkFOOTER_ARG("pages=0x%X", pages);
210 return pages;
211}
212
213gctSTRING
214_CreateKernelVirtualMapping(
215 IN PLINUX_MDL Mdl
216 )
217{
218 gctSTRING addr = 0;
219 gctINT numPages = Mdl->numPages;
220
221#if gcdNONPAGED_MEMORY_CACHEABLE
222 if (Mdl->contiguous)
223 {
224 addr = page_address(Mdl->u.contiguousPages);
225 }
226 else
227 {
228 addr = vmap(Mdl->u.nonContiguousPages,
229 numPages,
230 0,
231 PAGE_KERNEL);
232
233 /* Trigger a page fault. */
234 memset(addr, 0, numPages * PAGE_SIZE);
235 }
236#else
237 struct page ** pages;
238 gctBOOL free = gcvFALSE;
239 gctINT i;
240
241 if (Mdl->contiguous)
242 {
243 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
244
245 if (!pages)
246 {
247 return gcvNULL;
248 }
249
250 for (i = 0; i < numPages; i++)
251 {
252 pages[i] = nth_page(Mdl->u.contiguousPages, i);
253 }
254
255 free = gcvTRUE;
256 }
257 else
258 {
259 pages = Mdl->u.nonContiguousPages;
260 }
261
262 /* ioremap() can't work on system memory since 2.6.38. */
263 addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
264
265 if (free)
266 {
267 kfree(pages);
268 }
269
270#endif
271
272 return addr;
273}
274
275void
276_DestoryKernelVirtualMapping(
277 IN gctSTRING Addr
278 )
279{
280#if !gcdNONPAGED_MEMORY_CACHEABLE
281 vunmap(Addr);
282#endif
283}
284
285void
286_UnmapUserLogical(
287 IN gctPOINTER Logical,
288 IN gctUINT32 Size
289)
290{
291 if (unlikely(current->mm == gcvNULL))
292 {
293 /* Do nothing if process is exiting. */
294 return;
295 }
296
297#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
298 if (vm_munmap((unsigned long)Logical, Size) < 0)
299 {
300 gcmkTRACE_ZONE(
301 gcvLEVEL_WARNING, gcvZONE_OS,
302 "%s(%d): vm_munmap failed",
303 __FUNCTION__, __LINE__
304 );
305 }
306#else
307 down_write(&current->mm->mmap_sem);
308 if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
309 {
310 gcmkTRACE_ZONE(
311 gcvLEVEL_WARNING, gcvZONE_OS,
312 "%s(%d): do_munmap failed",
313 __FUNCTION__, __LINE__
314 );
315 }
316 up_write(&current->mm->mmap_sem);
317#endif
318}
319
320/***************************************************************************\
321************************ Default Allocator **********************************
322\***************************************************************************/
323#define C_MAX_PAGENUM (50*1024)
324static gceSTATUS
325_DefaultAlloc(
326 IN gckALLOCATOR Allocator,
327 INOUT PLINUX_MDL Mdl,
328 IN gctSIZE_T NumPages,
329 IN gctUINT32 Flags
330 )
331{
332 gceSTATUS status;
333 gctUINT32 order;
334 gctSIZE_T bytes;
335#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
336 gctPOINTER addr = gcvNULL;
337#endif
338 gctUINT32 numPages;
339 gctUINT i = 0;
340 gctBOOL contiguous = Flags & gcvALLOC_FLAG_CONTIGUOUS;
341 struct sysinfo temsysinfo;
342 gcsDEFAULT_PRIV_PTR priv = (gcsDEFAULT_PRIV_PTR)Allocator->privateData;
343
344 gcmkHEADER_ARG("Mdl=%p NumPages=%d", Mdl, NumPages);
345
346 numPages = NumPages;
347 bytes = NumPages * PAGE_SIZE;
348 order = get_order(bytes);
349
350 si_meminfo(&temsysinfo);
351
352 if (Flags & gcvALLOC_FLAG_MEMLIMIT)
353 {
354 if ( (temsysinfo.freeram < NumPages) || ((temsysinfo.freeram-NumPages) < C_MAX_PAGENUM) )
355 {
356 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
357 }
358 }
359
360 if (contiguous)
361 {
362 if (order >= MAX_ORDER)
363 {
364 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
365 }
366
367#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
368 addr =
369 alloc_pages_exact(bytes, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
370
371 Mdl->u.contiguousPages = addr
372 ? virt_to_page(addr)
373 : gcvNULL;
374
375 Mdl->exact = gcvTRUE;
376#else
377 Mdl->u.contiguousPages =
378 alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order);
379#endif
380
381 if (Mdl->u.contiguousPages == gcvNULL)
382 {
383 Mdl->u.contiguousPages =
384 alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
385
386#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
387 Mdl->exact = gcvFALSE;
388#endif
389 }
390 }
391 else
392 {
393 Mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
394 }
395
396 if (Mdl->u.contiguousPages == gcvNULL && Mdl->u.nonContiguousPages == gcvNULL)
397 {
398 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
399 }
400
401 for (i = 0; i < numPages; i++)
402 {
403 struct page *page;
404
405 if (contiguous)
406 {
407 page = nth_page(Mdl->u.contiguousPages, i);
408 }
409 else
410 {
411 page = _NonContiguousToPage(Mdl->u.nonContiguousPages, i);
412 }
413
414 SetPageReserved(page);
415
416 if (!PageHighMem(page) && page_to_phys(page))
417 {
418 gcmkVERIFY_OK(
419 gckOS_CacheFlush(Allocator->os, _GetProcessID(), gcvNULL,
420 page_to_phys(page),
421 page_address(page),
422 PAGE_SIZE));
423
424 priv->low += PAGE_SIZE;
425 }
426 else
427 {
428 flush_dcache_page(page);
429
430#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE) && gcdENABLE_OUTER_CACHE_PATCH
431 if (page_to_phys(page))
432 {
433 _HandleOuterCache(
434 Allocator->os,
435 page_to_phys(page),
436 gcvNULL,
437 PAGE_SIZE,
438 gcvCACHE_FLUSH
439 );
440 }
441#endif
442
443 priv->high += PAGE_SIZE;
444 }
445 }
446
447 gcmkFOOTER_NO();
448 return gcvSTATUS_OK;
449
450OnError:
451 gcmkFOOTER();
452 return status;
453}
454
455static void
456_DefaultFree(
457 IN gckALLOCATOR Allocator,
458 IN OUT PLINUX_MDL Mdl
459 )
460{
461 gctINT i;
462 struct page * page;
463 gcsDEFAULT_PRIV_PTR priv = (gcsDEFAULT_PRIV_PTR)Allocator->privateData;
464
465 for (i = 0; i < Mdl->numPages; i++)
466 {
467 if (Mdl->contiguous)
468 {
469 page = nth_page(Mdl->u.contiguousPages, i);
470 }
471 else
472 {
473 page = _NonContiguousToPage(Mdl->u.nonContiguousPages, i);
474 }
475
476 ClearPageReserved(page);
477
478 if (PageHighMem(page))
479 {
480 priv->high -= PAGE_SIZE;
481 }
482 else
483 {
484 priv->low -= PAGE_SIZE;
485 }
486 }
487
488 if (Mdl->contiguous)
489 {
490#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
491 if (Mdl->exact == gcvTRUE)
492 {
493 free_pages_exact(page_address(Mdl->u.contiguousPages), Mdl->numPages * PAGE_SIZE);
494 }
495 else
496#endif
497 {
498 __free_pages(Mdl->u.contiguousPages, get_order(Mdl->numPages * PAGE_SIZE));
499 }
500 }
501 else
502 {
503 _NonContiguousFree(Mdl->u.nonContiguousPages, Mdl->numPages);
504 }
505}
506
507gctINT
508_DefaultMapUser(
509 gckALLOCATOR Allocator,
510 PLINUX_MDL Mdl,
511 PLINUX_MDL_MAP MdlMap,
512 gctBOOL Cacheable
513 )
514{
515
516 gctSTRING addr;
517 unsigned long start;
518 unsigned long pfn;
519 gctINT i;
520 gckOS os = Allocator->os;
521 gcsPLATFORM * platform = os->device->platform;
522
523 PLINUX_MDL mdl = Mdl;
524 PLINUX_MDL_MAP mdlMap = MdlMap;
525
526 gcmkHEADER_ARG("Allocator=%p Mdl=%p MdlMap=%p gctBOOL=%d", Allocator, Mdl, MdlMap, Cacheable);
527
528#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
529 mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
530 0L,
531 mdl->numPages * PAGE_SIZE,
532 PROT_READ | PROT_WRITE,
533 MAP_SHARED,
534 0);
535#else
536 down_write(&current->mm->mmap_sem);
537
538 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
539 0L,
540 mdl->numPages * PAGE_SIZE,
541 PROT_READ | PROT_WRITE,
542 MAP_SHARED,
543 0);
544
545 up_write(&current->mm->mmap_sem);
546#endif
547
548 gcmkTRACE_ZONE(
549 gcvLEVEL_INFO, gcvZONE_OS,
550 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
551 __FUNCTION__, __LINE__,
552 (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
553 (gctUINT32)(gctUINTPTR_T)mdl
554 );
555
556 if (IS_ERR(mdlMap->vmaAddr))
557 {
558 gcmkTRACE_ZONE(
559 gcvLEVEL_INFO, gcvZONE_OS,
560 "%s(%d): do_mmap_pgoff error",
561 __FUNCTION__, __LINE__
562 );
563
564 mdlMap->vmaAddr = gcvNULL;
565
566 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
567 return gcvSTATUS_OUT_OF_MEMORY;
568 }
569
570 down_write(&current->mm->mmap_sem);
571
572 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
573
574 if (mdlMap->vma == gcvNULL)
575 {
576 up_write(&current->mm->mmap_sem);
577
578 gcmkTRACE_ZONE(
579 gcvLEVEL_INFO, gcvZONE_OS,
580 "%s(%d): find_vma error",
581 __FUNCTION__, __LINE__
582 );
583
584 mdlMap->vmaAddr = gcvNULL;
585
586 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
587 return gcvSTATUS_OUT_OF_RESOURCES;
588 }
589
590 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
591
592 if (Cacheable == gcvFALSE)
593 {
594 /* Make this mapping non-cached. */
595 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
596 }
597
598 if (platform && platform->ops->adjustProt)
599 {
600 platform->ops->adjustProt(mdlMap->vma);
601 }
602
603 addr = mdl->addr;
604
605 /* Now map all the vmalloc pages to this user address. */
606 if (mdl->contiguous)
607 {
608 /* map kernel memory to user space.. */
609 if (remap_pfn_range(mdlMap->vma,
610 mdlMap->vma->vm_start,
611 page_to_pfn(mdl->u.contiguousPages),
612 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
613 mdlMap->vma->vm_page_prot) < 0)
614 {
615 up_write(&current->mm->mmap_sem);
616
617 gcmkTRACE_ZONE(
618 gcvLEVEL_INFO, gcvZONE_OS,
619 "%s(%d): unable to mmap ret",
620 __FUNCTION__, __LINE__
621 );
622
623 mdlMap->vmaAddr = gcvNULL;
624
625 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
626 return gcvSTATUS_OUT_OF_MEMORY;
627 }
628 }
629 else
630 {
631 start = mdlMap->vma->vm_start;
632
633 for (i = 0; i < mdl->numPages; i++)
634 {
635 pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
636
637 if (remap_pfn_range(mdlMap->vma,
638 start,
639 pfn,
640 PAGE_SIZE,
641 mdlMap->vma->vm_page_prot) < 0)
642 {
643 up_write(&current->mm->mmap_sem);
644
645 mdlMap->vmaAddr = gcvNULL;
646
647 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
648 return gcvSTATUS_OUT_OF_MEMORY;
649 }
650
651 start += PAGE_SIZE;
652 addr += PAGE_SIZE;
653 }
654 }
655
656 up_write(&current->mm->mmap_sem);
657
658 gcmkFOOTER_NO();
659 return gcvSTATUS_OK;
660}
661
662void
663_DefaultUnmapUser(
664 IN gckALLOCATOR Allocator,
665 IN gctPOINTER Logical,
666 IN gctUINT32 Size
667 )
668{
669 _UnmapUserLogical(Logical, Size);
670}
671
672gceSTATUS
673_DefaultMapKernel(
674 IN gckALLOCATOR Allocator,
675 IN PLINUX_MDL Mdl,
676 OUT gctPOINTER *Logical
677 )
678{
679 *Logical = _CreateKernelVirtualMapping(Mdl);
680 return gcvSTATUS_OK;
681}
682
683gceSTATUS
684_DefaultUnmapKernel(
685 IN gckALLOCATOR Allocator,
686 IN PLINUX_MDL Mdl,
687 IN gctPOINTER Logical
688 )
689{
690 _DestoryKernelVirtualMapping(Logical);
691 return gcvSTATUS_OK;
692}
693
694gceSTATUS
695_DefaultLogicalToPhysical(
696 IN gckALLOCATOR Allocator,
697 IN PLINUX_MDL Mdl,
698 IN gctPOINTER Logical,
699 IN gctUINT32 ProcessID,
700 OUT gctPHYS_ADDR_T * Physical
701 )
702{
703 return _ConvertLogical2Physical(
704 Allocator->os, Logical, ProcessID, Mdl, Physical);
705}
706
707gceSTATUS
708_DefaultCache(
709 IN gckALLOCATOR Allocator,
710 IN PLINUX_MDL Mdl,
711 IN gctPOINTER Logical,
712 IN gctUINT32 Physical,
713 IN gctUINT32 Bytes,
714 IN gceCACHEOPERATION Operation
715 )
716{
717 return gcvSTATUS_OK;
718}
719
720gceSTATUS
721_DefaultPhysical(
722 IN gckALLOCATOR Allocator,
723 IN PLINUX_MDL Mdl,
724 IN gctUINT32 Offset,
725 OUT gctPHYS_ADDR_T * Physical
726 )
727{
728 gcmkASSERT(Mdl->pagedMem && !Mdl->contiguous);
729 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, Offset);
730
731 return gcvSTATUS_OK;
732}
733
734void
735_DefaultAllocatorDestructor(
736 IN void* PrivateData
737 )
738{
739 kfree(PrivateData);
740}
741
742/* Default allocator operations. */
743gcsALLOCATOR_OPERATIONS DefaultAllocatorOperations = {
744 .Alloc = _DefaultAlloc,
745 .Free = _DefaultFree,
746 .MapUser = _DefaultMapUser,
747 .UnmapUser = _DefaultUnmapUser,
748 .MapKernel = _DefaultMapKernel,
749 .UnmapKernel = _DefaultUnmapKernel,
750 .LogicalToPhysical = _DefaultLogicalToPhysical,
751 .Cache = _DefaultCache,
752 .Physical = _DefaultPhysical,
753};
754
755/* Default allocator entry. */
756gceSTATUS
757_DefaultAlloctorInit(
758 IN gckOS Os,
759 OUT gckALLOCATOR * Allocator
760 )
761{
762 gceSTATUS status;
763 gckALLOCATOR allocator;
764 gcsDEFAULT_PRIV_PTR priv = gcvNULL;
765
766 gcmkONERROR(
767 gckALLOCATOR_Construct(Os, &DefaultAllocatorOperations, &allocator));
768
769 priv = kzalloc(gcmSIZEOF(gcsDEFAULT_PRIV), GFP_KERNEL | gcdNOWARN);
770
771 if (!priv)
772 {
773 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
774 }
775
776 /* Register private data. */
777 allocator->privateData = priv;
778 allocator->privateDataDestructor = _DefaultAllocatorDestructor;
779
780 allocator->debugfsInit = _DefaultAllocatorDebugfsInit;
781 allocator->debugfsCleanup = _DefaultAllocatorDebugfsCleanup;
782
783 allocator->capability = gcvALLOC_FLAG_CONTIGUOUS
784 | gcvALLOC_FLAG_NON_CONTIGUOUS
785 | gcvALLOC_FLAG_CACHEABLE
786 | gcvALLOC_FLAG_MEMLIMIT
787 ;
788
789 *Allocator = allocator;
790
791 return gcvSTATUS_OK;
792
793OnError:
794 return status;
795}
796
797/***************************************************************************\
798************************ Allocator helper ***********************************
799\***************************************************************************/
800
801gceSTATUS
802gckALLOCATOR_Construct(
803 IN gckOS Os,
804 IN gcsALLOCATOR_OPERATIONS * Operations,
805 OUT gckALLOCATOR * Allocator
806 )
807{
808 gceSTATUS status;
809 gckALLOCATOR allocator;
810
811 gcmkHEADER_ARG("Os=%p, Operations=%p, Allocator=%p",
812 Os, Operations, Allocator);
813
814 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
815 gcmkVERIFY_ARGUMENT(Allocator != gcvNULL);
816 gcmkVERIFY_ARGUMENT
817 ( Operations
818 && (Operations->Alloc || Operations->Attach)
819 && (Operations->Free)
820 && Operations->MapUser
821 && Operations->UnmapUser
822 && Operations->MapKernel
823 && Operations->UnmapKernel
824 && Operations->LogicalToPhysical
825 && Operations->Cache
826 && Operations->Physical
827 );
828
829 gcmkONERROR(
830 gckOS_Allocate(Os, gcmSIZEOF(gcsALLOCATOR), (gctPOINTER *)&allocator));
831
832 gckOS_ZeroMemory(allocator, gcmSIZEOF(gcsALLOCATOR));
833
834 /* Record os. */
835 allocator->os = Os;
836
837 /* Set operations. */
838 allocator->ops = Operations;
839
840 *Allocator = allocator;
841
842 gcmkFOOTER_NO();
843 return gcvSTATUS_OK;
844
845OnError:
846 gcmkFOOTER();
847 return status;
848}
849
850/******************************************************************************\
851******************************** Debugfs Support *******************************
852\******************************************************************************/
853
854static gceSTATUS
855_AllocatorDebugfsInit(
856 IN gckOS Os
857 )
858{
859 gceSTATUS status;
860 gckGALDEVICE device = Os->device;
861
862 gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
863
864 gcmkONERROR(gckDEBUGFS_DIR_Init(dir, device->debugfsDir.root, "allocators"));
865
866 return gcvSTATUS_OK;
867
868OnError:
869 return status;
870}
871
872static void
873_AllocatorDebugfsCleanup(
874 IN gckOS Os
875 )
876{
877 gckDEBUGFS_DIR dir = &Os->allocatorDebugfsDir;
878
879 gckDEBUGFS_DIR_Deinit(dir);
880}
881
882/***************************************************************************\
883************************ Allocator management *******************************
884\***************************************************************************/
885
886gceSTATUS
887gckOS_ImportAllocators(
888 gckOS Os
889 )
890{
891 gceSTATUS status;
892 gctUINT i;
893 gckALLOCATOR allocator;
894
895 _AllocatorDebugfsInit(Os);
896
897 INIT_LIST_HEAD(&Os->allocatorList);
898
899 for (i = 0; i < gcmCOUNTOF(allocatorArray); i++)
900 {
901 if (allocatorArray[i].construct)
902 {
903 /* Construct allocator. */
904 status = allocatorArray[i].construct(Os, &allocator);
905
906 if (gcmIS_ERROR(status))
907 {
908 gcmkPRINT("["DEVICE_NAME"]: Can't construct allocator(%s)",
909 allocatorArray[i].name);
910
911 continue;
912 }
913
914 allocator->name = allocatorArray[i].name;
915
916 if (allocator->debugfsInit)
917 {
918 /* Init allocator's debugfs. */
919 allocator->debugfsInit(allocator, &Os->allocatorDebugfsDir);
920 }
921
922 list_add_tail(&allocator->head, &Os->allocatorList);
923 }
924 }
925
926#if gcdDEBUG
927 list_for_each_entry(allocator, &Os->allocatorList, head)
928 {
929 gcmkTRACE_ZONE(
930 gcvLEVEL_WARNING, gcvZONE_OS,
931 "%s(%d) Allocator: %s",
932 __FUNCTION__, __LINE__,
933 allocator->name
934 );
935 }
936#endif
937
938 return gcvSTATUS_OK;
939}
940
941gceSTATUS
942gckOS_FreeAllocators(
943 gckOS Os
944 )
945{
946 gckALLOCATOR allocator;
947 gckALLOCATOR temp;
948
949 list_for_each_entry_safe(allocator, temp, &Os->allocatorList, head)
950 {
951 list_del(&allocator->head);
952
953 if (allocator->debugfsCleanup)
954 {
955 /* Clean up allocator's debugfs. */
956 allocator->debugfsCleanup(allocator);
957 }
958
959 /* Free private data. */
960 if (allocator->privateDataDestructor && allocator->privateData)
961 {
962 allocator->privateDataDestructor(allocator->privateData);
963 }
964
965 gckOS_Free(Os, allocator);
966 }
967
968 _AllocatorDebugfsCleanup(Os);
969
970 return gcvSTATUS_OK;
971}
972
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_allocator.h b/src/hal/os/linux/kernel/gc_hal_kernel_allocator.h
new file mode 100755
index 0000000..72f7c40
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_allocator.h
@@ -0,0 +1,470 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_allocator_h_
57#define __gc_hal_kernel_allocator_h_
58
59#include "gc_hal_kernel_linux.h"
60
61typedef struct _gcsALLOCATOR * gckALLOCATOR;
62typedef struct _gcsATTACH_DESC * gcsATTACH_DESC_PTR;
63
64typedef struct _gcsALLOCATOR_OPERATIONS
65{
66 /**************************************************************************
67 **
68 ** Alloc
69 **
70 ** Allocte memory, request size is page aligned.
71 **
72 ** INPUT:
73 **
74 ** gckALLOCATOR Allocator
75 ** Pointer to an gckALLOCATOER object.
76 **
77 ** PLINUX_Mdl
78 ** Pointer to Mdl whichs stores information
79 ** about allocated memory.
80 **
81 ** gctSIZE_T NumPages
82 ** Number of pages need to allocate.
83 **
84 ** gctUINT32 Flag
85 ** Allocation option.
86 **
87 ** OUTPUT:
88 **
89 ** Nothing.
90 **
91 */
92 gceSTATUS
93 (*Alloc)(
94 IN gckALLOCATOR Allocator,
95 IN PLINUX_MDL Mdl,
96 IN gctSIZE_T NumPages,
97 IN gctUINT32 Flag
98 );
99
100 /**************************************************************************
101 **
102 ** Free
103 **
104 ** Free memory.
105 **
106 ** INPUT:
107 **
108 ** gckALLOCATOR Allocator
109 ** Pointer to an gckALLOCATOER object.
110 **
111 ** PLINUX_MDL Mdl
112 ** Mdl which stores information.
113 **
114 ** OUTPUT:
115 **
116 ** Nothing.
117 **
118 */
119 void
120 (*Free)(
121 IN gckALLOCATOR Allocator,
122 IN PLINUX_MDL Mdl
123 );
124
125 /**************************************************************************
126 **
127 ** MapUser
128 **
129 ** Map memory to user space.
130 **
131 ** INPUT:
132 ** gckALLOCATOR Allocator
133 ** Pointer to an gckALLOCATOER object.
134 **
135 ** PLINUX_MDL Mdl
136 ** Pointer to a Mdl.
137 **
138 ** PLINUX_MDL_MAP MdlMap
139 ** Pointer to a MdlMap, mapped address is stored
140 ** in MdlMap->vmaAddr
141 **
142 ** gctBOOL Cacheable
143 ** Whether this mapping is cacheable.
144 **
145 ** OUTPUT:
146 **
147 ** Nothing.
148 **
149 */
150 gctINT
151 (*MapUser)(
152 IN gckALLOCATOR Allocator,
153 IN PLINUX_MDL Mdl,
154 IN PLINUX_MDL_MAP MdlMap,
155 IN gctBOOL Cacheable
156 );
157
158 /**************************************************************************
159 **
160 ** UnmapUser
161 **
162 ** Unmap address from user address space.
163 **
164 ** INPUT:
165 ** gckALLOCATOR Allocator
166 ** Pointer to an gckALLOCATOER object.
167 **
168 ** gctPOINTER Logical
169 ** Address to be unmap
170 **
171 ** gctUINT32 Size
172 ** Size of address space
173 **
174 ** OUTPUT:
175 **
176 ** Nothing.
177 **
178 */
179 void
180 (*UnmapUser)(
181 IN gckALLOCATOR Allocator,
182 IN gctPOINTER Logical,
183 IN gctUINT32 Size
184 );
185
186 /**************************************************************************
187 **
188 ** MapKernel
189 **
190 ** Map memory to kernel space.
191 **
192 ** INPUT:
193 ** gckALLOCATOR Allocator
194 ** Pointer to an gckALLOCATOER object.
195 **
196 ** PLINUX_MDL Mdl
197 ** Pointer to a Mdl object.
198 **
199 ** OUTPUT:
200 ** gctPOINTER * Logical
201 ** Mapped kernel address.
202 */
203 gceSTATUS
204 (*MapKernel)(
205 IN gckALLOCATOR Allocator,
206 IN PLINUX_MDL Mdl,
207 OUT gctPOINTER *Logical
208 );
209
210 /**************************************************************************
211 **
212 ** UnmapKernel
213 **
214 ** Unmap memory from kernel space.
215 **
216 ** INPUT:
217 ** gckALLOCATOR Allocator
218 ** Pointer to an gckALLOCATOER object.
219 **
220 ** PLINUX_MDL Mdl
221 ** Pointer to a Mdl object.
222 **
223 ** gctPOINTER Logical
224 ** Mapped kernel address.
225 **
226 ** OUTPUT:
227 **
228 ** Nothing.
229 **
230 */
231 gceSTATUS
232 (*UnmapKernel)(
233 IN gckALLOCATOR Allocator,
234 IN PLINUX_MDL Mdl,
235 IN gctPOINTER Logical
236 );
237
238 /**************************************************************************
239 **
240 ** LogicalToPhysical
241 **
242 ** Get physical address from logical address, logical
243 ** address could be user virtual address or kernel
244 ** virtual address.
245 **
246 ** INPUT:
247 ** gckALLOCATOR Allocator
248 ** Pointer to an gckALLOCATOER object.
249 **
250 ** PLINUX_MDL Mdl
251 ** Pointer to a Mdl object.
252 **
253 ** gctPOINTER Logical
254 ** Mapped kernel address.
255 **
256 ** gctUINT32 ProcessID
257 ** pid of current process.
258 ** OUTPUT:
259 **
260 ** gctUINT32_PTR Physical
261 ** Physical address.
262 **
263 */
264 gceSTATUS
265 (*LogicalToPhysical)(
266 IN gckALLOCATOR Allocator,
267 IN PLINUX_MDL Mdl,
268 IN gctPOINTER Logical,
269 IN gctUINT32 ProcessID,
270 OUT gctPHYS_ADDR_T * Physical
271 );
272
273 /**************************************************************************
274 **
275 ** Cache
276 **
277 ** Maintain cache coherency.
278 **
279 ** INPUT:
280 ** gckALLOCATOR Allocator
281 ** Pointer to an gckALLOCATOER object.
282 **
283 ** PLINUX_MDL Mdl
284 ** Pointer to a Mdl object.
285 **
286 ** gctPOINTER Logical
287 ** Logical address, could be user address or kernel address
288 **
289 ** gctUINT32_PTR Physical
290 ** Physical address.
291 **
292 ** gctUINT32 Bytes
293 ** Size of memory region.
294 **
295 ** gceCACHEOPERATION Opertaion
296 ** Cache operation.
297 **
298 ** OUTPUT:
299 **
300 ** Nothing.
301 **
302 */
303 gceSTATUS (*Cache)(
304 IN gckALLOCATOR Allocator,
305 IN PLINUX_MDL Mdl,
306 IN gctPOINTER Logical,
307 IN gctUINT32 Physical,
308 IN gctUINT32 Bytes,
309 IN gceCACHEOPERATION Operation
310 );
311
312 /**************************************************************************
313 **
314 ** Physical
315 **
316 ** Get physical address from a offset in memory region.
317 **
318 ** INPUT:
319 ** gckALLOCATOR Allocator
320 ** Pointer to an gckALLOCATOER object.
321 **
322 ** PLINUX_MDL Mdl
323 ** Pointer to a Mdl object.
324 **
325 ** gctUINT32 Offset
326 ** Offset in this memory region.
327 **
328 ** OUTPUT:
329 ** gctUINT32_PTR Physical
330 ** Physical address.
331 **
332 */
333 gceSTATUS (*Physical)(
334 IN gckALLOCATOR Allocator,
335 IN PLINUX_MDL Mdl,
336 IN gctUINT32 Offset,
337 OUT gctPHYS_ADDR_T * Physical
338 );
339
340 /**************************************************************************
341 **
342 ** Attach
343 **
344 ** Import memory allocated by an external allocator.
345 **
346 ** INPUT:
347 ** gckALLOCATOR Allocator
348 ** Pointer to an gckALLOCATOER object.
349 **
350 ** gctUINT32 Handle
351 ** Handle of the memory.
352 **
353 ** OUTPUT:
354 ** None.
355 **
356 */
357 gceSTATUS (*Attach)(
358 IN gckALLOCATOR Allocator,
359 IN gcsATTACH_DESC_PTR Desc,
360 OUT PLINUX_MDL Mdl
361 );
362}
363gcsALLOCATOR_OPERATIONS;
364
365typedef struct _gcsALLOCATOR
366{
367 /* Pointer to gckOS Object. */
368 gckOS os;
369
370 /* Name. */
371 gctSTRING name;
372
373 /* Operations. */
374 gcsALLOCATOR_OPERATIONS* ops;
375
376 /* Capability of this allocator. */
377 gctUINT32 capability;
378
379 struct list_head head;
380
381 /* Debugfs entry of this allocator. */
382 gcsDEBUGFS_DIR debugfsDir;
383
384 /* Init allocator debugfs. */
385 void (*debugfsInit)(gckALLOCATOR, gckDEBUGFS_DIR);
386
387 /* Cleanup allocator debugfs. */
388 void (*debugfsCleanup)(gckALLOCATOR);
389
390 /* Private data used by customer allocator. */
391 void * privateData;
392
393 /* Private data destructor. */
394 void (*privateDataDestructor)(void *);
395}
396gcsALLOCATOR;
397
398typedef struct _gcsALLOCATOR_DESC
399{
400 /* Name of a allocator. */
401 char * name;
402
403 /* Entry function to construct a allocator. */
404 gceSTATUS (*construct)(gckOS, gckALLOCATOR *);
405}
406gcsALLOCATOR_DESC;
407
408typedef struct _gcsATTACH_DESC
409{
410 /* gcvALLOC_FLAG_DMABUF */
411 gctUINT32 handle;
412
413 /* gcvALLOC_FLAG_USERMEMORY */
414 gctPOINTER memory;
415 gctUINT32 physical;
416 gctSIZE_T size;
417}
418gcsATTACH_DESC;
419
420/*
421* Helpers
422*/
423
424/* Fill a gcsALLOCATOR_DESC structure. */
425#define gcmkDEFINE_ALLOCATOR_DESC(Name, Construct) \
426 { \
427 .name = Name, \
428 .construct = Construct, \
429 }
430
431/* Construct a allocator. */
432gceSTATUS
433gckALLOCATOR_Construct(
434 IN gckOS Os,
435 IN gcsALLOCATOR_OPERATIONS * Operations,
436 OUT gckALLOCATOR * Allocator
437 );
438
439/*
440 How to implement customer allocator
441
442 Build in customer alloctor
443
444 It is recommanded that customer allocator is implmented in independent
445 source file(s) which is specified by CUSOMTER_ALLOCATOR_OBJS in Kbuld.
446
447 Register gcsALLOCATOR
448
449 For each customer specified allocator, a desciption entry must be added
450 to allocatorArray defined in gc_hal_kernel_allocator_array.h.
451
452 An entry in allocatorArray is a gcsALLOCATOR_DESC structure which describes
453 name and constructor of a gckALLOCATOR object.
454
455
456 Implement gcsALLOCATOR_DESC.init()
457
458 In gcsALLOCATOR_DESC.init(), gckALLOCATOR_Construct should be called
459 to create a gckALLOCATOR object, customer specified private data can
460 be put in gcsALLOCATOR.privateData.
461
462
463 Implement gcsALLOCATOR_OPERATIONS
464
465 When call gckALLOCATOR_Construct to create a gckALLOCATOR object, a
466 gcsALLOCATOR_OPERATIONS structure must be provided whose all members
467 implemented.
468
469*/
470#endif
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_debug.h b/src/hal/os/linux/kernel/gc_hal_kernel_debug.h
new file mode 100755
index 0000000..54782fd
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_debug.h
@@ -0,0 +1,147 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_debug_h_
57#define __gc_hal_kernel_debug_h_
58
59#include <gc_hal_kernel_linux.h>
60#include <linux/spinlock.h>
61#include <linux/time.h>
62#include <stdarg.h>
63
64#ifdef __cplusplus
65extern "C" {
66#endif
67
68/******************************************************************************\
69****************************** OS-dependent Macros *****************************
70\******************************************************************************/
71
72typedef va_list gctARGUMENTS;
73
74#define gcmkARGUMENTS_START(Arguments, Pointer) \
75 va_start(Arguments, Pointer)
76
77#define gcmkARGUMENTS_END(Arguments) \
78 va_end(Arguments)
79
80#define gcmkARGUMENTS_ARG(Arguments, Type) \
81 va_arg(Arguments, Type)
82
83#define gcmkDECLARE_LOCK(__spinLock__) \
84 static DEFINE_SPINLOCK(__spinLock__); \
85 unsigned long __spinLock__##flags = 0;
86
87#define gcmkLOCKSECTION(__spinLock__) \
88 spin_lock_irqsave(&__spinLock__, __spinLock__##flags)
89
90#define gcmkUNLOCKSECTION(__spinLock__) \
91 spin_unlock_irqrestore(&__spinLock__, __spinLock__##flags)
92
93#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
94# define gcmkGETPROCESSID() \
95 task_tgid_vnr(current)
96#else
97# define gcmkGETPROCESSID() \
98 current->tgid
99#endif
100
101#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
102# define gcmkGETTHREADID() \
103 task_pid_vnr(current)
104#else
105# define gcmkGETTHREADID() \
106 current->pid
107#endif
108
109#define gcmkOUTPUT_STRING(String) \
110 if(gckDEBUGFS_IsEnabled()) {\
111 while(-ERESTARTSYS == gckDEBUGFS_Print(String));\
112 }else{\
113 printk(String); \
114 }\
115 touch_softlockup_watchdog()
116
117
118#define gcmkSPRINTF(Destination, Size, Message, Value) \
119 snprintf(Destination, Size, Message, Value)
120
121#define gcmkSPRINTF2(Destination, Size, Message, Value1, Value2) \
122 snprintf(Destination, Size, Message, Value1, Value2)
123
124#define gcmkSPRINTF3(Destination, Size, Message, Value1, Value2, Value3) \
125 snprintf(Destination, Size, Message, Value1, Value2, Value3)
126
127#define gcmkVSPRINTF(Destination, Size, Message, Arguments) \
128 vsnprintf(Destination, Size, Message, *((va_list*)Arguments))
129
130#define gcmkSTRCAT(Destination, Size, String) \
131 strncat(Destination, String, Size)
132
133#define gcmkMEMCPY(Destination, Source, Size) \
134 memcpy(Destination, Source, Size)
135
136#define gcmkSTRLEN(String) \
137 strlen(String)
138
139/* If not zero, forces data alignment in the variable argument list
140 by its individual size. */
141#define gcdALIGNBYSIZE 1
142
143#ifdef __cplusplus
144}
145#endif
146
147#endif /* __gc_hal_kernel_debug_h_ */
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_debugfs.c b/src/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
new file mode 100755
index 0000000..99b4a2f
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_debugfs.c
@@ -0,0 +1,1181 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifdef MODULE
57#include <linux/module.h>
58#endif
59#include <linux/init.h>
60#include <linux/debugfs.h>
61#include <linux/slab.h>
62#ifdef MODVERSIONS
63#include <linux/modversions.h>
64#endif
65#include <linux/stddef.h>
66#include <linux/sched.h>
67#include <linux/kernel.h>
68#include <linux/timer.h>
69#include <linux/delay.h>
70#include <linux/errno.h>
71#include <linux/mutex.h>
72#include <linux/vmalloc.h>
73#include <linux/types.h>
74#include <linux/fs.h>
75#include <linux/poll.h>
76#include <asm/uaccess.h>
77#include <linux/completion.h>
78#include <linux/seq_file.h>
79#include "gc_hal_kernel_linux.h"
80#include "gc_hal_kernel.h"
81#include "gc_hal_kernel_debug.h"
82
83/*
84 Prequsite:
85
86 1) Debugfs feature must be enabled in the kernel.
87 1.a) You can enable this, in the compilation of the uImage, all you have to do is, In the "make menuconfig" part,
88 you have to enable the debugfs in the kernel hacking part of the menu.
89
90 HOW TO USE:
91 1) insert the driver with the following option logFileSize, Ex: insmod galcore.ko ...... logFileSize=10240
92 This gives a circular buffer of 10 MB
93
94 2)Usually after inserting the driver, the debug file system is mounted under /sys/kernel/debug/
95
96 2.a)If the debugfs is not mounted, you must do "mount -t debugfs none /sys/kernel/debug"
97
98 3) To read what is being printed in the debugfs file system:
99 Ex : cat /sys/kernel/debug/gc/galcore_trace
100
101 4)To write into the debug file system from user side :
102 Ex: echo "hello" > cat /sys/kernel/debug/gc/galcore_trace
103
104 5)To write into debugfs from kernel side, Use the function called gckDEBUGFS_Print
105
106 How to Get Video Memory Usage:
107 1) Select a process whose video memory usage can be dump, no need to reset it until <pid> is needed to be change.
108 echo <pid> > /sys/kernel/debug/gc/vidmem
109
110 2) Get video memory usage.
111 cat /sys/kernel/debug/gc/vidmem
112
113 USECASE Kernel Dump:
114
115 1) Go to /hal/inc/gc_hal_options.h, and enable the following flags:
116 - # define gcdDUMP 1
117 - # define gcdDUMP_IN_KERNEL 1
118 - # define gcdDUMP_COMMAND 1
119
120 2) Go to /hal/kernel/gc_hal_kernel_command.c and disable the following flag
121 -#define gcdSIMPLE_COMMAND_DUMP 0
122
123 3) Compile the driver
124 4) insmod it with the logFileSize option
125 5) Run an application
126 6) You can get the dump by cat /sys/kernel/debug/gpu/galcore_trace
127
128 */
129
130/**/
131typedef va_list gctDBGARGS ;
132#define gcmkARGS_START(argument, pointer) va_start(argument, pointer)
133#define gcmkARGS_END(argument) va_end(argument)
134
135#define gcmkDEBUGFS_PRINT(ArgumentSize, Message) \
136 { \
137 gctDBGARGS __arguments__; \
138 gcmkARGS_START(__arguments__, Message); \
139 _debugfs_res = _DebugFSPrint(ArgumentSize, Message, &__arguments__);\
140 gcmkARGS_END(__arguments__); \
141 }
142
143
144gcmkDECLARE_LOCK(traceLock);
145
146/* Debug File System Node Struct. */
147struct _gcsDEBUGFS_Node
148{
149 /*wait queues for read and write operations*/
150#if defined(DECLARE_WAIT_QUEUE_HEAD)
151 wait_queue_head_t read_q , write_q ;
152#else
153 struct wait_queue *read_q , *write_q ;
154#endif
155 struct dentry *parent ; /*parent directory*/
156 struct dentry *filen ; /*filename*/
157 struct dentry *vidmem;
158 struct semaphore sem ; /* mutual exclusion semaphore */
159 char *data ; /* The circular buffer data */
160 int size ; /* Size of the buffer pointed to by 'data' */
161 int refcount ; /* Files that have this buffer open */
162 int read_point ; /* Offset in circ. buffer of oldest data */
163 int write_point ; /* Offset in circ. buffer of newest data */
164 int offset ; /* Byte number of read_point in the stream */
165 struct _gcsDEBUGFS_Node *next ;
166
167 caddr_t temp;
168 int tempSize;
169};
170
171/* amount of data in the queue */
172#define gcmkNODE_QLEN(node) ( (node)->write_point >= (node)->read_point ? \
173 (node)->write_point - (node)->read_point : \
174 (node)->size - (node)->read_point + (node)->write_point)
175
176/* byte number of the last byte in the queue */
177#define gcmkNODE_FIRST_EMPTY_BYTE(node) ((node)->offset + gcmkNODE_QLEN(node))
178
179/*Synchronization primitives*/
180#define gcmkNODE_READQ(node) (&((node)->read_q))
181#define gcmkNODE_WRITEQ(node) (&((node)->write_q))
182#define gcmkNODE_SEM(node) (&((node)->sem))
183
184/*Utilities*/
185#define gcmkMIN(x, y) ((x) < (y) ? (x) : y)
186
187/*Debug File System Struct*/
188typedef struct _gcsDEBUGFS_
189{
190 gcsDEBUGFS_Node* linkedlist ;
191 gcsDEBUGFS_Node* currentNode ;
192 int isInited ;
193} gcsDEBUGFS_ ;
194
195/*debug file system*/
196static gcsDEBUGFS_ gc_dbgfs ;
197
198static int gc_debugfs_open(struct inode *inode, struct file *file)
199{
200 gcsINFO_NODE *node = inode->i_private;
201
202 return single_open(file, node->info->show, node);
203}
204
205static const struct file_operations gc_debugfs_operations = {
206 .owner = THIS_MODULE,
207 .open = gc_debugfs_open,
208 .read = seq_read,
209 .llseek = seq_lseek,
210 .release = single_release,
211};
212
213gceSTATUS
214gckDEBUGFS_DIR_Init(
215 IN gckDEBUGFS_DIR Dir,
216 IN struct dentry *root,
217 IN gctCONST_STRING Name
218 )
219{
220 Dir->root = debugfs_create_dir(Name, root);
221
222 if (!Dir->root)
223 {
224 return gcvSTATUS_NOT_SUPPORTED;
225 }
226
227 INIT_LIST_HEAD(&Dir->nodeList);
228
229 return gcvSTATUS_OK;
230}
231
232gceSTATUS
233gckDEBUGFS_DIR_CreateFiles(
234 IN gckDEBUGFS_DIR Dir,
235 IN gcsINFO * List,
236 IN int count,
237 IN gctPOINTER Data
238 )
239{
240 int i;
241 gcsINFO_NODE * node;
242 gceSTATUS status;
243
244 for (i = 0; i < count; i++)
245 {
246 /* Create a node. */
247 node = (gcsINFO_NODE *)kzalloc(sizeof(gcsINFO_NODE), GFP_KERNEL);
248
249 node->info = &List[i];
250 node->device = Data;
251
252 /* Bind to a file. TODO: clean up when fail. */
253 node->entry = debugfs_create_file(
254 List[i].name, S_IRUGO|S_IWUSR, Dir->root, node, &gc_debugfs_operations);
255
256 if (!node->entry)
257 {
258 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
259 }
260
261 list_add(&(node->head), &(Dir->nodeList));
262 }
263
264 return gcvSTATUS_OK;
265
266OnError:
267 gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(Dir, List, count));
268 return status;
269}
270
271gceSTATUS
272gckDEBUGFS_DIR_RemoveFiles(
273 IN gckDEBUGFS_DIR Dir,
274 IN gcsINFO * List,
275 IN int count
276 )
277{
278 int i;
279 gcsINFO_NODE * node;
280 gcsINFO_NODE * temp;
281
282 for (i = 0; i < count; i++)
283 {
284 list_for_each_entry_safe(node, temp, &Dir->nodeList, head)
285 {
286 if (node->info == &List[i])
287 {
288 debugfs_remove(node->entry);
289 list_del(&node->head);
290 kfree(node);
291 }
292 }
293 }
294
295 return gcvSTATUS_OK;
296}
297
298void
299gckDEBUGFS_DIR_Deinit(
300 IN gckDEBUGFS_DIR Dir
301 )
302{
303 if (Dir->root != NULL)
304 {
305 debugfs_remove(Dir->root);
306 Dir->root = NULL;
307 }
308}
309
310/*******************************************************************************
311 **
312 ** READ & WRITE FUNCTIONS (START)
313 **
314 *******************************************************************************/
315
316/*******************************************************************************
317 **
318 ** _ReadFromNode
319 **
320 ** 1) reading bytes out of a circular buffer with wraparound.
321 ** 2)returns caddr_t, pointer to data read, which the caller must free.
322 ** 3) length is (a pointer to) the number of bytes to be read, which will be set by this function to
323 ** be the number of bytes actually returned
324 **
325 *******************************************************************************/
326static caddr_t
327_ReadFromNode (
328 gcsDEBUGFS_Node* Node ,
329 size_t *Length ,
330 loff_t *Offset
331 )
332{
333 caddr_t retval ;
334 int bytes_copied = 0 , n , start_point , remaining ;
335
336 /* find the smaller of the total bytes we have available and what
337 * the user is asking for */
338 *Length = gcmkMIN ( *Length , gcmkNODE_QLEN(Node) ) ;
339
340 remaining = * Length ;
341
342 /* Get start point. */
343 start_point = Node->read_point;
344
345 /* allocate memory to return */
346 if (remaining > Node->tempSize)
347 {
348 kfree(Node->temp);
349
350 if ( ( retval = kmalloc ( sizeof (char ) * remaining , GFP_KERNEL ) ) == NULL )
351 return NULL;
352
353 Node->temp = retval;
354 Node->tempSize = remaining;
355 }
356 else
357 {
358 retval = Node->temp;
359 }
360
361 /* copy the (possibly noncontiguous) data to our buffer */
362 while ( remaining )
363 {
364 n = gcmkMIN ( remaining , Node->size - start_point ) ;
365 memcpy ( retval + bytes_copied , Node->data + start_point , n ) ;
366 bytes_copied += n ;
367 remaining -= n ;
368 start_point = ( start_point + n ) % Node->size ;
369 }
370
371 /* advance user's file pointer */
372 Node->read_point = (Node->read_point + * Length) % Node->size ;
373
374 return retval ;
375}
376
377/*******************************************************************************
378 **
379 ** _WriteToNode
380 **
381 ** 1) writes to a circular buffer with wraparound.
382 ** 2)in case of an overflow, it overwrites the oldest unread data.
383 **
384 *********************************************************************************/
385static void
386_WriteToNode (
387 gcsDEBUGFS_Node* Node ,
388 caddr_t Buf ,
389 int Length
390 )
391{
392 int bytes_copied = 0 ;
393 int overflow = 0 ;
394 int n ;
395
396 if ( Length + gcmkNODE_QLEN ( Node ) >= ( Node->size - 1 ) )
397 {
398 overflow = 1 ;
399 }
400
401 while ( Length )
402 {
403 /* how many contiguous bytes are available from the write point to
404 * the end of the circular buffer? */
405 n = gcmkMIN ( Length , Node->size - Node->write_point ) ;
406 memcpy ( Node->data + Node->write_point , Buf + bytes_copied , n ) ;
407 bytes_copied += n ;
408 Length -= n ;
409 Node->write_point = ( Node->write_point + n ) % Node->size ;
410 }
411
412 /* if there is an overflow, reset the read point to read whatever is
413 * the oldest data that we have, that has not yet been
414 * overwritten. */
415 if ( overflow )
416 {
417 Node->read_point = ( Node->write_point + 1 ) % Node->size ;
418 }
419}
420
421/*******************************************************************************
422 **
423 ** PRINTING UTILITY (START)
424 **
425 *******************************************************************************/
426
427/*******************************************************************************
428 **
429 ** _GetArgumentSize
430 **
431 **
432 *******************************************************************************/
433static gctINT
434_GetArgumentSize (
435 IN gctCONST_STRING Message
436 )
437{
438 gctINT i , count ;
439
440 for ( i = 0 , count = 0 ; Message[i] ; i += 1 )
441 {
442 if ( Message[i] == '%' )
443 {
444 count += 1 ;
445 }
446 }
447 return count * sizeof (unsigned int ) ;
448}
449
450/*******************************************************************************
451 **
452 ** _AppendString
453 **
454 **
455 *******************************************************************************/
456static ssize_t
457_AppendString (
458 IN gcsDEBUGFS_Node* Node ,
459 IN gctCONST_STRING String ,
460 IN int Length
461 )
462{
463 int n ;
464
465 /* if the message is longer than the buffer, just take the beginning
466 * of it, in hopes that the reader (if any) will have time to read
467 * before we wrap around and obliterate it */
468 n = gcmkMIN ( Length , Node->size - 1 ) ;
469
470 gcmkLOCKSECTION(traceLock);
471
472 /* now copy it into the circular buffer and free our temp copy */
473 _WriteToNode ( Node , (caddr_t)String , n ) ;
474
475 gcmkUNLOCKSECTION(traceLock);
476
477 return n ;
478}
479
480/*******************************************************************************
481 **
482 ** _DebugFSPrint
483 **
484 **
485 *******************************************************************************/
486static ssize_t
487_DebugFSPrint (
488 IN unsigned int ArgumentSize ,
489 IN const char* Message ,
490 IN gctDBGARGS * Arguments
491
492 )
493{
494 char buffer[MAX_LINE_SIZE] ;
495 int len ;
496 ssize_t res=0;
497
498 len = vsnprintf ( buffer , sizeof (buffer ) , Message , *( va_list * ) Arguments ) ;
499
500 buffer[len] = '\0' ;
501
502 /* Add end-of-line if missing. */
503 if ( buffer[len - 1] != '\n' )
504 {
505 buffer[len ++] = '\n' ;
506 buffer[len] = '\0' ;
507 }
508
509 res = _AppendString ( gc_dbgfs.currentNode , buffer , len ) ;
510
511 wake_up_interruptible ( gcmkNODE_READQ ( gc_dbgfs.currentNode ) ) ; /* blocked in read*/
512
513 return res;
514}
515
516/*******************************************************************************
517 **
518 ** LINUX SYSTEM FUNCTIONS (START)
519 **
520 *******************************************************************************/
521
522/*******************************************************************************
523 **
524 ** find the vivlog structure associated with an inode.
525 ** returns a pointer to the structure if found, NULL if not found
526 **
527 *******************************************************************************/
528static gcsDEBUGFS_Node*
529_GetNodeInfo (
530 IN struct inode *Inode
531 )
532{
533 gcsDEBUGFS_Node* node ;
534
535 if ( Inode == NULL )
536 return NULL ;
537
538 for ( node = gc_dbgfs.linkedlist ; node != NULL ; node = node->next )
539 if ( node->filen->d_inode->i_ino == Inode->i_ino )
540 return node ;
541
542 return NULL ;
543}
544
545/*******************************************************************************
546 **
547 ** _DebugFSRead
548 **
549 *******************************************************************************/
550static ssize_t
551_DebugFSRead (
552 struct file *file ,
553 char __user * buffer ,
554 size_t length ,
555 loff_t * offset
556 )
557{
558 int retval ;
559 caddr_t data_to_return ;
560 gcsDEBUGFS_Node* node ;
561 /* get the metadata about this emlog */
562 if ( ( node = _GetNodeInfo ( file_inode(file) ) ) == NULL )
563 {
564 printk ( "debugfs_read: record not found\n" ) ;
565 return - EIO ;
566 }
567
568 gcmkLOCKSECTION(traceLock);
569
570 /* wait until there's data available (unless we do nonblocking reads) */
571 while (!gcmkNODE_QLEN(node))
572 {
573 gcmkUNLOCKSECTION(traceLock);
574
575 if ( file->f_flags & O_NONBLOCK )
576 {
577 return - EAGAIN ;
578 }
579
580 if ( wait_event_interruptible ( ( *( gcmkNODE_READQ ( node ) ) ) , ( *offset < gcmkNODE_FIRST_EMPTY_BYTE ( node ) ) ) )
581 {
582 return - ERESTARTSYS ; /* signal: tell the fs layer to handle it */
583 }
584
585 gcmkLOCKSECTION(traceLock);
586 }
587
588 data_to_return = _ReadFromNode ( node , &length , offset ) ;
589
590 gcmkUNLOCKSECTION(traceLock);
591
592 if ( data_to_return == NULL )
593 {
594 retval = 0 ;
595 goto unlock ;
596 }
597 if ( copy_to_user ( buffer , data_to_return , length ) > 0 )
598 {
599 retval = - EFAULT ;
600 }
601 else
602 {
603 retval = length ;
604 }
605unlock:
606
607 wake_up_interruptible ( gcmkNODE_WRITEQ ( node ) ) ;
608 return retval ;
609}
610
611/*******************************************************************************
612 **
613 **_DebugFSWrite
614 **
615 *******************************************************************************/
616static ssize_t
617_DebugFSWrite (
618 struct file *file ,
619 const char __user * buffer ,
620 size_t length ,
621 loff_t * offset
622 )
623{
624 caddr_t message = NULL ;
625 int n ;
626 gcsDEBUGFS_Node*node ;
627
628 /* get the metadata about this log */
629 if ( ( node = _GetNodeInfo ( file_inode(file) ) ) == NULL )
630 {
631 return - EIO ;
632 }
633
634 if ( down_interruptible ( gcmkNODE_SEM ( node ) ) )
635 {
636 return - ERESTARTSYS ;
637 }
638
639 /* if the message is longer than the buffer, just take the beginning
640 * of it, in hopes that the reader (if any) will have time to read
641 * before we wrap around and obliterate it */
642 n = gcmkMIN ( length , node->size - 1 ) ;
643
644 /* make sure we have the memory for it */
645 if ( ( message = kmalloc ( n , GFP_KERNEL ) ) == NULL )
646 {
647 up ( gcmkNODE_SEM ( node ) ) ;
648 return - ENOMEM ;
649 }
650
651
652 /* copy into our temp buffer */
653 if ( copy_from_user ( message , buffer , n ) > 0 )
654 {
655 up ( gcmkNODE_SEM ( node ) ) ;
656 kfree ( message ) ;
657 return - EFAULT ;
658 }
659
660 /* now copy it into the circular buffer and free our temp copy */
661 _WriteToNode ( node , message , n ) ;
662
663 kfree ( message ) ;
664 up ( gcmkNODE_SEM ( node ) ) ;
665
666 /* wake up any readers that might be waiting for the data. we call
667 * schedule in the vague hope that a reader will run before the
668 * writer's next write, to avoid losing data. */
669 wake_up_interruptible ( gcmkNODE_READQ ( node ) ) ;
670
671 return n ;
672}
673
674int dumpProcess = 0;
675
676void
677_PrintCounter(
678 struct seq_file *file,
679 gcsDATABASE_COUNTERS * counter,
680 gctCONST_STRING Name
681 )
682{
683 seq_printf(file,"Counter: %s\n", Name);
684
685 seq_printf(file,"%-9s%10s","", "All");
686
687 seq_printf(file, "\n");
688
689 seq_printf(file,"%-9s","Current");
690
691 seq_printf(file,"%10lld", counter->bytes);
692
693 seq_printf(file, "\n");
694
695 seq_printf(file,"%-9s","Maximum");
696
697 seq_printf(file,"%10lld", counter->maxBytes);
698
699 seq_printf(file, "\n");
700
701 seq_printf(file,"%-9s","Total");
702
703 seq_printf(file,"%10lld", counter->totalBytes);
704
705 seq_printf(file, "\n");
706}
707
708void
709_ShowCounters(
710 struct seq_file *file,
711 gcsDATABASE_PTR database
712 )
713{
714 gctUINT i = 0;
715 gcsDATABASE_COUNTERS * counter;
716 gcsDATABASE_COUNTERS * nonPaged;
717
718 static gctCONST_STRING surfaceTypes[] = {
719 "UNKNOWN",
720 "Index",
721 "Vertex",
722 "Texture",
723 "RT",
724 "Depth",
725 "Bitmap",
726 "TS",
727 "Image",
728 "Mask",
729 "Scissor",
730 "HZDepth",
731 };
732
733 /* Get pointer to counters. */
734 counter = &database->vidMem;
735
736 nonPaged = &database->nonPaged;
737
738 seq_printf(file,"Counter: vidMem (for each surface type)\n");
739
740 seq_printf(file,"%-9s%10s","", "All");
741
742 for (i = 1; i < gcvSURF_NUM_TYPES; i++)
743 {
744 counter = &database->vidMemType[i];
745
746 seq_printf(file, "%10s",surfaceTypes[i]);
747 }
748
749 seq_printf(file, "\n");
750
751 seq_printf(file,"%-9s","Current");
752
753 seq_printf(file,"%10lld", database->vidMem.bytes);
754
755 for (i = 1; i < gcvSURF_NUM_TYPES; i++)
756 {
757 counter = &database->vidMemType[i];
758
759 seq_printf(file,"%10lld", counter->bytes);
760 }
761
762 seq_printf(file, "\n");
763
764 seq_printf(file,"%-9s","Maximum");
765
766 seq_printf(file,"%10lld", database->vidMem.maxBytes);
767
768 for (i = 1; i < gcvSURF_NUM_TYPES; i++)
769 {
770 counter = &database->vidMemType[i];
771
772 seq_printf(file,"%10lld", counter->maxBytes);
773 }
774
775 seq_printf(file, "\n");
776
777 seq_printf(file,"%-9s","Total");
778
779 seq_printf(file,"%10lld", database->vidMem.totalBytes);
780
781 for (i = 1; i < gcvSURF_NUM_TYPES; i++)
782 {
783 counter = &database->vidMemType[i];
784
785 seq_printf(file,"%10lld", counter->totalBytes);
786 }
787
788 seq_printf(file, "\n");
789
790 seq_printf(file,"Counter: vidMem (for each pool)\n");
791
792 seq_printf(file,"%-9s%10s","", "All");
793
794 for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
795 {
796 seq_printf(file, "%10d", i);
797 }
798
799 seq_printf(file, "\n");
800
801 seq_printf(file,"%-9s","Current");
802
803 seq_printf(file,"%10lld", database->vidMem.bytes);
804
805 for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
806 {
807 counter = &database->vidMemPool[i];
808
809 seq_printf(file,"%10lld", counter->bytes);
810 }
811
812 seq_printf(file, "\n");
813
814 seq_printf(file,"%-9s","Maximum");
815
816 seq_printf(file,"%10lld", database->vidMem.maxBytes);
817
818 for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
819 {
820 counter = &database->vidMemPool[i];
821
822 seq_printf(file,"%10lld", counter->maxBytes);
823 }
824
825 seq_printf(file, "\n");
826
827 seq_printf(file,"%-9s","Total");
828
829 seq_printf(file,"%10lld", database->vidMem.totalBytes);
830
831 for (i = 1; i < gcvPOOL_NUMBER_OF_POOLS; i++)
832 {
833 counter = &database->vidMemPool[i];
834
835 seq_printf(file,"%10lld", counter->totalBytes);
836 }
837
838 seq_printf(file, "\n");
839
840 /* Print nonPaged. */
841 _PrintCounter(file, &database->nonPaged, "nonPaged");
842 _PrintCounter(file, &database->contiguous, "contiguous");
843 _PrintCounter(file, &database->mapUserMemory, "mapUserMemory");
844 _PrintCounter(file, &database->mapMemory, "mapMemory");
845}
846
847static int vidmem_show(struct seq_file *file, void *unused)
848{
849 gceSTATUS status;
850 gcsDATABASE_PTR database;
851 gckGALDEVICE device = file->private;
852
853 gckKERNEL kernel = _GetValidKernel(device);
854
855 /* Find the database. */
856 gcmkONERROR(
857 gckKERNEL_FindDatabase(kernel, dumpProcess, gcvFALSE, &database));
858
859 seq_printf(file, "VidMem Usage (Process %d):\n", dumpProcess);
860
861 _ShowCounters(file, database);
862
863 return 0;
864
865OnError:
866 return 0;
867}
868
869static int
870vidmem_open(
871 struct inode *inode,
872 struct file *file
873 )
874{
875 return single_open(file, vidmem_show, inode->i_private);
876}
877
878static ssize_t
879vidmem_write(
880 struct file *file,
881 const char __user *buf,
882 size_t count,
883 loff_t *pos
884 )
885{
886 dumpProcess = simple_strtol(buf, NULL, 0);
887 return count;
888}
889
890/*******************************************************************************
891 **
892 ** File Operations Table
893 **
894 *******************************************************************************/
895static const struct file_operations debugfs_operations = {
896 .owner = THIS_MODULE ,
897 .read = _DebugFSRead ,
898 .write = _DebugFSWrite ,
899} ;
900
901static const struct file_operations vidmem_operations = {
902 .owner = THIS_MODULE ,
903 .open = vidmem_open,
904 .read = seq_read,
905 .write = vidmem_write,
906 .llseek = seq_lseek,
907} ;
908
909/*******************************************************************************
910 **
911 ** INTERFACE FUNCTIONS (START)
912 **
913 *******************************************************************************/
914
915/*******************************************************************************
916 **
917 ** gckDEBUGFS_IsEnabled
918 **
919 **
920 ** INPUT:
921 **
922 ** OUTPUT:
923 **
924 *******************************************************************************/
925
926
927gctINT
928gckDEBUGFS_IsEnabled ( void )
929{
930 return gc_dbgfs.isInited ;
931}
932/*******************************************************************************
933 **
934 ** gckDEBUGFS_Initialize
935 **
936 **
937 ** INPUT:
938 **
939 ** OUTPUT:
940 **
941 *******************************************************************************/
942
943gctINT
944gckDEBUGFS_Initialize ( void )
945{
946 if ( ! gc_dbgfs.isInited )
947 {
948 gc_dbgfs.linkedlist = gcvNULL ;
949 gc_dbgfs.currentNode = gcvNULL ;
950 gc_dbgfs.isInited = 1 ;
951 }
952 return gc_dbgfs.isInited ;
953}
954/*******************************************************************************
955 **
956 ** gckDEBUGFS_Terminate
957 **
958 **
959 ** INPUT:
960 **
961 ** OUTPUT:
962 **
963 *******************************************************************************/
964
965gctINT
966gckDEBUGFS_Terminate ( void )
967{
968 gcsDEBUGFS_Node * next = gcvNULL ;
969 gcsDEBUGFS_Node * temp = gcvNULL ;
970 if ( gc_dbgfs.isInited )
971 {
972 temp = gc_dbgfs.linkedlist ;
973 while ( temp != gcvNULL )
974 {
975 next = temp->next ;
976 gckDEBUGFS_FreeNode ( temp ) ;
977 kfree ( temp ) ;
978 temp = next ;
979 }
980 gc_dbgfs.isInited = 0 ;
981 }
982 return 0 ;
983}
984
985
986/*******************************************************************************
987 **
988 ** gckDEBUGFS_CreateNode
989 **
990 **
991 ** INPUT:
992 **
993 ** OUTPUT:
994 **
995 ** gckDEBUGFS_FreeNode * Device
996 ** Pointer to a variable receiving the gcsDEBUGFS_Node object pointer on
997 ** success.
998 *********************************************************************************/
999
1000gctINT
1001gckDEBUGFS_CreateNode (
1002 IN gctPOINTER Device,
1003 IN gctINT SizeInKB ,
1004 IN struct dentry * Root ,
1005 IN gctCONST_STRING NodeName ,
1006 OUT gcsDEBUGFS_Node **Node
1007 )
1008{
1009 gcsDEBUGFS_Node*node ;
1010 /* allocate space for our metadata and initialize it */
1011 if ( ( node = kmalloc ( sizeof (gcsDEBUGFS_Node ) , GFP_KERNEL ) ) == NULL )
1012 goto struct_malloc_failed ;
1013
1014 /*Zero it out*/
1015 memset ( node , 0 , sizeof (gcsDEBUGFS_Node ) ) ;
1016
1017 /*Init the sync primitives*/
1018#if defined(DECLARE_WAIT_QUEUE_HEAD)
1019 init_waitqueue_head ( gcmkNODE_READQ ( node ) ) ;
1020#else
1021 init_waitqueue ( gcmkNODE_READQ ( node ) ) ;
1022#endif
1023
1024#if defined(DECLARE_WAIT_QUEUE_HEAD)
1025 init_waitqueue_head ( gcmkNODE_WRITEQ ( node ) ) ;
1026#else
1027 init_waitqueue ( gcmkNODE_WRITEQ ( node ) ) ;
1028#endif
1029 sema_init ( gcmkNODE_SEM ( node ) , 1 ) ;
1030 /*End the sync primitives*/
1031
1032 /*creating the debug file system*/
1033 node->parent = Root;
1034
1035 if (SizeInKB)
1036 {
1037 /* figure out how much of a buffer this should be and allocate the buffer */
1038 node->size = 1024 * SizeInKB ;
1039 if ( ( node->data = ( char * ) vmalloc ( sizeof (char ) * node->size ) ) == NULL )
1040 goto data_malloc_failed ;
1041
1042 node->tempSize = 0;
1043 node->temp = NULL;
1044
1045 /*creating the file*/
1046 node->filen = debugfs_create_file(NodeName, S_IRUGO|S_IWUSR, node->parent, NULL,
1047 &debugfs_operations);
1048 }
1049
1050 node->vidmem
1051 = debugfs_create_file("vidmem", S_IRUGO|S_IWUSR, node->parent, Device, &vidmem_operations);
1052
1053 /* add it to our linked list */
1054 node->next = gc_dbgfs.linkedlist ;
1055 gc_dbgfs.linkedlist = node ;
1056
1057
1058 /* pass the struct back */
1059 *Node = node ;
1060 return 0 ;
1061
1062
1063data_malloc_failed:
1064 kfree ( node ) ;
1065struct_malloc_failed:
1066 return - ENOMEM ;
1067}
1068
1069/*******************************************************************************
1070 **
1071 ** gckDEBUGFS_FreeNode
1072 **
1073 **
1074 ** INPUT:
1075 **
1076 ** OUTPUT:
1077 **
1078 *******************************************************************************/
1079void
1080gckDEBUGFS_FreeNode (
1081 IN gcsDEBUGFS_Node * Node
1082 )
1083{
1084
1085 gcsDEBUGFS_Node **ptr ;
1086
1087 if ( Node == NULL )
1088 {
1089 printk ( "null passed to free_vinfo\n" ) ;
1090 return ;
1091 }
1092
1093 down ( gcmkNODE_SEM ( Node ) ) ;
1094 /*free data*/
1095 vfree ( Node->data ) ;
1096
1097 kfree(Node->temp);
1098
1099 /*Close Debug fs*/
1100 if (Node->vidmem)
1101 {
1102 debugfs_remove(Node->vidmem);
1103 }
1104
1105 if ( Node->filen )
1106 {
1107 debugfs_remove ( Node->filen ) ;
1108 }
1109
1110 /* now delete the node from the linked list */
1111 ptr = & ( gc_dbgfs.linkedlist ) ;
1112 while ( *ptr != Node )
1113 {
1114 if ( ! *ptr )
1115 {
1116 printk ( "corrupt info list!\n" ) ;
1117 break ;
1118 }
1119 else
1120 ptr = & ( ( **ptr ).next ) ;
1121 }
1122 *ptr = Node->next ;
1123 up ( gcmkNODE_SEM ( Node ) ) ;
1124}
1125
1126/*******************************************************************************
1127 **
1128 ** gckDEBUGFS_SetCurrentNode
1129 **
1130 **
1131 ** INPUT:
1132 **
1133 ** OUTPUT:
1134 **
1135 *******************************************************************************/
1136void
1137gckDEBUGFS_SetCurrentNode (
1138 IN gcsDEBUGFS_Node * Node
1139 )
1140{
1141 gc_dbgfs.currentNode = Node ;
1142}
1143
1144/*******************************************************************************
1145 **
1146 ** gckDEBUGFS_GetCurrentNode
1147 **
1148 **
1149 ** INPUT:
1150 **
1151 ** OUTPUT:
1152 **
1153 *******************************************************************************/
1154void
1155gckDEBUGFS_GetCurrentNode (
1156 OUT gcsDEBUGFS_Node ** Node
1157 )
1158{
1159 *Node = gc_dbgfs.currentNode ;
1160}
1161
1162/*******************************************************************************
1163 **
1164 ** gckDEBUGFS_Print
1165 **
1166 **
1167 ** INPUT:
1168 **
1169 ** OUTPUT:
1170 **
1171 *******************************************************************************/
1172ssize_t
1173gckDEBUGFS_Print (
1174 IN gctCONST_STRING Message ,
1175 ...
1176 )
1177{
1178 ssize_t _debugfs_res;
1179 gcmkDEBUGFS_PRINT ( _GetArgumentSize ( Message ) , Message ) ;
1180 return _debugfs_res;
1181}
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_debugfs.h b/src/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
new file mode 100755
index 0000000..9a15d77
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_debugfs.h
@@ -0,0 +1,169 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include <stdarg.h>
57
58#ifndef __gc_hal_kernel_debugfs_h_
59#define __gc_hal_kernel_debugfs_h_
60
61 #define MAX_LINE_SIZE 768 /* Max bytes for a line of debug info */
62
63
64 typedef struct _gcsDEBUGFS_Node gcsDEBUGFS_Node;
65
66typedef struct _gcsDEBUGFS_DIR *gckDEBUGFS_DIR;
67typedef struct _gcsDEBUGFS_DIR
68{
69 struct dentry * root;
70 struct list_head nodeList;
71}
72gcsDEBUGFS_DIR;
73
74typedef struct _gcsINFO
75{
76 const char * name;
77 int (*show)(struct seq_file*, void*);
78}
79gcsINFO;
80
81typedef struct _gcsINFO_NODE
82{
83 gcsINFO * info;
84 gctPOINTER device;
85 struct dentry * entry;
86 struct list_head head;
87}
88gcsINFO_NODE;
89
90gceSTATUS
91gckDEBUGFS_DIR_Init(
92 IN gckDEBUGFS_DIR Dir,
93 IN struct dentry *root,
94 IN gctCONST_STRING Name
95 );
96
97gceSTATUS
98gckDEBUGFS_DIR_CreateFiles(
99 IN gckDEBUGFS_DIR Dir,
100 IN gcsINFO * List,
101 IN int count,
102 IN gctPOINTER Data
103 );
104
105gceSTATUS
106gckDEBUGFS_DIR_RemoveFiles(
107 IN gckDEBUGFS_DIR Dir,
108 IN gcsINFO * List,
109 IN int count
110 );
111
112void
113gckDEBUGFS_DIR_Deinit(
114 IN gckDEBUGFS_DIR Dir
115 );
116
117/*******************************************************************************
118 **
119 ** System Related
120 **
121 *******************************************************************************/
122
123gctINT gckDEBUGFS_IsEnabled(void);
124
125gctINT gckDEBUGFS_Initialize(void);
126
127gctINT gckDEBUGFS_Terminate(void);
128
129
130/*******************************************************************************
131 **
132 ** Node Related
133 **
134 *******************************************************************************/
135
136gctINT
137gckDEBUGFS_CreateNode(
138 IN gctPOINTER Device,
139 IN gctINT SizeInKB,
140 IN struct dentry * Root,
141 IN gctCONST_STRING NodeName,
142 OUT gcsDEBUGFS_Node **Node
143 );
144
145void gckDEBUGFS_FreeNode(
146 IN gcsDEBUGFS_Node * Node
147 );
148
149
150
151void gckDEBUGFS_SetCurrentNode(
152 IN gcsDEBUGFS_Node * Node
153 );
154
155
156
157void gckDEBUGFS_GetCurrentNode(
158 OUT gcsDEBUGFS_Node ** Node
159 );
160
161
162ssize_t gckDEBUGFS_Print(
163 IN gctCONST_STRING Message,
164 ...
165 );
166
167#endif
168
169
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_device.c b/src/hal/os/linux/kernel/gc_hal_kernel_device.c
new file mode 100755
index 0000000..f7ee2c6
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_device.c
@@ -0,0 +1,2337 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include <linux/pagemap.h>
58#include <linux/seq_file.h>
59#include <linux/mman.h>
60#include <linux/slab.h>
61
62#define _GC_OBJ_ZONE gcvZONE_DEVICE
63
64#define DEBUG_FILE "galcore_trace"
65#define PARENT_FILE "gpu"
66
67#define gcdDEBUG_FS_WARN "Experimental debug entry, may be removed in future release, do NOT rely on it!\n"
68
69#ifdef FLAREON
70 static struct dove_gpio_irq_handler gc500_handle;
71#endif
72
73/******************************************************************************\
74******************************** Debugfs Support *******************************
75\******************************************************************************/
76
77/******************************************************************************\
78***************************** DEBUG SHOW FUNCTIONS *****************************
79\******************************************************************************/
80
81int gc_info_show(struct seq_file* m, void* data)
82{
83 gcsINFO_NODE *node = m->private;
84 gckGALDEVICE device = node->device;
85 int i = 0;
86 gceCHIPMODEL chipModel;
87 gctUINT32 chipRevision;
88
89 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
90 {
91 if (device->irqLines[i] != -1)
92 {
93 {
94 chipModel = device->kernels[i]->hardware->identity.chipModel;
95 chipRevision = device->kernels[i]->hardware->identity.chipRevision;
96 }
97
98 seq_printf(m, "gpu : %d\n", i);
99 seq_printf(m, "model : %4x\n", chipModel);
100 seq_printf(m, "revision : %4x\n", chipRevision);
101 seq_printf(m, "\n");
102 }
103 }
104
105 return 0;
106}
107
108int gc_clients_show(struct seq_file* m, void* data)
109{
110 gcsINFO_NODE *node = m->private;
111 gckGALDEVICE device = node->device;
112
113 gckKERNEL kernel = _GetValidKernel(device);
114
115 gcsDATABASE_PTR database;
116 gctINT i, pid;
117 gctUINT8 name[24];
118
119 seq_printf(m, "%-8s%s\n", "PID", "NAME");
120 seq_printf(m, "------------------------\n");
121
122 /* Acquire the database mutex. */
123 gcmkVERIFY_OK(
124 gckOS_AcquireMutex(kernel->os, kernel->db->dbMutex, gcvINFINITE));
125
126 /* Walk the databases. */
127 for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
128 {
129 for (database = kernel->db->db[i];
130 database != gcvNULL;
131 database = database->next)
132 {
133 pid = database->processID;
134
135 gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
136
137 gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
138
139 seq_printf(m, "%-8d%s\n", pid, name);
140 }
141 }
142
143 /* Release the database mutex. */
144 gcmkVERIFY_OK(gckOS_ReleaseMutex(kernel->os, kernel->db->dbMutex));
145
146 /* Success. */
147 return 0;
148}
149
150static void
151_CounterAdd(
152 gcsDATABASE_COUNTERS * Dest,
153 gcsDATABASE_COUNTERS * Src
154 )
155{
156 Dest->bytes += Src->bytes;
157 Dest->maxBytes += Src->maxBytes;
158 Dest->totalBytes += Src->totalBytes;
159}
160
161static void
162_CounterPrint(
163 gcsDATABASE_COUNTERS * Counter,
164 gctCONST_STRING Name,
165 struct seq_file* m
166 )
167{
168 seq_printf(m, " %s:\n", Name);
169 seq_printf(m, " Used : %10llu B\n", Counter->bytes);
170}
171
172int gc_meminfo_show(struct seq_file* m, void* data)
173{
174 gcsINFO_NODE *node = m->private;
175 gckGALDEVICE device = node->device;
176 gckKERNEL kernel = _GetValidKernel(device);
177 gckVIDMEM memory;
178 gceSTATUS status;
179 gcsDATABASE_PTR database;
180 gctUINT32 i;
181
182 gctUINT32 free = 0, used = 0, total = 0;
183
184 gcsDATABASE_COUNTERS contiguousCounter = {0, 0, 0};
185 gcsDATABASE_COUNTERS virtualCounter = {0, 0, 0};
186 gcsDATABASE_COUNTERS nonPagedCounter = {0, 0, 0};
187
188 status = gckKERNEL_GetVideoMemoryPool(kernel, gcvPOOL_SYSTEM, &memory);
189
190 if (gcmIS_SUCCESS(status))
191 {
192 gcmkVERIFY_OK(
193 gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE));
194
195 free = memory->freeBytes;
196 used = memory->bytes - memory->freeBytes;
197 total = memory->bytes;
198
199 gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex));
200 }
201
202 seq_printf(m, "VIDEO MEMORY:\n");
203 seq_printf(m, " gcvPOOL_SYSTEM:\n");
204 seq_printf(m, " Free : %10u B\n", free);
205 seq_printf(m, " Used : %10u B\n", used);
206 seq_printf(m, " Total : %10u B\n", total);
207
208 /* Acquire the database mutex. */
209 gcmkVERIFY_OK(
210 gckOS_AcquireMutex(kernel->os, kernel->db->dbMutex, gcvINFINITE));
211
212 /* Walk the databases. */
213 for (i = 0; i < gcmCOUNTOF(kernel->db->db); ++i)
214 {
215 for (database = kernel->db->db[i];
216 database != gcvNULL;
217 database = database->next)
218 {
219 gcsDATABASE_COUNTERS * counter = &database->vidMemPool[gcvPOOL_CONTIGUOUS];
220 _CounterAdd(&contiguousCounter, counter);
221
222 counter = &database->vidMemPool[gcvPOOL_VIRTUAL];
223 _CounterAdd(&virtualCounter, counter);
224
225
226 counter = &database->nonPaged;
227 _CounterAdd(&nonPagedCounter, counter);
228 }
229 }
230
231 /* Release the database mutex. */
232 gcmkVERIFY_OK(gckOS_ReleaseMutex(kernel->os, kernel->db->dbMutex));
233
234 _CounterPrint(&contiguousCounter, "gcvPOOL_CONTIGUOUS", m);
235 _CounterPrint(&virtualCounter, "gcvPOOL_VIRTUAL", m);
236
237 seq_printf(m, "\n");
238
239 seq_printf(m, "NON PAGED MEMORY:\n");
240 seq_printf(m, " Used : %10llu B\n", nonPagedCounter.bytes);
241
242 return 0;
243}
244
245static int
246_ShowRecord(
247 IN struct seq_file *file,
248 IN gcsDATABASE_RECORD_PTR record
249 )
250{
251 seq_printf(file, "%4d%8d%16p%16p%16zu\n",
252 record->type,
253 record->kernel->core,
254 record->data,
255 record->physical,
256 record->bytes
257 );
258
259 return 0;
260}
261
262static int
263_ShowRecords(
264 IN struct seq_file *File,
265 IN gcsDATABASE_PTR Database
266 )
267{
268 gctUINT i;
269
270 seq_printf(File, "Records:\n");
271
272 seq_printf(File, "%s%8s%16s%16s%16s\n",
273 "Type", "GPU", "Data", "Physical", "Bytes");
274
275 for (i = 0; i < gcmCOUNTOF(Database->list); i++)
276 {
277 gcsDATABASE_RECORD_PTR record = Database->list[i];
278
279 while (record != NULL)
280 {
281 _ShowRecord(File, record);
282 record = record->next;
283 }
284 }
285
286 return 0;
287}
288
289void
290_ShowCounters(
291 struct seq_file *File,
292 gcsDATABASE_PTR Database
293 );
294
295static void
296_ShowProcess(
297 IN struct seq_file *File,
298 IN gcsDATABASE_PTR Database
299 )
300{
301 gctINT pid;
302 gctUINT8 name[24];
303
304 /* Process ID and name */
305 pid = Database->processID;
306 gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
307 gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
308
309 seq_printf(File, "--------------------------------------------------------------------------------\n");
310 seq_printf(File, "Process: %-8d %s\n", pid, name);
311
312 /* Detailed records */
313 _ShowRecords(File, Database);
314
315 seq_printf(File, "Counters:\n");
316
317 _ShowCounters(File, Database);
318}
319
320static void
321_ShowProcesses(
322 IN struct seq_file * file,
323 IN gckKERNEL Kernel
324 )
325{
326 gcsDATABASE_PTR database;
327 gctINT i;
328 static gctUINT64 idleTime = 0;
329
330 /* Acquire the database mutex. */
331 gcmkVERIFY_OK(
332 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
333
334 if (Kernel->db->idleTime)
335 {
336 /* Record idle time if DB upated. */
337 idleTime = Kernel->db->idleTime;
338 Kernel->db->idleTime = 0;
339 }
340
341 /* Idle time since last call */
342 seq_printf(file, "GPU Idle: %llu ns\n", idleTime);
343
344 /* Walk the databases. */
345 for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
346 {
347 for (database = Kernel->db->db[i];
348 database != gcvNULL;
349 database = database->next)
350 {
351 _ShowProcess(file, database);
352 }
353 }
354
355 /* Release the database mutex. */
356 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
357}
358
359static int
360gc_db_show(struct seq_file *m, void *data)
361{
362 gcsINFO_NODE *node = m->private;
363 gckGALDEVICE device = node->device;
364 gckKERNEL kernel = _GetValidKernel(device);
365 _ShowProcesses(m, kernel);
366 return 0 ;
367}
368
369static int
370gc_version_show(struct seq_file *m, void *data)
371{
372 gcsINFO_NODE *node = m->private;
373 gckGALDEVICE device = node->device;
374 gcsPLATFORM * platform = device->platform;
375 gctCONST_STRING name;
376
377 seq_printf(m, "%s built at %s\n", gcvVERSION_STRING, HOST);
378
379 if (platform->ops->name)
380 {
381 platform->ops->name(platform, &name);
382 seq_printf(m, "Platform path: %s\n", name);
383 }
384 else
385 {
386 seq_printf(m, "Code path: %s\n", __FILE__);
387 }
388
389 return 0 ;
390}
391
392/*******************************************************************************
393**
394** Show PM state timer.
395**
396** Entry is called as 'idle' for compatible reason, it shows more information
397** than idle actually.
398**
399** Start: Start time of this counting period.
400** End: End time of this counting peroid.
401** On: Time GPU stays in gcvPOWER_0N.
402** Off: Time GPU stays in gcvPOWER_0FF.
403** Idle: Time GPU stays in gcvPOWER_IDLE.
404** Suspend: Time GPU stays in gcvPOWER_SUSPEND.
405*/
406static int
407gc_idle_show(struct seq_file *m, void *data)
408{
409 gcsINFO_NODE *node = m->private;
410 gckGALDEVICE device = node->device;
411 gckKERNEL kernel = _GetValidKernel(device);
412
413 gctUINT64 start;
414 gctUINT64 end;
415 gctUINT64 on;
416 gctUINT64 off;
417 gctUINT64 idle;
418 gctUINT64 suspend;
419
420 gckHARDWARE_QueryStateTimer(kernel->hardware, &start, &end, &on, &off, &idle, &suspend);
421
422 /* Idle time since last call */
423 seq_printf(m, "Start: %llu ns\n", start);
424 seq_printf(m, "End: %llu ns\n", end);
425 seq_printf(m, "On: %llu ns\n", on);
426 seq_printf(m, "Off: %llu ns\n", off);
427 seq_printf(m, "Idle: %llu ns\n", idle);
428 seq_printf(m, "Suspend: %llu ns\n", suspend);
429
430 return 0 ;
431}
432
433extern void
434_DumpState(
435 IN gckKERNEL Kernel
436 );
437
438static int
439gc_dump_trigger_show(struct seq_file *m, void *data)
440{
441 gcsINFO_NODE *node = m->private;
442 gckGALDEVICE device = node->device;
443 gckKERNEL kernel = _GetValidKernel(device);
444
445 seq_printf(m, gcdDEBUG_FS_WARN);
446
447 seq_printf(m, "Get dump from /proc/kmsg or /sys/kernel/debug/gc/galcore_trace\n");
448
449 if (kernel->hardware->powerManagement == gcvFALSE)
450 {
451 _DumpState(kernel);
452 }
453
454 return 0;
455}
456
457static gcsINFO InfoList[] =
458{
459 {"info", gc_info_show},
460 {"clients", gc_clients_show},
461 {"meminfo", gc_meminfo_show},
462 {"idle", gc_idle_show},
463 {"database", gc_db_show},
464 {"version", gc_version_show},
465 {"dump_trigger", gc_dump_trigger_show},
466};
467
468static gceSTATUS
469_DebugfsInit(
470 IN gckGALDEVICE Device
471 )
472{
473 gceSTATUS status;
474
475 gckDEBUGFS_DIR dir = &Device->debugfsDir;
476
477 gcmkONERROR(gckDEBUGFS_DIR_Init(dir, gcvNULL, "gc"));
478
479 gcmkONERROR(gckDEBUGFS_DIR_CreateFiles(dir, InfoList, gcmCOUNTOF(InfoList), Device));
480
481 return gcvSTATUS_OK;
482
483OnError:
484 return status;
485}
486
487static void
488_DebugfsCleanup(
489 IN gckGALDEVICE Device
490 )
491{
492 gckDEBUGFS_DIR dir = &Device->debugfsDir;
493
494 if (Device->debugfsDir.root)
495 {
496 gcmkVERIFY_OK(gckDEBUGFS_DIR_RemoveFiles(dir, InfoList, gcmCOUNTOF(InfoList)));
497
498 gckDEBUGFS_DIR_Deinit(dir);
499 }
500}
501
502
503/******************************************************************************\
504*************************** Memory Allocation Wrappers *************************
505\******************************************************************************/
506
507static gceSTATUS
508_AllocateMemory(
509 IN gckGALDEVICE Device,
510 IN gctSIZE_T Bytes,
511 OUT gctPOINTER *Logical,
512 OUT gctPHYS_ADDR *Physical,
513 OUT gctUINT32 *PhysAddr
514 )
515{
516 gceSTATUS status;
517
518 gcmkHEADER_ARG("Device=0x%x Bytes=%lu", Device, Bytes);
519
520 gcmkVERIFY_ARGUMENT(Device != NULL);
521 gcmkVERIFY_ARGUMENT(Logical != NULL);
522 gcmkVERIFY_ARGUMENT(Physical != NULL);
523 gcmkVERIFY_ARGUMENT(PhysAddr != NULL);
524
525 gcmkONERROR(gckOS_AllocateContiguous(
526 Device->os, gcvFALSE, &Bytes, Physical, Logical
527 ));
528
529 *PhysAddr = ((PLINUX_MDL)*Physical)->dmaHandle;
530
531 /* Success. */
532 gcmkFOOTER_ARG(
533 "*Logical=0x%x *Physical=0x%x *PhysAddr=0x%08x",
534 *Logical, *Physical, *PhysAddr
535 );
536
537 return gcvSTATUS_OK;
538
539OnError:
540 gcmkFOOTER();
541 return status;
542}
543
544static gceSTATUS
545_FreeMemory(
546 IN gckGALDEVICE Device,
547 IN gctPOINTER Logical,
548 IN gctPHYS_ADDR Physical)
549{
550 gceSTATUS status;
551
552 gcmkHEADER_ARG("Device=0x%x Logical=0x%x Physical=0x%x",
553 Device, Logical, Physical);
554
555 gcmkVERIFY_ARGUMENT(Device != NULL);
556
557 status = gckOS_FreeContiguous(
558 Device->os, Physical, Logical,
559 ((PLINUX_MDL) Physical)->numPages * PAGE_SIZE
560 );
561
562 gcmkFOOTER();
563 return status;
564}
565
566
567
568/******************************************************************************\
569******************************* Interrupt Handler ******************************
570\******************************************************************************/
571#if gcdMULTI_GPU_AFFINITY
572static irqreturn_t isrRoutine3D0(int irq, void *ctxt)
573{
574 gceSTATUS status;
575 gckGALDEVICE device;
576
577 device = (gckGALDEVICE) ctxt;
578
579 /* Call kernel interrupt notification. */
580 status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
581
582 if (gcmIS_SUCCESS(status))
583 {
584 up(&device->semas[gcvCORE_MAJOR]);
585
586 return IRQ_HANDLED;
587 }
588
589 return IRQ_NONE;
590}
591
592static int threadRoutine3D0(void *ctxt)
593{
594 gckGALDEVICE device = (gckGALDEVICE) ctxt;
595
596 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
597 "Starting isr Thread with extension=%p",
598 device);
599
600 for (;;)
601 {
602 static int down;
603
604 down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
605 if (down); /*To make gcc 4.6 happye*/
606
607 if (device->killThread == gcvTRUE)
608 {
609 /* The daemon exits. */
610 while (!kthread_should_stop())
611 {
612 gckOS_Delay(device->os, 1);
613 }
614
615 return 0;
616 }
617
618 gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
619 gcvNOTIFY_INTERRUPT,
620 gcvFALSE);
621 }
622}
623
624static irqreturn_t isrRoutine3D1(int irq, void *ctxt)
625{
626 gceSTATUS status;
627 gckGALDEVICE device;
628
629 device = (gckGALDEVICE) ctxt;
630
631 /* Call kernel interrupt notification. */
632 status = gckKERNEL_Notify(device->kernels[gcvCORE_OCL], gcvNOTIFY_INTERRUPT, gcvTRUE);
633
634 if (gcmIS_SUCCESS(status))
635 {
636 up(&device->semas[gcvCORE_OCL]);
637
638 return IRQ_HANDLED;
639 }
640
641 return IRQ_NONE;
642}
643
644static int threadRoutine3D1(void *ctxt)
645{
646 gckGALDEVICE device = (gckGALDEVICE) ctxt;
647
648 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
649 "Starting isr Thread with extension=%p",
650 device);
651
652 for (;;)
653 {
654 static int down;
655
656 down = down_interruptible(&device->semas[gcvCORE_OCL]);
657 if (down); /*To make gcc 4.6 happye*/
658
659 if (device->killThread == gcvTRUE)
660 {
661 /* The daemon exits. */
662 while (!kthread_should_stop())
663 {
664 gckOS_Delay(device->os, 1);
665 }
666
667 return 0;
668 }
669
670 gckKERNEL_Notify(device->kernels[gcvCORE_OCL],
671 gcvNOTIFY_INTERRUPT,
672 gcvFALSE);
673 }
674}
675#else
676static irqreturn_t isrRoutine(int irq, void *ctxt)
677{
678 gceSTATUS status;
679 gckGALDEVICE device;
680
681 device = (gckGALDEVICE) ctxt;
682
683 /* Call kernel interrupt notification. */
684 status = gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR], gcvNOTIFY_INTERRUPT, gcvTRUE);
685
686 if (gcmIS_SUCCESS(status))
687 {
688 up(&device->semas[gcvCORE_MAJOR]);
689
690 return IRQ_HANDLED;
691 }
692
693 return IRQ_NONE;
694}
695
696static int threadRoutine(void *ctxt)
697{
698 gckGALDEVICE device = (gckGALDEVICE) ctxt;
699
700 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
701 "Starting isr Thread with extension=%p",
702 device);
703
704 for (;;)
705 {
706 static int down;
707
708 down = down_interruptible(&device->semas[gcvCORE_MAJOR]);
709 if (down); /*To make gcc 4.6 happye*/
710
711 if (device->killThread == gcvTRUE)
712 {
713 /* The daemon exits. */
714 while (!kthread_should_stop())
715 {
716 gckOS_Delay(device->os, 1);
717 }
718
719 return 0;
720 }
721
722 gckKERNEL_Notify(device->kernels[gcvCORE_MAJOR],
723 gcvNOTIFY_INTERRUPT,
724 gcvFALSE);
725 }
726}
727#endif
728
729static irqreturn_t isrRoutine2D(int irq, void *ctxt)
730{
731 gceSTATUS status;
732 gckGALDEVICE device;
733
734 device = (gckGALDEVICE) ctxt;
735
736 /* Call kernel interrupt notification. */
737 status = gckKERNEL_Notify(device->kernels[gcvCORE_2D],
738 gcvNOTIFY_INTERRUPT,
739 gcvTRUE);
740 if (gcmIS_SUCCESS(status))
741 {
742 up(&device->semas[gcvCORE_2D]);
743
744 return IRQ_HANDLED;
745 }
746
747 return IRQ_NONE;
748}
749
750static int threadRoutine2D(void *ctxt)
751{
752 gckGALDEVICE device = (gckGALDEVICE) ctxt;
753
754 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
755 "Starting isr Thread with extension=%p",
756 device);
757
758 for (;;)
759 {
760 static int down;
761
762 down = down_interruptible(&device->semas[gcvCORE_2D]);
763 if (down); /*To make gcc 4.6 happye*/
764
765 if (device->killThread == gcvTRUE)
766 {
767 /* The daemon exits. */
768 while (!kthread_should_stop())
769 {
770 gckOS_Delay(device->os, 1);
771 }
772
773 return 0;
774 }
775 gckKERNEL_Notify(device->kernels[gcvCORE_2D],
776 gcvNOTIFY_INTERRUPT,
777 gcvFALSE);
778 }
779}
780
781static irqreturn_t isrRoutineVG(int irq, void *ctxt)
782{
783 return IRQ_NONE;
784}
785
786static int threadRoutineVG(void *ctxt)
787{
788 gckGALDEVICE device = (gckGALDEVICE) ctxt;
789
790 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DRIVER,
791 "Starting isr Thread with extension=%p",
792 device);
793
794 for (;;)
795 {
796 static int down;
797
798 down = down_interruptible(&device->semas[gcvCORE_VG]);
799 if (down); /*To make gcc 4.6 happye*/
800
801 if (device->killThread == gcvTRUE)
802 {
803 /* The daemon exits. */
804 while (!kthread_should_stop())
805 {
806 gckOS_Delay(device->os, 1);
807 }
808
809 return 0;
810 }
811 gckKERNEL_Notify(device->kernels[gcvCORE_VG],
812 gcvNOTIFY_INTERRUPT,
813 gcvFALSE);
814 }
815}
816
817/******************************************************************************\
818******************************* gckGALDEVICE Code ******************************
819\******************************************************************************/
820
821/*******************************************************************************
822**
823** gckGALDEVICE_Construct
824**
825** Constructor.
826**
827** INPUT:
828**
829** OUTPUT:
830**
831** gckGALDEVICE * Device
832** Pointer to a variable receiving the gckGALDEVICE object pointer on
833** success.
834*/
835gceSTATUS
836gckGALDEVICE_Construct(
837#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
838 IN gctINT IrqLine3D0,
839 IN gctUINT32 RegisterMemBase3D0,
840 IN gctSIZE_T RegisterMemSize3D0,
841 IN gctINT IrqLine3D1,
842 IN gctUINT32 RegisterMemBase3D1,
843 IN gctSIZE_T RegisterMemSize3D1,
844#else
845 IN gctINT IrqLine,
846 IN gctUINT32 RegisterMemBase,
847 IN gctSIZE_T RegisterMemSize,
848#endif
849 IN gctINT IrqLine2D,
850 IN gctUINT32 RegisterMemBase2D,
851 IN gctSIZE_T RegisterMemSize2D,
852 IN gctINT IrqLineVG,
853 IN gctUINT32 RegisterMemBaseVG,
854 IN gctSIZE_T RegisterMemSizeVG,
855 IN gctUINT32 ContiguousBase,
856 IN gctSIZE_T ContiguousSize,
857 IN gctSIZE_T BankSize,
858 IN gctINT FastClear,
859 IN gctINT Compression,
860 IN gctUINT32 PhysBaseAddr,
861 IN gctUINT32 PhysSize,
862 IN gctINT Signal,
863 IN gctUINT LogFileSize,
864 IN gctINT PowerManagement,
865 IN gctINT GpuProfiler,
866 IN gcsDEVICE_CONSTRUCT_ARGS * Args,
867 OUT gckGALDEVICE *Device
868 )
869{
870 gctUINT32 internalBaseAddress = 0, internalAlignment = 0;
871 gctUINT32 externalBaseAddress = 0, externalAlignment = 0;
872 gctUINT32 horizontalTileSize, verticalTileSize;
873 struct resource* mem_region;
874 gctUINT32 physAddr;
875 gctUINT32 physical;
876 gckGALDEVICE device;
877 gceSTATUS status;
878 gctINT32 i;
879 gceHARDWARE_TYPE type;
880 gckDB sharedDB = gcvNULL;
881 gckKERNEL kernel = gcvNULL;
882
883#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
884 gcmkHEADER_ARG("IrqLine3D0=%d RegisterMemBase3D0=0x%08x RegisterMemSize3D0=%u "
885 "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
886 "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
887 "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
888 "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
889 IrqLine3D0, RegisterMemBase3D0, RegisterMemSize3D0,
890 IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
891 IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
892 ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
893 PhysBaseAddr, PhysSize, Signal);
894#else
895 gcmkHEADER_ARG("IrqLine=%d RegisterMemBase=0x%08x RegisterMemSize=%u "
896 "IrqLine2D=%d RegisterMemBase2D=0x%08x RegisterMemSize2D=%u "
897 "IrqLineVG=%d RegisterMemBaseVG=0x%08x RegisterMemSizeVG=%u "
898 "ContiguousBase=0x%08x ContiguousSize=%lu BankSize=%lu "
899 "FastClear=%d Compression=%d PhysBaseAddr=0x%x PhysSize=%d Signal=%d",
900 IrqLine, RegisterMemBase, RegisterMemSize,
901 IrqLine2D, RegisterMemBase2D, RegisterMemSize2D,
902 IrqLineVG, RegisterMemBaseVG, RegisterMemSizeVG,
903 ContiguousBase, ContiguousSize, BankSize, FastClear, Compression,
904 PhysBaseAddr, PhysSize, Signal);
905#endif
906
907#if gcdDISABLE_CORES_2D3D
908 IrqLine = -1;
909 IrqLine2D = -1;
910#endif
911
912 /* Allocate device structure. */
913 device = kmalloc(sizeof(struct _gckGALDEVICE), GFP_KERNEL | __GFP_NOWARN);
914
915 if (!device)
916 {
917 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
918 }
919
920 memset(device, 0, sizeof(struct _gckGALDEVICE));
921
922 device->dbgNode = gcvNULL;
923
924 device->platform = Args->platform;
925
926 /* set up the contiguous memory */
927 device->contiguousSize = ContiguousSize;
928
929 gcmkONERROR(_DebugfsInit(device));
930
931 if (gckDEBUGFS_CreateNode(
932 device, LogFileSize, device->debugfsDir.root ,DEBUG_FILE, &(device->dbgNode)))
933 {
934 gcmkTRACE_ZONE(
935 gcvLEVEL_ERROR, gcvZONE_DRIVER,
936 "%s(%d): Failed to create the debug file system %s/%s \n",
937 __FUNCTION__, __LINE__,
938 PARENT_FILE, DEBUG_FILE
939 );
940 }
941 else if (LogFileSize)
942 {
943 gckDEBUGFS_SetCurrentNode(device->dbgNode);
944 }
945
946#if gcdMULTI_GPU_AFFINITY
947 if (IrqLine3D0 != -1)
948 {
949 device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase3D0;
950 device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize3D0;
951 }
952
953 if (IrqLine3D1 != -1)
954 {
955 device->requestedRegisterMemBases[gcvCORE_OCL] = RegisterMemBase3D1;
956 device->requestedRegisterMemSizes[gcvCORE_OCL] = RegisterMemSize3D1;
957 }
958#else
959 if (IrqLine != -1)
960 {
961 device->requestedRegisterMemBases[gcvCORE_MAJOR] = RegisterMemBase;
962 device->requestedRegisterMemSizes[gcvCORE_MAJOR] = RegisterMemSize;
963 }
964#endif
965
966 if (IrqLine2D != -1)
967 {
968 device->requestedRegisterMemBases[gcvCORE_2D] = RegisterMemBase2D;
969 device->requestedRegisterMemSizes[gcvCORE_2D] = RegisterMemSize2D;
970 }
971
972 if (IrqLineVG != -1)
973 {
974 device->requestedRegisterMemBases[gcvCORE_VG] = RegisterMemBaseVG;
975 device->requestedRegisterMemSizes[gcvCORE_VG] = RegisterMemSizeVG;
976 }
977#if gcdENABLE_DEC_COMPRESSION
978 {
979 device->requestedRegisterMemBases[gcvCORE_DEC] = Args->registerMemBaseDEC300;
980 device->requestedRegisterMemSizes[gcvCORE_DEC] = Args->registerMemSizeDEC300;
981 }
982#endif
983
984
985 device->requestedContiguousBase = 0;
986 device->requestedContiguousSize = 0;
987
988 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
989 {
990 {
991 physical = device->requestedRegisterMemBases[i];
992
993 /* Set up register memory region. */
994 if (physical != 0)
995 {
996
997 if ( Args->registerMemMapped )
998 {
999 device->registerBases[i] = Args->registerMemAddress;
1000 device->requestedRegisterMemBases[i] = 0;
1001
1002 } else {
1003
1004 mem_region = request_mem_region(physical,
1005 device->requestedRegisterMemSizes[i],
1006 "galcore register region");
1007
1008 if (mem_region == gcvNULL)
1009 {
1010 gcmkTRACE_ZONE(
1011 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1012 "%s(%d): Failed to claim %lu bytes @ 0x%08X\n",
1013 __FUNCTION__, __LINE__,
1014 physical, device->requestedRegisterMemSizes[i]
1015 );
1016
1017 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1018 }
1019
1020 device->registerBases[i] = (gctPOINTER) ioremap_nocache(
1021 physical, device->requestedRegisterMemSizes[i]);
1022
1023 if (device->registerBases[i] == gcvNULL)
1024 {
1025 gcmkTRACE_ZONE(
1026 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1027 "%s(%d): Unable to map %ld bytes @ 0x%08X\n",
1028 __FUNCTION__, __LINE__,
1029 physical, device->requestedRegisterMemSizes[i]
1030 );
1031
1032 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1033 }
1034 }
1035
1036 physical += device->requestedRegisterMemSizes[i];
1037
1038 }
1039 }
1040 }
1041
1042 /* Set the base address */
1043 device->baseAddress = device->physBase = PhysBaseAddr;
1044 device->physSize = PhysSize;
1045 device->mmu = Args->mmu;
1046
1047 /* Construct the gckOS object. */
1048 gcmkONERROR(gckOS_Construct(device, &device->os));
1049
1050#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
1051 if (IrqLine3D0 != -1)
1052#else
1053 if (IrqLine != -1)
1054#endif
1055 {
1056 /* Construct the gckKERNEL object. */
1057 gcmkONERROR(gckKERNEL_Construct(
1058 device->os, gcvCORE_MAJOR, device,
1059 gcvNULL, &device->kernels[gcvCORE_MAJOR]));
1060
1061 sharedDB = device->kernels[gcvCORE_MAJOR]->db;
1062
1063 /* Initialize core mapping */
1064 for (i = 0; i < 8; i++)
1065 {
1066 device->coreMapping[i] = gcvCORE_MAJOR;
1067 }
1068
1069 /* Setup the ISR manager. */
1070 gcmkONERROR(gckHARDWARE_SetIsrManager(
1071 device->kernels[gcvCORE_MAJOR]->hardware,
1072 (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
1073 (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
1074 device
1075 ));
1076
1077 gcmkONERROR(gckHARDWARE_SetFastClear(
1078 device->kernels[gcvCORE_MAJOR]->hardware, FastClear, Compression
1079 ));
1080
1081 gcmkONERROR(gckHARDWARE_SetPowerManagement(
1082 device->kernels[gcvCORE_MAJOR]->hardware, PowerManagement
1083 ));
1084
1085#if gcdENABLE_FSCALE_VAL_ADJUST
1086 gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
1087 device->kernels[gcvCORE_MAJOR]->hardware, Args->gpu3DMinClock
1088 ));
1089#endif
1090
1091 gcmkONERROR(gckHARDWARE_SetGpuProfiler(
1092 device->kernels[gcvCORE_MAJOR]->hardware, GpuProfiler
1093 ));
1094
1095 gcmkVERIFY_OK(gckKERNEL_SetRecovery(
1096 device->kernels[gcvCORE_MAJOR], Args->recovery, Args->stuckDump
1097 ));
1098
1099#if COMMAND_PROCESSOR_VERSION == 1
1100 /* Start the command queue. */
1101 gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_MAJOR]->command));
1102#endif
1103 }
1104 else
1105 {
1106 device->kernels[gcvCORE_MAJOR] = gcvNULL;
1107 }
1108
1109#if gcdMULTI_GPU_AFFINITY
1110 if (IrqLine3D1 != -1)
1111 {
1112 /* Construct the gckKERNEL object. */
1113 gcmkONERROR(gckKERNEL_Construct(
1114 device->os, gcvCORE_OCL, device,
1115 gcvNULL, &device->kernels[gcvCORE_OCL]));
1116
1117 if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_OCL]->db;
1118
1119 /* Initialize core mapping */
1120 if (device->kernels[gcvCORE_MAJOR] == gcvNULL)
1121 {
1122 for (i = 0; i < 8; i++)
1123 {
1124 device->coreMapping[i] = gcvCORE_OCL;
1125 }
1126 }
1127 else
1128 {
1129 device->coreMapping[gcvHARDWARE_OCL] = gcvCORE_OCL;
1130 }
1131
1132 /* Setup the ISR manager. */
1133 gcmkONERROR(gckHARDWARE_SetIsrManager(
1134 device->kernels[gcvCORE_OCL]->hardware,
1135 (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR,
1136 (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR,
1137 device
1138 ));
1139
1140 gcmkONERROR(gckHARDWARE_SetFastClear(
1141 device->kernels[gcvCORE_OCL]->hardware, FastClear, Compression
1142 ));
1143
1144#if gcdENABLE_FSCALE_VAL_ADJUST
1145 gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
1146 device->kernels[gcvCORE_OCL]->hardware, Args->gpu3DMinClock
1147 ));
1148#endif
1149
1150 gcmkONERROR(gckHARDWARE_SetPowerManagement(
1151 device->kernels[gcvCORE_OCL]->hardware, PowerManagement
1152 ));
1153
1154#if COMMAND_PROCESSOR_VERSION == 1
1155 /* Start the command queue. */
1156 gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_OCL]->command));
1157#endif
1158 }
1159 else
1160 {
1161 device->kernels[gcvCORE_OCL] = gcvNULL;
1162 }
1163#endif
1164
1165 if (IrqLine2D != -1)
1166 {
1167 gcmkONERROR(gckKERNEL_Construct(
1168 device->os, gcvCORE_2D, device,
1169 sharedDB, &device->kernels[gcvCORE_2D]));
1170
1171 if (sharedDB == gcvNULL) sharedDB = device->kernels[gcvCORE_2D]->db;
1172
1173 /* Verify the hardware type */
1174 gcmkONERROR(gckHARDWARE_GetType(device->kernels[gcvCORE_2D]->hardware, &type));
1175
1176 if (type != gcvHARDWARE_2D)
1177 {
1178 gcmkTRACE_ZONE(
1179 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1180 "%s(%d): Unexpected hardware type: %d\n",
1181 __FUNCTION__, __LINE__,
1182 type
1183 );
1184
1185 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
1186 }
1187
1188 /* Initialize core mapping */
1189 if (device->kernels[gcvCORE_MAJOR] == gcvNULL
1190#if gcdMULTI_GPU_AFFINITY
1191 && device->kernels[gcvCORE_OCL] == gcvNULL
1192#endif
1193 )
1194 {
1195 for (i = 0; i < 8; i++)
1196 {
1197 device->coreMapping[i] = gcvCORE_2D;
1198 }
1199 }
1200 else
1201 {
1202 device->coreMapping[gcvHARDWARE_2D] = gcvCORE_2D;
1203 }
1204
1205 /* Setup the ISR manager. */
1206 gcmkONERROR(gckHARDWARE_SetIsrManager(
1207 device->kernels[gcvCORE_2D]->hardware,
1208 (gctISRMANAGERFUNC) gckGALDEVICE_Setup_ISR_2D,
1209 (gctISRMANAGERFUNC) gckGALDEVICE_Release_ISR_2D,
1210 device
1211 ));
1212
1213 gcmkONERROR(gckHARDWARE_SetPowerManagement(
1214 device->kernels[gcvCORE_2D]->hardware, PowerManagement
1215 ));
1216
1217#if gcdENABLE_FSCALE_VAL_ADJUST
1218 gcmkONERROR(gckHARDWARE_SetMinFscaleValue(
1219 device->kernels[gcvCORE_2D]->hardware, 1
1220 ));
1221#endif
1222
1223 gcmkVERIFY_OK(gckKERNEL_SetRecovery(
1224 device->kernels[gcvCORE_2D], Args->recovery, Args->stuckDump
1225 ));
1226
1227#if COMMAND_PROCESSOR_VERSION == 1
1228 /* Start the command queue. */
1229 gcmkONERROR(gckCOMMAND_Start(device->kernels[gcvCORE_2D]->command));
1230#endif
1231 }
1232 else
1233 {
1234 device->kernels[gcvCORE_2D] = gcvNULL;
1235 }
1236
1237 if (IrqLineVG != -1)
1238 {
1239 }
1240 else
1241 {
1242 device->kernels[gcvCORE_VG] = gcvNULL;
1243 }
1244
1245 /* Initialize the ISR. */
1246#if gcdMULTI_GPU_AFFINITY
1247 device->irqLines[gcvCORE_MAJOR] = IrqLine3D0;
1248 device->irqLines[gcvCORE_OCL] = IrqLine3D1;
1249#else
1250 device->irqLines[gcvCORE_MAJOR] = IrqLine;
1251#endif
1252 device->irqLines[gcvCORE_2D] = IrqLine2D;
1253 device->irqLines[gcvCORE_VG] = IrqLineVG;
1254
1255 /* Initialize the kernel thread semaphores. */
1256 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1257 {
1258 {
1259 if (device->irqLines[i] != -1) sema_init(&device->semas[i], 0);
1260 }
1261 }
1262
1263 device->signal = Signal;
1264
1265 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1266 {
1267 if (device->kernels[i] != gcvNULL) break;
1268 }
1269
1270 if (i == gcdMAX_GPU_COUNT)
1271 {
1272 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
1273 }
1274
1275 {
1276 /* Query the ceiling of the system memory. */
1277 gcmkONERROR(gckHARDWARE_QuerySystemMemory(
1278 device->kernels[i]->hardware,
1279 &device->systemMemorySize,
1280 &device->systemMemoryBaseAddress
1281 ));
1282
1283 /* query the amount of video memory */
1284 gcmkONERROR(gckHARDWARE_QueryMemory(
1285 device->kernels[i]->hardware,
1286 &device->internalSize, &internalBaseAddress, &internalAlignment,
1287 &device->externalSize, &externalBaseAddress, &externalAlignment,
1288 &horizontalTileSize, &verticalTileSize
1289 ));
1290 }
1291
1292
1293 /* Grab the first availiable kernel */
1294 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1295 {
1296 {
1297 if (device->irqLines[i] != -1)
1298 {
1299 kernel = device->kernels[i];
1300 break;
1301 }
1302 }
1303 }
1304
1305 /* Set up the internal memory region. */
1306 if (device->internalSize > 0)
1307 {
1308 status = gckVIDMEM_Construct(
1309 device->os,
1310 internalBaseAddress, device->internalSize, internalAlignment,
1311 0, &device->internalVidMem
1312 );
1313
1314 if (gcmIS_ERROR(status))
1315 {
1316 /* Error, disable internal heap. */
1317 device->internalSize = 0;
1318 }
1319 else
1320 {
1321 /* Map internal memory. */
1322 device->internalLogical
1323 = (gctPOINTER) ioremap_nocache(physical, device->internalSize);
1324
1325 if (device->internalLogical == gcvNULL)
1326 {
1327 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1328 }
1329
1330 device->internalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
1331 device->internalPhysicalName = gcmPTR_TO_NAME(device->internalPhysical);
1332 physical += device->internalSize;
1333 }
1334 }
1335
1336 if (device->externalSize > 0)
1337 {
1338 /* create the external memory heap */
1339 status = gckVIDMEM_Construct(
1340 device->os,
1341 externalBaseAddress, device->externalSize, externalAlignment,
1342 0, &device->externalVidMem
1343 );
1344
1345 if (gcmIS_ERROR(status))
1346 {
1347 /* Error, disable internal heap. */
1348 device->externalSize = 0;
1349 }
1350 else
1351 {
1352 /* Map external memory. */
1353 device->externalLogical
1354 = (gctPOINTER) ioremap_nocache(physical, device->externalSize);
1355
1356 if (device->externalLogical == gcvNULL)
1357 {
1358 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1359 }
1360
1361 device->externalPhysical = (gctPHYS_ADDR)(gctUINTPTR_T) physical;
1362 device->externalPhysicalName = gcmPTR_TO_NAME(device->externalPhysical);
1363 physical += device->externalSize;
1364 }
1365 }
1366
1367 /* set up the contiguous memory */
1368 device->contiguousSize = ContiguousSize;
1369
1370 if (ContiguousSize > 0)
1371 {
1372 if (ContiguousBase == 0)
1373 {
1374 while (device->contiguousSize > 0)
1375 {
1376 /* Allocate contiguous memory. */
1377 status = _AllocateMemory(
1378 device,
1379 device->contiguousSize,
1380 &device->contiguousBase,
1381 &device->contiguousPhysical,
1382 &physAddr
1383 );
1384
1385 if (gcmIS_SUCCESS(status))
1386 {
1387 device->contiguousPhysicalName = gcmPTR_TO_NAME(device->contiguousPhysical);
1388 status = gckVIDMEM_Construct(
1389 device->os,
1390 physAddr | device->systemMemoryBaseAddress,
1391 device->contiguousSize,
1392 64,
1393 BankSize,
1394 &device->contiguousVidMem
1395 );
1396
1397 if (gcmIS_SUCCESS(status))
1398 {
1399 break;
1400 }
1401
1402 gcmkONERROR(_FreeMemory(
1403 device,
1404 device->contiguousBase,
1405 device->contiguousPhysical
1406 ));
1407
1408 gcmRELEASE_NAME(device->contiguousPhysicalName);
1409 device->contiguousBase = gcvNULL;
1410 device->contiguousPhysical = gcvNULL;
1411 }
1412
1413 if (device->contiguousSize <= (4 << 20))
1414 {
1415 device->contiguousSize = 0;
1416 }
1417 else
1418 {
1419 device->contiguousSize -= (4 << 20);
1420 }
1421 }
1422 }
1423 else
1424 {
1425 /* Create the contiguous memory heap. */
1426 status = gckVIDMEM_Construct(
1427 device->os,
1428 ContiguousBase | device->systemMemoryBaseAddress,
1429 ContiguousSize,
1430 64, BankSize,
1431 &device->contiguousVidMem
1432 );
1433
1434 if (gcmIS_ERROR(status))
1435 {
1436 /* Error, disable contiguous memory pool. */
1437 device->contiguousVidMem = gcvNULL;
1438 device->contiguousSize = 0;
1439 }
1440 else
1441 {
1442 if (Args->contiguousRequested == gcvFALSE)
1443 {
1444 mem_region = request_mem_region(
1445 ContiguousBase, ContiguousSize, "galcore managed memory"
1446 );
1447
1448 if (mem_region == gcvNULL)
1449 {
1450 gcmkTRACE_ZONE(
1451 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1452 "%s(%d): Failed to claim %ld bytes @ 0x%08X\n",
1453 __FUNCTION__, __LINE__,
1454 ContiguousSize, ContiguousBase
1455 );
1456
1457 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1458 }
1459 }
1460
1461 device->requestedContiguousBase = ContiguousBase;
1462 device->requestedContiguousSize = ContiguousSize;
1463 device->contiguousRequested = Args->contiguousRequested;
1464
1465 device->contiguousPhysical = gcvNULL;
1466 device->contiguousPhysicalName = 0;
1467 device->contiguousSize = ContiguousSize;
1468 device->contiguousMapped = gcvTRUE;
1469 }
1470 }
1471 }
1472
1473 /* Return pointer to the device. */
1474 *Device = device;
1475
1476 gcmkFOOTER_ARG("*Device=0x%x", * Device);
1477 return gcvSTATUS_OK;
1478
1479OnError:
1480 /* Roll back. */
1481 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
1482
1483 gcmkFOOTER();
1484 return status;
1485}
1486
1487/*******************************************************************************
1488**
1489** gckGALDEVICE_Destroy
1490**
1491** Class destructor.
1492**
1493** INPUT:
1494**
1495** Nothing.
1496**
1497** OUTPUT:
1498**
1499** Nothing.
1500**
1501** RETURNS:
1502**
1503** Nothing.
1504*/
1505gceSTATUS
1506gckGALDEVICE_Destroy(
1507 gckGALDEVICE Device)
1508{
1509 gctINT i;
1510 gckKERNEL kernel = gcvNULL;
1511
1512 gcmkHEADER_ARG("Device=0x%x", Device);
1513
1514 if (Device != gcvNULL)
1515 {
1516 /* Grab the first availiable kernel */
1517 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1518 {
1519 {
1520 if (Device->irqLines[i] != -1)
1521 {
1522 kernel = Device->kernels[i];
1523 break;
1524 }
1525 }
1526 }
1527
1528 if (Device->internalPhysicalName != 0)
1529 {
1530 gcmRELEASE_NAME(Device->internalPhysicalName);
1531 Device->internalPhysicalName = 0;
1532 }
1533 if (Device->externalPhysicalName != 0)
1534 {
1535 gcmRELEASE_NAME(Device->externalPhysicalName);
1536 Device->externalPhysicalName = 0;
1537 }
1538 if (Device->contiguousPhysicalName != 0)
1539 {
1540 gcmRELEASE_NAME(Device->contiguousPhysicalName);
1541 Device->contiguousPhysicalName = 0;
1542 }
1543
1544
1545 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1546 {
1547 if (Device->kernels[i] != gcvNULL)
1548 {
1549 /* Destroy the gckKERNEL object. */
1550 gcmkVERIFY_OK(gckKERNEL_Destroy(Device->kernels[i]));
1551 Device->kernels[i] = gcvNULL;
1552 }
1553 }
1554
1555 if (Device->internalLogical != gcvNULL)
1556 {
1557 /* Unmap the internal memory. */
1558 iounmap(Device->internalLogical);
1559 Device->internalLogical = gcvNULL;
1560 }
1561
1562 if (Device->internalVidMem != gcvNULL)
1563 {
1564 /* Destroy the internal heap. */
1565 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->internalVidMem));
1566 Device->internalVidMem = gcvNULL;
1567 }
1568
1569 if (Device->externalLogical != gcvNULL)
1570 {
1571 /* Unmap the external memory. */
1572 iounmap(Device->externalLogical);
1573 Device->externalLogical = gcvNULL;
1574 }
1575
1576 if (Device->externalVidMem != gcvNULL)
1577 {
1578 /* destroy the external heap */
1579 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->externalVidMem));
1580 Device->externalVidMem = gcvNULL;
1581 }
1582
1583 if (Device->contiguousBase != gcvNULL)
1584 {
1585 if (Device->contiguousMapped == gcvFALSE)
1586 {
1587 gcmkVERIFY_OK(_FreeMemory(
1588 Device,
1589 Device->contiguousBase,
1590 Device->contiguousPhysical
1591 ));
1592 }
1593
1594 Device->contiguousBase = gcvNULL;
1595 Device->contiguousPhysical = gcvNULL;
1596 }
1597
1598 if (Device->requestedContiguousBase != 0
1599 && Device->contiguousRequested == gcvFALSE
1600 )
1601 {
1602 release_mem_region(Device->requestedContiguousBase, Device->requestedContiguousSize);
1603 Device->requestedContiguousBase = 0;
1604 Device->requestedContiguousSize = 0;
1605 }
1606
1607 if (Device->contiguousVidMem != gcvNULL)
1608 {
1609 /* Destroy the contiguous heap. */
1610 gcmkVERIFY_OK(gckVIDMEM_Destroy(Device->contiguousVidMem));
1611 Device->contiguousVidMem = gcvNULL;
1612 }
1613
1614 if (Device->dbgNode)
1615 {
1616 gckDEBUGFS_FreeNode(Device->dbgNode);
1617
1618 if(Device->dbgNode != gcvNULL)
1619 {
1620 kfree(Device->dbgNode);
1621 Device->dbgNode = gcvNULL;
1622 }
1623 }
1624
1625 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1626 {
1627 {
1628 if (Device->registerBases[i] != gcvNULL)
1629 {
1630 /* Unmap register memory. */
1631 if (Device->requestedRegisterMemBases[i] != 0)
1632 iounmap(Device->registerBases[i]);
1633
1634 if (Device->requestedRegisterMemBases[i] != 0)
1635 {
1636 release_mem_region(Device->requestedRegisterMemBases[i],
1637 Device->requestedRegisterMemSizes[i]);
1638 }
1639
1640 Device->registerBases[i] = gcvNULL;
1641 Device->requestedRegisterMemBases[i] = 0;
1642 Device->requestedRegisterMemSizes[i] = 0;
1643 }
1644 }
1645 }
1646
1647 /* Destroy the gckOS object. */
1648 if (Device->os != gcvNULL)
1649 {
1650 gcmkVERIFY_OK(gckOS_Destroy(Device->os));
1651 Device->os = gcvNULL;
1652 }
1653
1654 _DebugfsCleanup(Device);
1655
1656 /* Free the device. */
1657 kfree(Device);
1658 }
1659
1660 gcmkFOOTER_NO();
1661 return gcvSTATUS_OK;
1662}
1663
1664/*******************************************************************************
1665**
1666** gckGALDEVICE_Setup_ISR
1667**
1668** Start the ISR routine.
1669**
1670** INPUT:
1671**
1672** gckGALDEVICE Device
1673** Pointer to an gckGALDEVICE object.
1674**
1675** OUTPUT:
1676**
1677** Nothing.
1678**
1679** RETURNS:
1680**
1681** gcvSTATUS_OK
1682** Setup successfully.
1683** gcvSTATUS_GENERIC_IO
1684** Setup failed.
1685*/
1686gceSTATUS
1687gckGALDEVICE_Setup_ISR(
1688 IN gckGALDEVICE Device
1689 )
1690{
1691 gceSTATUS status;
1692 gctINT ret = 0;
1693
1694 gcmkHEADER_ARG("Device=0x%x", Device);
1695
1696 gcmkVERIFY_ARGUMENT(Device != NULL);
1697
1698 if (Device->irqLines[gcvCORE_MAJOR] < 0)
1699 {
1700 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1701 }
1702
1703 /* Hook up the isr based on the irq line. */
1704#ifdef FLAREON
1705 gc500_handle.dev_name = "galcore interrupt service";
1706 gc500_handle.dev_id = Device;
1707 gc500_handle.handler = isrRoutine;
1708 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1709 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1710
1711 ret = dove_gpio_request(
1712 DOVE_GPIO0_7, &gc500_handle
1713 );
1714#else
1715#if gcdMULTI_GPU_AFFINITY
1716 ret = request_irq(
1717 Device->irqLines[gcvCORE_MAJOR], isrRoutine3D0, IRQF_SHARED,
1718 "galcore_3d_0", Device
1719 );
1720
1721 if (ret != 0)
1722 {
1723 gcmkTRACE_ZONE(
1724 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1725 "%s(%d): Could not register irq line %d (error=%d)\n",
1726 __FUNCTION__, __LINE__,
1727 Device->irqLines[gcvCORE_MAJOR], ret
1728 );
1729
1730 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1731 }
1732
1733 /* Mark ISR as initialized. */
1734 Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
1735
1736 ret = request_irq(
1737 Device->irqLines[gcvCORE_OCL], isrRoutine3D1, IRQF_SHARED,
1738 "galcore_3d_1", Device
1739 );
1740
1741 if (ret != 0)
1742 {
1743 gcmkTRACE_ZONE(
1744 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1745 "%s(%d): Could not register irq line %d (error=%d)\n",
1746 __FUNCTION__, __LINE__,
1747 Device->irqLines[gcvCORE_OCL], ret
1748 );
1749
1750 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1751 }
1752
1753 /* Mark ISR as initialized. */
1754 Device->isrInitializeds[gcvCORE_OCL] = gcvTRUE;
1755#else
1756 ret = request_irq(
1757 Device->irqLines[gcvCORE_MAJOR], isrRoutine, IRQF_SHARED,
1758 "galcore interrupt service", Device
1759 );
1760
1761 if (ret != 0)
1762 {
1763 gcmkTRACE_ZONE(
1764 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1765 "%s(%d): Could not register irq line %d (error=%d)\n",
1766 __FUNCTION__, __LINE__,
1767 Device->irqLines[gcvCORE_MAJOR], ret
1768 );
1769
1770 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1771 }
1772
1773 /* Mark ISR as initialized. */
1774 Device->isrInitializeds[gcvCORE_MAJOR] = gcvTRUE;
1775#endif
1776#endif
1777
1778 gcmkFOOTER_NO();
1779 return gcvSTATUS_OK;
1780
1781OnError:
1782 gcmkFOOTER();
1783 return status;
1784}
1785
1786gceSTATUS
1787gckGALDEVICE_Setup_ISR_2D(
1788 IN gckGALDEVICE Device
1789 )
1790{
1791 gceSTATUS status;
1792 gctINT ret;
1793
1794 gcmkHEADER_ARG("Device=0x%x", Device);
1795
1796 gcmkVERIFY_ARGUMENT(Device != NULL);
1797
1798 if (Device->irqLines[gcvCORE_2D] < 0)
1799 {
1800 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1801 }
1802
1803 /* Hook up the isr based on the irq line. */
1804#ifdef FLAREON
1805 gc500_handle.dev_name = "galcore interrupt service";
1806 gc500_handle.dev_id = Device;
1807 gc500_handle.handler = isrRoutine2D;
1808 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1809 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1810
1811 ret = dove_gpio_request(
1812 DOVE_GPIO0_7, &gc500_handle
1813 );
1814#else
1815 ret = request_irq(
1816 Device->irqLines[gcvCORE_2D], isrRoutine2D, IRQF_SHARED,
1817 "galcore interrupt service for 2D", Device
1818 );
1819#endif
1820
1821 if (ret != 0)
1822 {
1823 gcmkTRACE_ZONE(
1824 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1825 "%s(%d): Could not register irq line %d (error=%d)\n",
1826 __FUNCTION__, __LINE__,
1827 Device->irqLines[gcvCORE_2D], ret
1828 );
1829
1830 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1831 }
1832
1833 /* Mark ISR as initialized. */
1834 Device->isrInitializeds[gcvCORE_2D] = gcvTRUE;
1835
1836 gcmkFOOTER_NO();
1837 return gcvSTATUS_OK;
1838
1839OnError:
1840 gcmkFOOTER();
1841 return status;
1842}
1843
1844gceSTATUS
1845gckGALDEVICE_Setup_ISR_VG(
1846 IN gckGALDEVICE Device
1847 )
1848{
1849 gceSTATUS status;
1850 gctINT ret;
1851
1852 gcmkHEADER_ARG("Device=0x%x", Device);
1853
1854 gcmkVERIFY_ARGUMENT(Device != NULL);
1855
1856 if (Device->irqLines[gcvCORE_VG] < 0)
1857 {
1858 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1859 }
1860
1861 /* Hook up the isr based on the irq line. */
1862#ifdef FLAREON
1863 gc500_handle.dev_name = "galcore interrupt service";
1864 gc500_handle.dev_id = Device;
1865 gc500_handle.handler = isrRoutineVG;
1866 gc500_handle.intr_gen = GPIO_INTR_LEVEL_TRIGGER;
1867 gc500_handle.intr_trig = GPIO_TRIG_HIGH_LEVEL;
1868
1869 ret = dove_gpio_request(
1870 DOVE_GPIO0_7, &gc500_handle
1871 );
1872#else
1873 ret = request_irq(
1874 Device->irqLines[gcvCORE_VG], isrRoutineVG, IRQF_SHARED,
1875 "galcore interrupt service for 2D", Device
1876 );
1877#endif
1878
1879 if (ret != 0)
1880 {
1881 gcmkTRACE_ZONE(
1882 gcvLEVEL_ERROR, gcvZONE_DRIVER,
1883 "%s(%d): Could not register irq line %d (error=%d)\n",
1884 __FUNCTION__, __LINE__,
1885 Device->irqLines[gcvCORE_VG], ret
1886 );
1887
1888 gcmkONERROR(gcvSTATUS_GENERIC_IO);
1889 }
1890
1891 /* Mark ISR as initialized. */
1892 Device->isrInitializeds[gcvCORE_VG] = gcvTRUE;
1893
1894 gcmkFOOTER_NO();
1895 return gcvSTATUS_OK;
1896
1897OnError:
1898 gcmkFOOTER();
1899 return status;
1900}
1901
1902/*******************************************************************************
1903**
1904** gckGALDEVICE_Release_ISR
1905**
1906** Release the irq line.
1907**
1908** INPUT:
1909**
1910** gckGALDEVICE Device
1911** Pointer to an gckGALDEVICE object.
1912**
1913** OUTPUT:
1914**
1915** Nothing.
1916**
1917** RETURNS:
1918**
1919** Nothing.
1920*/
1921gceSTATUS
1922gckGALDEVICE_Release_ISR(
1923 IN gckGALDEVICE Device
1924 )
1925{
1926 gcmkHEADER_ARG("Device=0x%x", Device);
1927
1928 gcmkVERIFY_ARGUMENT(Device != NULL);
1929
1930 /* release the irq */
1931 if (Device->isrInitializeds[gcvCORE_MAJOR])
1932 {
1933#ifdef FLAREON
1934 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1935#else
1936 free_irq(Device->irqLines[gcvCORE_MAJOR], Device);
1937#endif
1938 Device->isrInitializeds[gcvCORE_MAJOR] = gcvFALSE;
1939 }
1940
1941 gcmkFOOTER_NO();
1942 return gcvSTATUS_OK;
1943}
1944
1945gceSTATUS
1946gckGALDEVICE_Release_ISR_2D(
1947 IN gckGALDEVICE Device
1948 )
1949{
1950 gcmkHEADER_ARG("Device=0x%x", Device);
1951
1952 gcmkVERIFY_ARGUMENT(Device != NULL);
1953
1954 /* release the irq */
1955 if (Device->isrInitializeds[gcvCORE_2D])
1956 {
1957#ifdef FLAREON
1958 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1959#else
1960 free_irq(Device->irqLines[gcvCORE_2D], Device);
1961#endif
1962
1963 Device->isrInitializeds[gcvCORE_2D] = gcvFALSE;
1964 }
1965
1966 gcmkFOOTER_NO();
1967 return gcvSTATUS_OK;
1968}
1969
1970gceSTATUS
1971gckGALDEVICE_Release_ISR_VG(
1972 IN gckGALDEVICE Device
1973 )
1974{
1975 gcmkHEADER_ARG("Device=0x%x", Device);
1976
1977 gcmkVERIFY_ARGUMENT(Device != NULL);
1978
1979 /* release the irq */
1980 if (Device->isrInitializeds[gcvCORE_VG])
1981 {
1982#ifdef FLAREON
1983 dove_gpio_free(DOVE_GPIO0_7, "galcore interrupt service");
1984#else
1985 free_irq(Device->irqLines[gcvCORE_VG], Device);
1986#endif
1987
1988 Device->isrInitializeds[gcvCORE_VG] = gcvFALSE;
1989 }
1990
1991 gcmkFOOTER_NO();
1992 return gcvSTATUS_OK;
1993}
1994
1995/*******************************************************************************
1996**
1997** gckGALDEVICE_Start_Threads
1998**
1999** Start the daemon threads.
2000**
2001** INPUT:
2002**
2003** gckGALDEVICE Device
2004** Pointer to an gckGALDEVICE object.
2005**
2006** OUTPUT:
2007**
2008** Nothing.
2009**
2010** RETURNS:
2011**
2012** gcvSTATUS_OK
2013** Start successfully.
2014** gcvSTATUS_GENERIC_IO
2015** Start failed.
2016*/
2017gceSTATUS
2018gckGALDEVICE_Start_Threads(
2019 IN gckGALDEVICE Device
2020 )
2021{
2022 gceSTATUS status;
2023 struct task_struct * task;
2024
2025 gcmkHEADER_ARG("Device=0x%x", Device);
2026
2027 gcmkVERIFY_ARGUMENT(Device != NULL);
2028
2029#if gcdMULTI_GPU_AFFINITY
2030 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
2031 {
2032 /* Start the kernel thread. */
2033 task = kthread_run(threadRoutine3D0, Device, "galcore_3d_0");
2034
2035 if (IS_ERR(task))
2036 {
2037 gcmkTRACE_ZONE(
2038 gcvLEVEL_ERROR, gcvZONE_DRIVER,
2039 "%s(%d): Could not start the kernel thread.\n",
2040 __FUNCTION__, __LINE__
2041 );
2042
2043 gcmkONERROR(gcvSTATUS_GENERIC_IO);
2044 }
2045
2046 Device->threadCtxts[gcvCORE_MAJOR] = task;
2047 Device->threadInitializeds[gcvCORE_MAJOR] = gcvTRUE;
2048 }
2049
2050 if (Device->kernels[gcvCORE_OCL] != gcvNULL)
2051 {
2052 /* Start the kernel thread. */
2053 task = kthread_run(threadRoutine3D1, Device, "galcore_3d_1");
2054
2055 if (IS_ERR(task))
2056 {
2057 gcmkTRACE_ZONE(
2058 gcvLEVEL_ERROR, gcvZONE_DRIVER,
2059 "%s(%d): Could not start the kernel thread.\n",
2060 __FUNCTION__, __LINE__
2061 );
2062
2063 gcmkONERROR(gcvSTATUS_GENERIC_IO);
2064 }
2065
2066 Device->threadCtxts[gcvCORE_OCL] = task;
2067 Device->threadInitializeds[gcvCORE_OCL] = gcvTRUE;
2068 }
2069#else
2070 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
2071 {
2072 /* Start the kernel thread. */
2073 task = kthread_run(threadRoutine, Device, "galcore daemon thread");
2074
2075 if (IS_ERR(task))
2076 {
2077 gcmkTRACE_ZONE(
2078 gcvLEVEL_ERROR, gcvZONE_DRIVER,
2079 "%s(%d): Could not start the kernel thread.\n",
2080 __FUNCTION__, __LINE__
2081 );
2082
2083 gcmkONERROR(gcvSTATUS_GENERIC_IO);
2084 }
2085
2086 Device->threadCtxts[gcvCORE_MAJOR] = task;
2087 Device->threadInitializeds[gcvCORE_MAJOR] = gcvTRUE;
2088 }
2089#endif
2090
2091 if (Device->kernels[gcvCORE_2D] != gcvNULL)
2092 {
2093 /* Start the kernel thread. */
2094 task = kthread_run(threadRoutine2D, Device, "galcore daemon thread for 2D");
2095
2096 if (IS_ERR(task))
2097 {
2098 gcmkTRACE_ZONE(
2099 gcvLEVEL_ERROR, gcvZONE_DRIVER,
2100 "%s(%d): Could not start the kernel thread.\n",
2101 __FUNCTION__, __LINE__
2102 );
2103
2104 gcmkONERROR(gcvSTATUS_GENERIC_IO);
2105 }
2106
2107 Device->threadCtxts[gcvCORE_2D] = task;
2108 Device->threadInitializeds[gcvCORE_2D] = gcvTRUE;
2109 }
2110 else
2111 {
2112 Device->threadInitializeds[gcvCORE_2D] = gcvFALSE;
2113 }
2114
2115 if (Device->kernels[gcvCORE_VG] != gcvNULL)
2116 {
2117 /* Start the kernel thread. */
2118 task = kthread_run(threadRoutineVG, Device, "galcore daemon thread for VG");
2119
2120 if (IS_ERR(task))
2121 {
2122 gcmkTRACE_ZONE(
2123 gcvLEVEL_ERROR, gcvZONE_DRIVER,
2124 "%s(%d): Could not start the kernel thread.\n",
2125 __FUNCTION__, __LINE__
2126 );
2127
2128 gcmkONERROR(gcvSTATUS_GENERIC_IO);
2129 }
2130
2131 Device->threadCtxts[gcvCORE_VG] = task;
2132 Device->threadInitializeds[gcvCORE_VG] = gcvTRUE;
2133 }
2134 else
2135 {
2136 Device->threadInitializeds[gcvCORE_VG] = gcvFALSE;
2137 }
2138
2139 gcmkFOOTER_NO();
2140 return gcvSTATUS_OK;
2141
2142OnError:
2143 gcmkFOOTER();
2144 return status;
2145}
2146
2147/*******************************************************************************
2148**
2149** gckGALDEVICE_Stop_Threads
2150**
2151** Stop the gal device, including the following actions: stop the daemon
2152** thread, release the irq.
2153**
2154** INPUT:
2155**
2156** gckGALDEVICE Device
2157** Pointer to an gckGALDEVICE object.
2158**
2159** OUTPUT:
2160**
2161** Nothing.
2162**
2163** RETURNS:
2164**
2165** Nothing.
2166*/
2167gceSTATUS
2168gckGALDEVICE_Stop_Threads(
2169 gckGALDEVICE Device
2170 )
2171{
2172 gctINT i;
2173
2174 gcmkHEADER_ARG("Device=0x%x", Device);
2175
2176 gcmkVERIFY_ARGUMENT(Device != NULL);
2177
2178 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
2179 {
2180 {
2181 /* Stop the kernel threads. */
2182 if (Device->threadInitializeds[i])
2183 {
2184 Device->killThread = gcvTRUE;
2185 up(&Device->semas[i]);
2186
2187 kthread_stop(Device->threadCtxts[i]);
2188 Device->threadCtxts[i] = gcvNULL;
2189 Device->threadInitializeds[i] = gcvFALSE;
2190 }
2191 }
2192 }
2193
2194 gcmkFOOTER_NO();
2195 return gcvSTATUS_OK;
2196}
2197
2198/*******************************************************************************
2199**
2200** gckGALDEVICE_Start
2201**
2202** Start the gal device, including the following actions: setup the isr routine
2203** and start the daemoni thread.
2204**
2205** INPUT:
2206**
2207** gckGALDEVICE Device
2208** Pointer to an gckGALDEVICE object.
2209**
2210** OUTPUT:
2211**
2212** Nothing.
2213**
2214** RETURNS:
2215**
2216** gcvSTATUS_OK
2217** Start successfully.
2218*/
2219gceSTATUS
2220gckGALDEVICE_Start(
2221 IN gckGALDEVICE Device
2222 )
2223{
2224 gceSTATUS status;
2225
2226 gcmkHEADER_ARG("Device=0x%x", Device);
2227
2228 /* Start the kernel thread. */
2229 gcmkONERROR(gckGALDEVICE_Start_Threads(Device));
2230
2231 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
2232 {
2233 /* Setup the ISR routine. */
2234 gcmkONERROR(gckGALDEVICE_Setup_ISR(Device));
2235
2236 /* Switch to SUSPEND power state. */
2237 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
2238 Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF_BROADCAST
2239 ));
2240 }
2241
2242 if (Device->kernels[gcvCORE_2D] != gcvNULL)
2243 {
2244 /* Setup the ISR routine. */
2245 gcmkONERROR(gckGALDEVICE_Setup_ISR_2D(Device));
2246
2247 /* Switch to SUSPEND power state. */
2248 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
2249 Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF_BROADCAST
2250 ));
2251 }
2252
2253 if (Device->kernels[gcvCORE_VG] != gcvNULL)
2254 {
2255 /* Setup the ISR routine. */
2256 gcmkONERROR(gckGALDEVICE_Setup_ISR_VG(Device));
2257
2258 }
2259
2260 gcmkFOOTER_NO();
2261 return gcvSTATUS_OK;
2262
2263OnError:
2264 gcmkFOOTER();
2265 return status;
2266}
2267
2268/*******************************************************************************
2269**
2270** gckGALDEVICE_Stop
2271**
2272** Stop the gal device, including the following actions: stop the daemon
2273** thread, release the irq.
2274**
2275** INPUT:
2276**
2277** gckGALDEVICE Device
2278** Pointer to an gckGALDEVICE object.
2279**
2280** OUTPUT:
2281**
2282** Nothing.
2283**
2284** RETURNS:
2285**
2286** Nothing.
2287*/
2288gceSTATUS
2289gckGALDEVICE_Stop(
2290 gckGALDEVICE Device
2291 )
2292{
2293 gceSTATUS status;
2294
2295 gcmkHEADER_ARG("Device=0x%x", Device);
2296
2297 gcmkVERIFY_ARGUMENT(Device != NULL);
2298
2299 if (Device->kernels[gcvCORE_MAJOR] != gcvNULL)
2300 {
2301 /* Switch to OFF power state. */
2302 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
2303 Device->kernels[gcvCORE_MAJOR]->hardware, gcvPOWER_OFF
2304 ));
2305
2306 /* Remove the ISR routine. */
2307 gcmkONERROR(gckGALDEVICE_Release_ISR(Device));
2308 }
2309
2310 if (Device->kernels[gcvCORE_2D] != gcvNULL)
2311 {
2312 /* Setup the ISR routine. */
2313 gcmkONERROR(gckGALDEVICE_Release_ISR_2D(Device));
2314
2315 /* Switch to OFF power state. */
2316 gcmkONERROR(gckHARDWARE_SetPowerManagementState(
2317 Device->kernels[gcvCORE_2D]->hardware, gcvPOWER_OFF
2318 ));
2319 }
2320
2321 if (Device->kernels[gcvCORE_VG] != gcvNULL)
2322 {
2323 /* Setup the ISR routine. */
2324 gcmkONERROR(gckGALDEVICE_Release_ISR_VG(Device));
2325
2326 }
2327
2328 /* Stop the kernel thread. */
2329 gcmkONERROR(gckGALDEVICE_Stop_Threads(Device));
2330
2331 gcmkFOOTER_NO();
2332 return gcvSTATUS_OK;
2333
2334OnError:
2335 gcmkFOOTER();
2336 return status;
2337}
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_device.h b/src/hal/os/linux/kernel/gc_hal_kernel_device.h
new file mode 100755
index 0000000..cd6f1ca
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_device.h
@@ -0,0 +1,264 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_device_h_
57#define __gc_hal_kernel_device_h_
58
59#include "gc_hal_kernel_debugfs.h"
60
61/******************************************************************************\
62******************************* gckGALDEVICE Structure *******************************
63\******************************************************************************/
64
65typedef struct _gckGALDEVICE
66{
67 /* Objects. */
68 gckOS os;
69 gckKERNEL kernels[gcdMAX_GPU_COUNT];
70
71 gcsPLATFORM* platform;
72
73 /* Attributes. */
74 gctSIZE_T internalSize;
75 gctPHYS_ADDR internalPhysical;
76 gctUINT32 internalPhysicalName;
77 gctPOINTER internalLogical;
78 gckVIDMEM internalVidMem;
79 gctSIZE_T externalSize;
80 gctPHYS_ADDR externalPhysical;
81 gctUINT32 externalPhysicalName;
82 gctPOINTER externalLogical;
83 gckVIDMEM externalVidMem;
84 gckVIDMEM contiguousVidMem;
85 gctPOINTER contiguousBase;
86 gctPHYS_ADDR contiguousPhysical;
87 gctUINT32 contiguousPhysicalName;
88 gctSIZE_T contiguousSize;
89 gctBOOL contiguousMapped;
90 gctPOINTER contiguousMappedUser;
91 gctBOOL contiguousRequested;
92 gctSIZE_T systemMemorySize;
93 gctUINT32 systemMemoryBaseAddress;
94 gctPOINTER registerBases[gcdMAX_GPU_COUNT];
95 gctSIZE_T registerSizes[gcdMAX_GPU_COUNT];
96 gctUINT32 baseAddress;
97 gctUINT32 physBase;
98 gctUINT32 physSize;
99 gctBOOL mmu;
100 gctUINT32 requestedRegisterMemBases[gcdMAX_GPU_COUNT];
101 gctSIZE_T requestedRegisterMemSizes[gcdMAX_GPU_COUNT];
102 gctUINT32 requestedContiguousBase;
103 gctSIZE_T requestedContiguousSize;
104
105 /* IRQ management. */
106 gctINT irqLines[gcdMAX_GPU_COUNT];
107 gctBOOL isrInitializeds[gcdMAX_GPU_COUNT];
108
109 /* Thread management. */
110 struct task_struct *threadCtxts[gcdMAX_GPU_COUNT];
111 struct semaphore semas[gcdMAX_GPU_COUNT];
112 gctBOOL threadInitializeds[gcdMAX_GPU_COUNT];
113 gctBOOL killThread;
114
115 /* Signal management. */
116 gctINT signal;
117
118 /* Core mapping */
119 gceCORE coreMapping[8];
120
121 /* States before suspend. */
122 gceCHIPPOWERSTATE statesStored[gcdMAX_GPU_COUNT];
123
124 /* Device Debug File System Entry in kernel. */
125 struct _gcsDEBUGFS_Node * dbgNode;
126
127 gcsDEBUGFS_DIR debugfsDir;
128}
129* gckGALDEVICE;
130
131typedef struct _gcsHAL_PRIVATE_DATA
132{
133 gckGALDEVICE device;
134 gctPOINTER mappedMemory;
135 gctPOINTER contiguousLogical;
136 /* The process opening the device may not be the same as the one that closes it. */
137 gctUINT32 pidOpen;
138}
139gcsHAL_PRIVATE_DATA, * gcsHAL_PRIVATE_DATA_PTR;
140
141typedef struct _gcsDEVICE_CONSTRUCT_ARGS
142{
143 gctBOOL recovery;
144 gctUINT stuckDump;
145 gctUINT gpu3DMinClock;
146
147 gctBOOL contiguousRequested;
148 gcsPLATFORM* platform;
149 gctBOOL mmu;
150 gctBOOL registerMemMapped;
151 gctPOINTER registerMemAddress;
152#if gcdENABLE_DEC_COMPRESSION
153 gctUINT32 registerMemBaseDEC300;
154 gctSIZE_T registerMemSizeDEC300;
155#endif
156}
157
158gcsDEVICE_CONSTRUCT_ARGS;
159
160gceSTATUS gckGALDEVICE_Setup_ISR(
161 IN gckGALDEVICE Device
162 );
163
164gceSTATUS gckGALDEVICE_Setup_ISR_2D(
165 IN gckGALDEVICE Device
166 );
167
168gceSTATUS gckGALDEVICE_Setup_ISR_VG(
169 IN gckGALDEVICE Device
170 );
171
172gceSTATUS gckGALDEVICE_Release_ISR(
173 IN gckGALDEVICE Device
174 );
175
176gceSTATUS gckGALDEVICE_Release_ISR_2D(
177 IN gckGALDEVICE Device
178 );
179
180gceSTATUS gckGALDEVICE_Release_ISR_VG(
181 IN gckGALDEVICE Device
182 );
183
184gceSTATUS gckGALDEVICE_Start_Threads(
185 IN gckGALDEVICE Device
186 );
187
188gceSTATUS gckGALDEVICE_Stop_Threads(
189 gckGALDEVICE Device
190 );
191
192gceSTATUS gckGALDEVICE_Start(
193 IN gckGALDEVICE Device
194 );
195
196gceSTATUS gckGALDEVICE_Stop(
197 gckGALDEVICE Device
198 );
199
200gceSTATUS gckGALDEVICE_Construct(
201#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
202 IN gctINT IrqLine3D0,
203 IN gctUINT32 RegisterMemBase3D0,
204 IN gctSIZE_T RegisterMemSize3D0,
205 IN gctINT IrqLine3D1,
206 IN gctUINT32 RegisterMemBase3D1,
207 IN gctSIZE_T RegisterMemSize3D1,
208#else
209 IN gctINT IrqLine,
210 IN gctUINT32 RegisterMemBase,
211 IN gctSIZE_T RegisterMemSize,
212#endif
213 IN gctINT IrqLine2D,
214 IN gctUINT32 RegisterMemBase2D,
215 IN gctSIZE_T RegisterMemSize2D,
216 IN gctINT IrqLineVG,
217 IN gctUINT32 RegisterMemBaseVG,
218 IN gctSIZE_T RegisterMemSizeVG,
219 IN gctUINT32 ContiguousBase,
220 IN gctSIZE_T ContiguousSize,
221 IN gctSIZE_T BankSize,
222 IN gctINT FastClear,
223 IN gctINT Compression,
224 IN gctUINT32 PhysBaseAddr,
225 IN gctUINT32 PhysSize,
226 IN gctINT Signal,
227 IN gctUINT LogFileSize,
228 IN gctINT PowerManagement,
229 IN gctINT GpuProfiler,
230 IN gcsDEVICE_CONSTRUCT_ARGS * Args,
231 OUT gckGALDEVICE *Device
232 );
233
234gceSTATUS gckGALDEVICE_Destroy(
235 IN gckGALDEVICE Device
236 );
237
238static gcmINLINE gckKERNEL
239_GetValidKernel(
240 gckGALDEVICE Device
241 )
242{
243 if (Device->kernels[gcvCORE_MAJOR])
244 {
245 return Device->kernels[gcvCORE_MAJOR];
246 }
247 else
248 if (Device->kernels[gcvCORE_2D])
249 {
250 return Device->kernels[gcvCORE_2D];
251 }
252 else
253 if (Device->kernels[gcvCORE_VG])
254 {
255 return Device->kernels[gcvCORE_VG];
256 }
257 else
258 {
259 gcmkASSERT(gcvFALSE);
260 return gcvNULL;
261 }
262}
263
264#endif /* __gc_hal_kernel_device_h_ */
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_iommu.c b/src/hal/os/linux/kernel/gc_hal_kernel_iommu.c
new file mode 100755
index 0000000..843b7e1
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_iommu.c
@@ -0,0 +1,250 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include "gc_hal_kernel_device.h"
58
59#include <linux/iommu.h>
60#include <linux/platform_device.h>
61
62#define _GC_OBJ_ZONE gcvZONE_OS
63
64typedef struct _gcsIOMMU
65{
66 struct iommu_domain * domain;
67 struct device * device;
68}
69gcsIOMMU;
70
71#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
72static int
73_IOMMU_Fault_Handler(
74 struct iommu_domain * Domain,
75 struct device * Dev,
76 unsigned long DomainAddress,
77 int flags,
78 void * args
79 )
80#else
81static int
82_IOMMU_Fault_Handler(
83 struct iommu_domain * Domain,
84 struct device * Dev,
85 unsigned long DomainAddress,
86 int flags
87 )
88#endif
89{
90 return 0;
91}
92
93static int
94_FlatMapping(
95 IN gckIOMMU Iommu
96 )
97{
98 gceSTATUS status;
99 gctUINT32 physical;
100
101 for (physical = 0; physical < 0x80000000; physical += PAGE_SIZE)
102 {
103 gcmkTRACE_ZONE(
104 gcvLEVEL_INFO, gcvZONE_OS,
105 "Map %x => %x bytes = %d",
106 physical, physical, PAGE_SIZE
107 );
108
109 gcmkONERROR(gckIOMMU_Map(Iommu, physical, physical, PAGE_SIZE));
110 }
111
112 return gcvSTATUS_OK;
113
114OnError:
115 return status;
116}
117
118void
119gckIOMMU_Destory(
120 IN gckOS Os,
121 IN gckIOMMU Iommu
122 )
123{
124 gcmkHEADER();
125
126 if (Iommu->domain && Iommu->device)
127 {
128 iommu_attach_device(Iommu->domain, Iommu->device);
129 }
130
131 if (Iommu->domain)
132 {
133 iommu_domain_free(Iommu->domain);
134 }
135
136 if (Iommu)
137 {
138 gcmkOS_SAFE_FREE(Os, Iommu);
139 }
140
141 gcmkFOOTER_NO();
142}
143
144gceSTATUS
145gckIOMMU_Construct(
146 IN gckOS Os,
147 OUT gckIOMMU * Iommu
148 )
149{
150 gceSTATUS status;
151 gckIOMMU iommu = gcvNULL;
152 struct device *dev;
153 int ret;
154
155 gcmkHEADER();
156
157 dev = &Os->device->platform->device->dev;
158
159 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(gcsIOMMU), (gctPOINTER *)&iommu));
160
161 gckOS_ZeroMemory(iommu, gcmSIZEOF(gcsIOMMU));
162
163 iommu->domain = iommu_domain_alloc(&platform_bus_type);
164
165 if (!iommu->domain)
166 {
167 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "iommu_domain_alloc() fail");
168
169 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
170 }
171
172#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
173 iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler, dev);
174#else
175 iommu_set_fault_handler(iommu->domain, _IOMMU_Fault_Handler);
176#endif
177
178 ret = iommu_attach_device(iommu->domain, dev);
179
180 if (ret)
181 {
182 gcmkTRACE_ZONE(
183 gcvLEVEL_INFO, gcvZONE_OS, "iommu_attach_device() fail %d", ret);
184
185 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
186 }
187
188 iommu->device = dev;
189
190 _FlatMapping(iommu);
191
192 *Iommu = iommu;
193
194 gcmkFOOTER_NO();
195 return gcvSTATUS_OK;
196
197OnError:
198
199 gckIOMMU_Destory(Os, iommu);
200
201 gcmkFOOTER();
202 return status;
203}
204
205gceSTATUS
206gckIOMMU_Map(
207 IN gckIOMMU Iommu,
208 IN gctUINT32 DomainAddress,
209 IN gctUINT32 Physical,
210 IN gctUINT32 Bytes
211 )
212{
213 gceSTATUS status;
214 int ret;
215
216 gcmkHEADER_ARG("DomainAddress=%#X, Physical=%#X, Bytes=%d",
217 DomainAddress, Physical, Bytes);
218
219 ret = iommu_map(Iommu->domain, DomainAddress, Physical, Bytes, 0);
220
221 if (ret)
222 {
223 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
224 }
225
226 gcmkFOOTER_NO();
227 return gcvSTATUS_OK;
228
229OnError:
230
231 gcmkFOOTER();
232 return status;
233
234}
235
236gceSTATUS
237gckIOMMU_Unmap(
238 IN gckIOMMU Iommu,
239 IN gctUINT32 DomainAddress,
240 IN gctUINT32 Bytes
241 )
242{
243 gcmkHEADER();
244
245 iommu_unmap(Iommu->domain, DomainAddress, Bytes);
246
247 gcmkFOOTER_NO();
248 return gcvSTATUS_OK;
249}
250
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_linux.c b/src/hal/os/linux/kernel/gc_hal_kernel_linux.c
new file mode 100755
index 0000000..f71b697
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_linux.c
@@ -0,0 +1,508 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57
58#define _GC_OBJ_ZONE gcvZONE_KERNEL
59
60/******************************************************************************\
61******************************* gckKERNEL API Code ******************************
62\******************************************************************************/
63
64/*******************************************************************************
65**
66** gckKERNEL_QueryVideoMemory
67**
68** Query the amount of video memory.
69**
70** INPUT:
71**
72** gckKERNEL Kernel
73** Pointer to an gckKERNEL object.
74**
75** OUTPUT:
76**
77** gcsHAL_INTERFACE * Interface
78** Pointer to an gcsHAL_INTERFACE structure that will be filled in with
79** the memory information.
80*/
81gceSTATUS
82gckKERNEL_QueryVideoMemory(
83 IN gckKERNEL Kernel,
84 OUT gcsHAL_INTERFACE * Interface
85 )
86{
87 gckGALDEVICE device;
88
89 gcmkHEADER_ARG("Kernel=%p", Kernel);
90
91 /* Verify the arguments. */
92 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
93 gcmkVERIFY_ARGUMENT(Interface != NULL);
94
95 /* Extract the pointer to the gckGALDEVICE class. */
96 device = (gckGALDEVICE) Kernel->context;
97
98 /* Get internal memory size and physical address. */
99 Interface->u.QueryVideoMemory.internalSize = device->internalSize;
100 Interface->u.QueryVideoMemory.internalPhysical = device->internalPhysicalName;
101
102 /* Get external memory size and physical address. */
103 Interface->u.QueryVideoMemory.externalSize = device->externalSize;
104 Interface->u.QueryVideoMemory.externalPhysical = device->externalPhysicalName;
105
106 /* Get contiguous memory size and physical address. */
107 Interface->u.QueryVideoMemory.contiguousSize = device->contiguousSize;
108 Interface->u.QueryVideoMemory.contiguousPhysical = device->contiguousPhysicalName;
109
110 /* Success. */
111 gcmkFOOTER_NO();
112 return gcvSTATUS_OK;
113}
114
115/*******************************************************************************
116**
117** gckKERNEL_GetVideoMemoryPool
118**
119** Get the gckVIDMEM object belonging to the specified pool.
120**
121** INPUT:
122**
123** gckKERNEL Kernel
124** Pointer to an gckKERNEL object.
125**
126** gcePOOL Pool
127** Pool to query gckVIDMEM object for.
128**
129** OUTPUT:
130**
131** gckVIDMEM * VideoMemory
132** Pointer to a variable that will hold the pointer to the gckVIDMEM
133** object belonging to the requested pool.
134*/
135gceSTATUS
136gckKERNEL_GetVideoMemoryPool(
137 IN gckKERNEL Kernel,
138 IN gcePOOL Pool,
139 OUT gckVIDMEM * VideoMemory
140 )
141{
142 gckGALDEVICE device;
143 gckVIDMEM videoMemory;
144
145 gcmkHEADER_ARG("Kernel=%p Pool=%d", Kernel, Pool);
146
147 /* Verify the arguments. */
148 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
149 gcmkVERIFY_ARGUMENT(VideoMemory != NULL);
150
151 /* Extract the pointer to the gckGALDEVICE class. */
152 device = (gckGALDEVICE) Kernel->context;
153
154 /* Dispatch on pool. */
155 switch (Pool)
156 {
157 case gcvPOOL_LOCAL_INTERNAL:
158 /* Internal memory. */
159 videoMemory = device->internalVidMem;
160 break;
161
162 case gcvPOOL_LOCAL_EXTERNAL:
163 /* External memory. */
164 videoMemory = device->externalVidMem;
165 break;
166
167 case gcvPOOL_SYSTEM:
168 /* System memory. */
169 videoMemory = device->contiguousVidMem;
170 break;
171
172 default:
173 /* Unknown pool. */
174 videoMemory = NULL;
175 }
176
177 /* Return pointer to the gckVIDMEM object. */
178 *VideoMemory = videoMemory;
179
180 /* Return status. */
181 gcmkFOOTER_ARG("*VideoMemory=%p", *VideoMemory);
182 return (videoMemory == NULL) ? gcvSTATUS_OUT_OF_MEMORY : gcvSTATUS_OK;
183}
184
185/*******************************************************************************
186**
187** gckKERNEL_MapMemory
188**
189** Map video memory into the current process space.
190**
191** INPUT:
192**
193** gckKERNEL Kernel
194** Pointer to an gckKERNEL object.
195**
196** gctPHYS_ADDR Physical
197** Physical address of video memory to map.
198**
199** gctSIZE_T Bytes
200** Number of bytes to map.
201**
202** OUTPUT:
203**
204** gctPOINTER * Logical
205** Pointer to a variable that will hold the base address of the mapped
206** memory region.
207*/
208gceSTATUS
209gckKERNEL_MapMemory(
210 IN gckKERNEL Kernel,
211 IN gctPHYS_ADDR Physical,
212 IN gctSIZE_T Bytes,
213 OUT gctPOINTER * Logical
214 )
215{
216 gckKERNEL kernel = Kernel;
217 gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
218
219 return gckOS_MapMemory(Kernel->os, physical, Bytes, Logical);
220}
221
222/*******************************************************************************
223**
224** gckKERNEL_UnmapMemory
225**
226** Unmap video memory from the current process space.
227**
228** INPUT:
229**
230** gckKERNEL Kernel
231** Pointer to an gckKERNEL object.
232**
233** gctPHYS_ADDR Physical
234** Physical address of video memory to map.
235**
236** gctSIZE_T Bytes
237** Number of bytes to map.
238**
239** gctPOINTER Logical
240** Base address of the mapped memory region.
241**
242** OUTPUT:
243**
244** Nothing.
245*/
246gceSTATUS
247gckKERNEL_UnmapMemory(
248 IN gckKERNEL Kernel,
249 IN gctPHYS_ADDR Physical,
250 IN gctSIZE_T Bytes,
251 IN gctPOINTER Logical
252 )
253{
254 gckKERNEL kernel = Kernel;
255 gctPHYS_ADDR physical = gcmNAME_TO_PTR(Physical);
256
257 return gckOS_UnmapMemory(Kernel->os, physical, Bytes, Logical);
258}
259
260/*******************************************************************************
261**
262** gckKERNEL_MapVideoMemory
263**
264** Get the logical address for a hardware specific memory address for the
265** current process.
266**
267** INPUT:
268**
269** gckKERNEL Kernel
270** Pointer to an gckKERNEL object.
271**
272** gctBOOL InUserSpace
273** gcvTRUE to map the memory into the user space.
274**
275** gctUINT32 Address
276** Hardware specific memory address.
277**
278** OUTPUT:
279**
280** gctPOINTER * Logical
281** Pointer to a variable that will hold the logical address of the
282** specified memory address.
283*/
284gceSTATUS
285gckKERNEL_MapVideoMemoryEx(
286 IN gckKERNEL Kernel,
287 IN gceCORE Core,
288 IN gctBOOL InUserSpace,
289 IN gctUINT32 Address,
290 OUT gctPOINTER * Logical
291 )
292{
293 gckGALDEVICE device = gcvNULL;
294 PLINUX_MDL mdl = gcvNULL;
295 PLINUX_MDL_MAP mdlMap = gcvNULL;
296 gcePOOL pool = gcvPOOL_UNKNOWN;
297 gctUINT32 offset = 0;
298 gctUINT32 base = 0;
299 gceSTATUS status;
300 gctPOINTER logical = gcvNULL;
301 gctUINT32 baseAddress;
302 gctPHYS_ADDR_T physical;
303
304 gcmkHEADER_ARG("Kernel=%p InUserSpace=%d Address=%08x",
305 Kernel, InUserSpace, Address);
306
307 /* Verify the arguments. */
308 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
309 gcmkVERIFY_ARGUMENT(Logical != NULL);
310
311 /* Extract the pointer to the gckGALDEVICE class. */
312 device = (gckGALDEVICE) Kernel->context;
313
314 {
315 /* Split the memory address into a pool type and offset. */
316 gcmkONERROR(
317 gckHARDWARE_SplitMemory(Kernel->hardware, Address, &pool, &offset));
318 }
319
320 /* Dispatch on pool. */
321 switch (pool)
322 {
323 case gcvPOOL_LOCAL_INTERNAL:
324 /* Internal memory. */
325 logical = device->internalLogical;
326 break;
327
328 case gcvPOOL_LOCAL_EXTERNAL:
329 /* External memory. */
330 logical = device->externalLogical;
331 break;
332
333 case gcvPOOL_SYSTEM:
334 /* System memory. */
335 if (device->contiguousMapped)
336 {
337 logical = device->contiguousBase;
338 }
339 else
340 {
341 gctINT processID;
342 gckOS_GetProcessID(&processID);
343
344 mdl = (PLINUX_MDL) device->contiguousPhysical;
345
346 mdlMap = FindMdlMap(mdl, processID);
347 gcmkASSERT(mdlMap);
348
349 logical = (gctPOINTER) mdlMap->vmaAddr;
350 }
351 {
352 gctUINT32 systemBaseAddress = 0;
353
354 if (Kernel->hardware->mmuVersion == 0)
355 {
356 gcmkONERROR(gckOS_GetBaseAddress(Kernel->os, &systemBaseAddress));
357 }
358
359 gcmkVERIFY_OK(
360 gckOS_CPUPhysicalToGPUPhysical(
361 Kernel->os,
362 device->contiguousVidMem->baseAddress - systemBaseAddress,
363 &physical
364 ));
365
366 gcmkSAFECASTPHYSADDRT(baseAddress, physical);
367
368 gcmkVERIFY_OK(
369 gckHARDWARE_SplitMemory(Kernel->hardware,
370 baseAddress,
371 &pool,
372 &base));
373 }
374 offset -= base;
375 break;
376
377 default:
378 /* Invalid memory pool. */
379 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
380 }
381
382 /* Build logical address of specified address. */
383 *Logical = (gctPOINTER) ((gctUINT8_PTR) logical + offset);
384
385 /* Success. */
386 gcmkFOOTER_ARG("*Logical=%p", *Logical);
387 return gcvSTATUS_OK;
388
389OnError:
390 /* Retunn the status. */
391 gcmkFOOTER();
392 return status;
393}
394
395/*******************************************************************************
396**
397** gckKERNEL_MapVideoMemory
398**
399** Get the logical address for a hardware specific memory address for the
400** current process.
401**
402** INPUT:
403**
404** gckKERNEL Kernel
405** Pointer to an gckKERNEL object.
406**
407** gctBOOL InUserSpace
408** gcvTRUE to map the memory into the user space.
409**
410** gctUINT32 Address
411** Hardware specific memory address.
412**
413** OUTPUT:
414**
415** gctPOINTER * Logical
416** Pointer to a variable that will hold the logical address of the
417** specified memory address.
418*/
419gceSTATUS
420gckKERNEL_MapVideoMemory(
421 IN gckKERNEL Kernel,
422 IN gctBOOL InUserSpace,
423 IN gctUINT32 Address,
424 OUT gctPOINTER * Logical
425 )
426{
427 return gckKERNEL_MapVideoMemoryEx(Kernel, gcvCORE_MAJOR, InUserSpace, Address, Logical);
428}
429/*******************************************************************************
430**
431** gckKERNEL_Notify
432**
433** This function iscalled by clients to notify the gckKERNRL object of an event.
434**
435** INPUT:
436**
437** gckKERNEL Kernel
438** Pointer to an gckKERNEL object.
439**
440** gceNOTIFY Notification
441** Notification event.
442**
443** OUTPUT:
444**
445** Nothing.
446*/
447gceSTATUS
448gckKERNEL_Notify(
449 IN gckKERNEL Kernel,
450 IN gceNOTIFY Notification,
451 IN gctBOOL Data
452 )
453{
454 gceSTATUS status;
455
456 gcmkHEADER_ARG("Kernel=%p Notification=%d Data=%d",
457 Kernel, Notification, Data);
458
459 /* Verify the arguments. */
460 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
461
462 /* Dispatch on notifcation. */
463 switch (Notification)
464 {
465 case gcvNOTIFY_INTERRUPT:
466 /* Process the interrupt. */
467#if COMMAND_PROCESSOR_VERSION > 1
468 status = gckINTERRUPT_Notify(Kernel->interrupt, Data);
469#else
470 status = gckHARDWARE_Interrupt(Kernel->hardware,
471 Data);
472#endif
473 break;
474
475 default:
476 status = gcvSTATUS_OK;
477 break;
478 }
479
480 /* Success. */
481 gcmkFOOTER();
482 return status;
483}
484
485gceSTATUS
486gckKERNEL_QuerySettings(
487 IN gckKERNEL Kernel,
488 OUT gcsKERNEL_SETTINGS * Settings
489 )
490{
491 gckGALDEVICE device;
492
493 gcmkHEADER_ARG("Kernel=%p", Kernel);
494
495 /* Verify the arguments. */
496 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
497 gcmkVERIFY_ARGUMENT(Settings != gcvNULL);
498
499 /* Extract the pointer to the gckGALDEVICE class. */
500 device = (gckGALDEVICE) Kernel->context;
501
502 /* Fill in signal. */
503 Settings->signal = device->signal;
504
505 /* Success. */
506 gcmkFOOTER_ARG("Settings->signal=%d", Settings->signal);
507 return gcvSTATUS_OK;
508}
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_linux.h b/src/hal/os/linux/kernel/gc_hal_kernel_linux.h
new file mode 100755
index 0000000..b863784
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_linux.h
@@ -0,0 +1,437 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_linux_h_
57#define __gc_hal_kernel_linux_h_
58
59#include <linux/version.h>
60#include <linux/init.h>
61#include <linux/module.h>
62#include <linux/fs.h>
63#include <linux/mm.h>
64#include <linux/sched.h>
65#include <linux/signal.h>
66#ifdef FLAREON
67# include <asm/arch-realview/dove_gpio_irq.h>
68#endif
69#include <linux/interrupt.h>
70#include <linux/vmalloc.h>
71#include <linux/dma-mapping.h>
72#include <linux/kthread.h>
73
74#include <linux/idr.h>
75
76#ifdef MODVERSIONS
77# include <linux/modversions.h>
78#endif
79#include <asm/io.h>
80#include <asm/uaccess.h>
81
82#if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
83#include <linux/clk.h>
84#endif
85
86#define NTSTRSAFE_NO_CCH_FUNCTIONS
87#include "gc_hal.h"
88#include "gc_hal_driver.h"
89#include "gc_hal_kernel.h"
90#include "gc_hal_kernel_platform.h"
91#include "gc_hal_kernel_device.h"
92#include "gc_hal_kernel_os.h"
93#include "gc_hal_kernel_debugfs.h"
94
95
96#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
97#define FIND_TASK_BY_PID(x) pid_task(find_vpid(x), PIDTYPE_PID)
98#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
99#define FIND_TASK_BY_PID(x) find_task_by_vpid(x)
100#else
101#define FIND_TASK_BY_PID(x) find_task_by_pid(x)
102#endif
103
104#define _WIDE(string) L##string
105#define WIDE(string) _WIDE(string)
106
107#define countof(a) (sizeof(a) / sizeof(a[0]))
108
109#ifndef DEVICE_NAME
110#ifdef CONFIG_DOVE_GPU
111# define DEVICE_NAME "dove_gpu"
112#else
113# define DEVICE_NAME "galcore"
114#endif
115#endif
116
117#ifndef CLASS_NAME
118# define CLASS_NAME "graphics_class"
119#endif
120
121#define GetPageCount(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
122
123#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
124#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
125#else
126#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
127#endif
128
129/* Protection bit when mapping memroy to user sapce */
130#define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
131
132#if gcdNONPAGED_MEMORY_BUFFERABLE
133#define gcmkIOREMAP ioremap_wc
134#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
135#elif !gcdNONPAGED_MEMORY_CACHEABLE
136#define gcmkIOREMAP ioremap_nocache
137#define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
138#endif
139
140#define gcdSUPPRESS_OOM_MESSAGE 1
141
142#if gcdSUPPRESS_OOM_MESSAGE
143#define gcdNOWARN __GFP_NOWARN
144#else
145#define gcdNOWARN 0
146#endif
147
148/******************************************************************************\
149********************************** Structures **********************************
150\******************************************************************************/
151typedef struct _gcsIOMMU * gckIOMMU;
152
153typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
154typedef struct _gcsUSER_MAPPING
155{
156 /* Pointer to next mapping structure. */
157 gcsUSER_MAPPING_PTR next;
158
159 /* Physical address of this mapping. */
160 gctUINT32 physical;
161
162 /* Logical address of this mapping. */
163 gctPOINTER logical;
164
165 /* Number of bytes of this mapping. */
166 gctSIZE_T bytes;
167
168 /* Starting address of this mapping. */
169 gctINT8_PTR start;
170
171 /* Ending address of this mapping. */
172 gctINT8_PTR end;
173}
174gcsUSER_MAPPING;
175
176typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
177typedef struct _gcsINTEGER_DB
178{
179 struct idr idr;
180 spinlock_t lock;
181 gctINT curr;
182}
183gcsINTEGER_DB;
184
185struct _gckOS
186{
187 /* Object. */
188 gcsOBJECT object;
189
190 /* Pointer to device */
191 gckGALDEVICE device;
192
193 /* Memory management */
194 gctPOINTER memoryLock;
195 gctPOINTER memoryMapLock;
196
197 struct _LINUX_MDL *mdlHead;
198 struct _LINUX_MDL *mdlTail;
199
200 /* Kernel process ID. */
201 gctUINT32 kernelProcessID;
202
203 /* Signal management. */
204
205 /* Lock. */
206 gctPOINTER signalMutex;
207
208 /* signal id database. */
209 gcsINTEGER_DB signalDB;
210
211#if gcdANDROID_NATIVE_FENCE_SYNC
212 /* Lock. */
213 gctPOINTER syncPointMutex;
214
215 /* sync point id database. */
216 gcsINTEGER_DB syncPointDB;
217#endif
218
219 gcsUSER_MAPPING_PTR userMap;
220 gctPOINTER debugLock;
221
222 /* workqueue for os timer. */
223 struct workqueue_struct * workqueue;
224
225 /* Allocate extra page to avoid cache overflow */
226 struct page* paddingPage;
227
228 /* Detect unfreed allocation. */
229 atomic_t allocateCount;
230
231 struct list_head allocatorList;
232
233 gcsDEBUGFS_DIR allocatorDebugfsDir;
234
235 /* Lock for register access check. */
236 struct mutex registerAccessLocks[gcdMAX_GPU_COUNT];
237
238 /* External power states. */
239 gctBOOL powerStates[gcdMAX_GPU_COUNT];
240
241 /* External clock states. */
242 gctBOOL clockStates[gcdMAX_GPU_COUNT];
243
244 /* IOMMU. */
245 gckIOMMU iommu;
246};
247
248typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
249typedef struct _gcsSIGNAL
250{
251 /* Kernel sync primitive. */
252 struct completion obj;
253
254 /* Manual reset flag. */
255 gctBOOL manualReset;
256
257 /* The reference counter. */
258 atomic_t ref;
259
260 /* The owner of the signal. */
261 gctHANDLE process;
262
263 gckHARDWARE hardware;
264
265 /* ID. */
266 gctUINT32 id;
267}
268gcsSIGNAL;
269
270#if gcdANDROID_NATIVE_FENCE_SYNC
271typedef struct _gcsSYNC_POINT * gcsSYNC_POINT_PTR;
272typedef struct _gcsSYNC_POINT
273{
274 /* The reference counter. */
275 atomic_t ref;
276
277 /* State. */
278 atomic_t state;
279
280 /* timeline. */
281 struct sync_timeline * timeline;
282
283 /* ID. */
284 gctUINT32 id;
285}
286gcsSYNC_POINT;
287#endif
288
289typedef struct _gcsPageInfo * gcsPageInfo_PTR;
290typedef struct _gcsPageInfo
291{
292 struct page **pages;
293 gctUINT32_PTR pageTable;
294 gctUINT32 extraPage;
295 gctUINT32 address;
296#if gcdPROCESS_ADDRESS_SPACE
297 gckMMU mmu;
298#endif
299}
300gcsPageInfo;
301
302typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
303typedef struct _gcsOSTIMER
304{
305 struct delayed_work work;
306 gctTIMERFUNCTION function;
307 gctPOINTER data;
308} gcsOSTIMER;
309
310gceSTATUS
311gckOS_ImportAllocators(
312 gckOS Os
313 );
314
315gceSTATUS
316gckOS_FreeAllocators(
317 gckOS Os
318 );
319
320gceSTATUS
321_HandleOuterCache(
322 IN gckOS Os,
323 IN gctUINT32 Physical,
324 IN gctPOINTER Logical,
325 IN gctSIZE_T Bytes,
326 IN gceCACHEOPERATION Type
327 );
328
329gceSTATUS
330_ConvertLogical2Physical(
331 IN gckOS Os,
332 IN gctPOINTER Logical,
333 IN gctUINT32 ProcessID,
334 IN PLINUX_MDL Mdl,
335 OUT gctPHYS_ADDR_T * Physical
336 );
337
338gctSTRING
339_CreateKernelVirtualMapping(
340 IN PLINUX_MDL Mdl
341 );
342
343void
344_DestoryKernelVirtualMapping(
345 IN gctSTRING Addr
346 );
347
348void
349_UnmapUserLogical(
350 IN gctPOINTER Logical,
351 IN gctUINT32 Size
352 );
353
354static inline gctINT
355_GetProcessID(
356 void
357 )
358{
359#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
360 return task_tgid_vnr(current);
361#else
362 return current->tgid;
363#endif
364}
365
366static inline struct page *
367_NonContiguousToPage(
368 IN struct page ** Pages,
369 IN gctUINT32 Index
370 )
371{
372 gcmkASSERT(Pages != gcvNULL);
373 return Pages[Index];
374}
375
376static inline unsigned long
377_NonContiguousToPfn(
378 IN struct page ** Pages,
379 IN gctUINT32 Index
380 )
381{
382 gcmkASSERT(Pages != gcvNULL);
383 return page_to_pfn(_NonContiguousToPage(Pages, Index));
384}
385
386static inline unsigned long
387_NonContiguousToPhys(
388 IN struct page ** Pages,
389 IN gctUINT32 Index
390 )
391{
392 gcmkASSERT(Pages != gcvNULL);
393 return page_to_phys(_NonContiguousToPage(Pages, Index));
394}
395
396#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
397static inline int
398is_vmalloc_addr(
399 void *Addr
400 )
401{
402 unsigned long addr = (unsigned long)Addr;
403
404 return addr >= VMALLOC_START && addr < VMALLOC_END;
405}
406#endif
407
408#ifdef CONFIG_IOMMU_SUPPORT
409void
410gckIOMMU_Destory(
411 IN gckOS Os,
412 IN gckIOMMU Iommu
413 );
414
415gceSTATUS
416gckIOMMU_Construct(
417 IN gckOS Os,
418 OUT gckIOMMU * Iommu
419 );
420
421gceSTATUS
422gckIOMMU_Map(
423 IN gckIOMMU Iommu,
424 IN gctUINT32 DomainAddress,
425 IN gctUINT32 Physical,
426 IN gctUINT32 Bytes
427 );
428
429gceSTATUS
430gckIOMMU_Unmap(
431 IN gckIOMMU Iommu,
432 IN gctUINT32 DomainAddress,
433 IN gctUINT32 Bytes
434 );
435#endif
436
437#endif /* __gc_hal_kernel_linux_h_ */
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_math.c b/src/hal/os/linux/kernel/gc_hal_kernel_math.c
new file mode 100755
index 0000000..ae3c8a7
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_math.c
@@ -0,0 +1,66 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57
58gctINT
59gckMATH_ModuloInt(
60 IN gctINT X,
61 IN gctINT Y
62 )
63{
64 if(Y ==0) {return 0;}
65 else {return X % Y;}
66}
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_mutex.h b/src/hal/os/linux/kernel/gc_hal_kernel_mutex.h
new file mode 100755
index 0000000..7027d46
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_mutex.h
@@ -0,0 +1,89 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef _gc_hal_kernel_mutex_h_
57#define _gc_hal_kernel_mutex_h_
58
59#include "gc_hal.h"
60#include <linux/mutex.h>
61
62/* Create a new mutex. */
63#define gckOS_CreateMutex(Os, Mutex) \
64({ \
65 gceSTATUS _status; \
66 gcmkHEADER_ARG("Os=0x%X", Os); \
67 \
68 /* Validate the arguments. */ \
69 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS); \
70 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL); \
71 \
72 /* Allocate the mutex structure. */ \
73 _status = gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex); \
74 \
75 if (gcmIS_SUCCESS(_status)) \
76 { \
77 /* Initialize the mutex. */ \
78 mutex_init(*(struct mutex **)Mutex); \
79 } \
80 \
81 /* Return status. */ \
82 gcmkFOOTER_ARG("*Mutex=0x%X", *(struct mutex **)Mutex); \
83 _status; \
84})
85
86#endif
87
88
89
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_os.c b/src/hal/os/linux/kernel/gc_hal_kernel_os.c
new file mode 100755
index 0000000..5b97898
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -0,0 +1,8225 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57
58#include <linux/pagemap.h>
59#include <linux/seq_file.h>
60#include <linux/mman.h>
61#include <asm/atomic.h>
62#include <linux/dma-mapping.h>
63#include <linux/slab.h>
64#include <linux/workqueue.h>
65#include <linux/irqflags.h>
66#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
67#include <linux/math64.h>
68#endif
69#include <linux/delay.h>
70
71#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
72#include <linux/anon_inodes.h>
73#endif
74
75#if gcdANDROID_NATIVE_FENCE_SYNC
76#include <linux/file.h>
77#include "gc_hal_kernel_sync.h"
78#endif
79
80#define _GC_OBJ_ZONE gcvZONE_OS
81
82#include "gc_hal_kernel_allocator.h"
83
84#define MEMORY_LOCK(os) \
85 gcmkVERIFY_OK(gckOS_AcquireMutex( \
86 (os), \
87 (os)->memoryLock, \
88 gcvINFINITE))
89
90#define MEMORY_UNLOCK(os) \
91 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
92
93#define MEMORY_MAP_LOCK(os) \
94 gcmkVERIFY_OK(gckOS_AcquireMutex( \
95 (os), \
96 (os)->memoryMapLock, \
97 gcvINFINITE))
98
99#define MEMORY_MAP_UNLOCK(os) \
100 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
101
102
103/******************************************************************************\
104******************************* Private Functions ******************************
105\******************************************************************************/
106static gctINT
107_GetThreadID(
108 void
109 )
110{
111#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
112 return task_pid_vnr(current);
113#else
114 return current->pid;
115#endif
116}
117
118static PLINUX_MDL
119_CreateMdl(
120 void
121 )
122{
123 PLINUX_MDL mdl;
124
125 gcmkHEADER();
126
127 mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
128
129 gcmkFOOTER_ARG("0x%X", mdl);
130 return mdl;
131}
132
133static gceSTATUS
134_DestroyMdlMap(
135 IN PLINUX_MDL Mdl,
136 IN PLINUX_MDL_MAP MdlMap
137 );
138
139static gceSTATUS
140_DestroyMdl(
141 IN PLINUX_MDL Mdl
142 )
143{
144 PLINUX_MDL_MAP mdlMap, next;
145
146 gcmkHEADER_ARG("Mdl=0x%X", Mdl);
147
148 /* Verify the arguments. */
149 gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
150
151 mdlMap = Mdl->maps;
152
153 while (mdlMap != gcvNULL)
154 {
155 next = mdlMap->next;
156
157 gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
158
159 mdlMap = next;
160 }
161
162 kfree(Mdl);
163
164 gcmkFOOTER_NO();
165 return gcvSTATUS_OK;
166}
167
168static PLINUX_MDL_MAP
169_CreateMdlMap(
170 IN PLINUX_MDL Mdl,
171 IN gctINT ProcessID
172 )
173{
174 PLINUX_MDL_MAP mdlMap;
175
176 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
177
178 mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
179 if (mdlMap == gcvNULL)
180 {
181 gcmkFOOTER_NO();
182 return gcvNULL;
183 }
184
185 mdlMap->pid = ProcessID;
186 mdlMap->vmaAddr = gcvNULL;
187 mdlMap->vma = gcvNULL;
188 mdlMap->count = 0;
189
190 mdlMap->next = Mdl->maps;
191 Mdl->maps = mdlMap;
192
193 gcmkFOOTER_ARG("0x%X", mdlMap);
194 return mdlMap;
195}
196
197static gceSTATUS
198_DestroyMdlMap(
199 IN PLINUX_MDL Mdl,
200 IN PLINUX_MDL_MAP MdlMap
201 )
202{
203 PLINUX_MDL_MAP prevMdlMap;
204
205 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
206
207 /* Verify the arguments. */
208 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
209 gcmkASSERT(Mdl->maps != gcvNULL);
210
211 if (Mdl->maps == MdlMap)
212 {
213 Mdl->maps = MdlMap->next;
214 }
215 else
216 {
217 prevMdlMap = Mdl->maps;
218
219 while (prevMdlMap->next != MdlMap)
220 {
221 prevMdlMap = prevMdlMap->next;
222
223 gcmkASSERT(prevMdlMap != gcvNULL);
224 }
225
226 prevMdlMap->next = MdlMap->next;
227 }
228
229 kfree(MdlMap);
230
231 gcmkFOOTER_NO();
232 return gcvSTATUS_OK;
233}
234
235extern PLINUX_MDL_MAP
236FindMdlMap(
237 IN PLINUX_MDL Mdl,
238 IN gctINT ProcessID
239 )
240{
241 PLINUX_MDL_MAP mdlMap;
242
243 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
244 if(Mdl == gcvNULL)
245 {
246 gcmkFOOTER_NO();
247 return gcvNULL;
248 }
249 mdlMap = Mdl->maps;
250
251 while (mdlMap != gcvNULL)
252 {
253 if (mdlMap->pid == ProcessID)
254 {
255 gcmkFOOTER_ARG("0x%X", mdlMap);
256 return mdlMap;
257 }
258
259 mdlMap = mdlMap->next;
260 }
261
262 gcmkFOOTER_NO();
263 return gcvNULL;
264}
265
266/*******************************************************************************
267** Integer Id Management.
268*/
269gceSTATUS
270_AllocateIntegerId(
271 IN gcsINTEGER_DB_PTR Database,
272 IN gctPOINTER KernelPointer,
273 OUT gctUINT32 *Id
274 )
275{
276 int result;
277 gctINT next;
278
279#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
280 idr_preload(GFP_KERNEL | gcdNOWARN);
281
282 spin_lock(&Database->lock);
283
284 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
285
286 result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
287
288 /* ID allocated should not be 0. */
289 gcmkASSERT(result != 0);
290
291 if (result > 0)
292 {
293 Database->curr = *Id = result;
294 }
295
296 spin_unlock(&Database->lock);
297
298 idr_preload_end();
299
300 if (result < 0)
301 {
302 return gcvSTATUS_OUT_OF_RESOURCES;
303 }
304#else
305again:
306 if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
307 {
308 return gcvSTATUS_OUT_OF_MEMORY;
309 }
310
311 spin_lock(&Database->lock);
312
313 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
314
315 /* Try to get a id greater than 0. */
316 result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
317
318 if (!result)
319 {
320 Database->curr = *Id;
321 }
322
323 spin_unlock(&Database->lock);
324
325 if (result == -EAGAIN)
326 {
327 goto again;
328 }
329
330 if (result != 0)
331 {
332 return gcvSTATUS_OUT_OF_RESOURCES;
333 }
334#endif
335
336 return gcvSTATUS_OK;
337}
338
339gceSTATUS
340_QueryIntegerId(
341 IN gcsINTEGER_DB_PTR Database,
342 IN gctUINT32 Id,
343 OUT gctPOINTER * KernelPointer
344 )
345{
346 gctPOINTER pointer;
347
348 spin_lock(&Database->lock);
349
350 pointer = idr_find(&Database->idr, Id);
351
352 spin_unlock(&Database->lock);
353
354 if(pointer)
355 {
356 *KernelPointer = pointer;
357 return gcvSTATUS_OK;
358 }
359 else
360 {
361 gcmkTRACE_ZONE(
362 gcvLEVEL_ERROR, gcvZONE_OS,
363 "%s(%d) Id = %d is not found",
364 __FUNCTION__, __LINE__, Id);
365
366 return gcvSTATUS_NOT_FOUND;
367 }
368}
369
370gceSTATUS
371_DestroyIntegerId(
372 IN gcsINTEGER_DB_PTR Database,
373 IN gctUINT32 Id
374 )
375{
376 spin_lock(&Database->lock);
377
378 idr_remove(&Database->idr, Id);
379
380 spin_unlock(&Database->lock);
381
382 return gcvSTATUS_OK;
383}
384
385gceSTATUS
386_QueryProcessPageTable(
387 IN gctPOINTER Logical,
388 OUT gctPHYS_ADDR_T * Address
389 )
390{
391 spinlock_t *lock;
392 gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
393 pgd_t *pgd;
394 pud_t *pud;
395 pmd_t *pmd;
396 pte_t *pte;
397
398 if (!current->mm)
399 {
400 return gcvSTATUS_NOT_FOUND;
401 }
402
403 pgd = pgd_offset(current->mm, logical);
404 if (pgd_none(*pgd) || pgd_bad(*pgd))
405 {
406 return gcvSTATUS_NOT_FOUND;
407 }
408
409 pud = pud_offset(pgd, logical);
410 if (pud_none(*pud) || pud_bad(*pud))
411 {
412 return gcvSTATUS_NOT_FOUND;
413 }
414
415 pmd = pmd_offset(pud, logical);
416 if (pmd_none(*pmd) || pmd_bad(*pmd))
417 {
418 return gcvSTATUS_NOT_FOUND;
419 }
420
421 pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
422 if (!pte)
423 {
424 return gcvSTATUS_NOT_FOUND;
425 }
426
427 if (!pte_present(*pte))
428 {
429 pte_unmap_unlock(pte, lock);
430 return gcvSTATUS_NOT_FOUND;
431 }
432
433 *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
434 pte_unmap_unlock(pte, lock);
435
436 return gcvSTATUS_OK;
437}
438
439#if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
440static inline gceSTATUS
441outer_func(
442 gceCACHEOPERATION Type,
443 unsigned long Start,
444 unsigned long End
445 )
446{
447 switch (Type)
448 {
449 case gcvCACHE_CLEAN:
450 outer_clean_range(Start, End);
451 break;
452 case gcvCACHE_INVALIDATE:
453 outer_inv_range(Start, End);
454 break;
455 case gcvCACHE_FLUSH:
456 outer_flush_range(Start, End);
457 break;
458 default:
459 return gcvSTATUS_INVALID_ARGUMENT;
460 break;
461 }
462 return gcvSTATUS_OK;
463}
464
465#if gcdENABLE_OUTER_CACHE_PATCH
466/*******************************************************************************
467** _HandleOuterCache
468**
469** Handle the outer cache for the specified addresses.
470**
471** ARGUMENTS:
472**
473** gckOS Os
474** Pointer to gckOS object.
475**
476** gctPOINTER Physical
477** Physical address to flush.
478**
479** gctPOINTER Logical
480** Logical address to flush.
481**
482** gctSIZE_T Bytes
483** Size of the address range in bytes to flush.
484**
485** gceOUTERCACHE_OPERATION Type
486** Operation need to be execute.
487*/
488gceSTATUS
489_HandleOuterCache(
490 IN gckOS Os,
491 IN gctUINT32 Physical,
492 IN gctPOINTER Logical,
493 IN gctSIZE_T Bytes,
494 IN gceCACHEOPERATION Type
495 )
496{
497 gceSTATUS status;
498 gctPHYS_ADDR_T paddr;
499 gctPOINTER vaddr;
500 gctUINT32 offset, bytes, left;
501
502 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu",
503 Os, Logical, Bytes);
504
505 if (Physical != gcvINVALID_ADDRESS)
506 {
507 /* Non paged memory or gcvPOOL_USER surface */
508 paddr = (unsigned long) Physical;
509 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
510 }
511 else
512 {
513 /* Non contiguous virtual memory */
514 vaddr = Logical;
515 left = Bytes;
516
517 while (left)
518 {
519 /* Handle (part of) current page. */
520 offset = (gctUINTPTR_T)vaddr & ~PAGE_MASK;
521
522 bytes = gcmMIN(left, PAGE_SIZE - offset);
523
524 gcmkONERROR(_QueryProcessPageTable(vaddr, &paddr));
525 gcmkONERROR(outer_func(Type, paddr, paddr + bytes));
526
527 vaddr = (gctUINT8_PTR)vaddr + bytes;
528 left -= bytes;
529 }
530 }
531
532 mb();
533
534 /* Success. */
535 gcmkFOOTER_NO();
536 return gcvSTATUS_OK;
537
538OnError:
539 /* Return the status. */
540 gcmkFOOTER();
541 return status;
542}
543#endif
544#endif
545
546gctBOOL
547_AllowAccess(
548 IN gckOS Os,
549 IN gceCORE Core,
550 IN gctUINT32 Address
551 )
552{
553 gctUINT32 data;
554
555 /* Check external clock state. */
556 if (Os->clockStates[Core] == gcvFALSE)
557 {
558 gcmkPRINT("[galcore]: %s(%d) External clock off", __FUNCTION__, __LINE__);
559 return gcvFALSE;
560 }
561
562 /* Check internal clock state. */
563 if (Address == 0)
564 {
565 return gcvTRUE;
566 }
567
568 {
569 data = readl((gctUINT8 *)Os->device->registerBases[Core] + 0x0);
570 }
571
572 if ((data & 0x3) == 0x3)
573 {
574 gcmkPRINT("[galcore]: %s(%d) Internal clock off", __FUNCTION__, __LINE__);
575 return gcvFALSE;
576 }
577
578 return gcvTRUE;
579}
580
581static gceSTATUS
582_ShrinkMemory(
583 IN gckOS Os
584 )
585{
586 gcsPLATFORM * platform;
587
588 gcmkHEADER_ARG("Os=0x%X", Os);
589 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
590
591 platform = Os->device->platform;
592
593 if (platform && platform->ops->shrinkMemory)
594 {
595 platform->ops->shrinkMemory(platform);
596 }
597 else
598 {
599 gcmkFOOTER_NO();
600 return gcvSTATUS_NOT_SUPPORTED;
601 }
602
603 gcmkFOOTER_NO();
604 return gcvSTATUS_OK;
605}
606
607/*******************************************************************************
608**
609** gckOS_Construct
610**
611** Construct a new gckOS object.
612**
613** INPUT:
614**
615** gctPOINTER Context
616** Pointer to the gckGALDEVICE class.
617**
618** OUTPUT:
619**
620** gckOS * Os
621** Pointer to a variable that will hold the pointer to the gckOS object.
622*/
623gceSTATUS
624gckOS_Construct(
625 IN gctPOINTER Context,
626 OUT gckOS * Os
627 )
628{
629 gckOS os;
630 gceSTATUS status;
631 gctINT i;
632
633 gcmkHEADER_ARG("Context=0x%X", Context);
634
635 /* Verify the arguments. */
636 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
637
638 /* Allocate the gckOS object. */
639 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
640
641 if (os == gcvNULL)
642 {
643 /* Out of memory. */
644 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
645 return gcvSTATUS_OUT_OF_MEMORY;
646 }
647
648 /* Zero the memory. */
649 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
650
651 /* Initialize the gckOS object. */
652 os->object.type = gcvOBJ_OS;
653
654 /* Set device device. */
655 os->device = Context;
656
657 /* Set allocateCount to 0, gckOS_Allocate has not been used yet. */
658 atomic_set(&os->allocateCount, 0);
659
660 /* Initialize the memory lock. */
661 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
662 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
663
664 /* Create debug lock mutex. */
665 gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
666
667 os->mdlHead = os->mdlTail = gcvNULL;
668
669 /* Get the kernel process ID. */
670 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
671
672 /*
673 * Initialize the signal manager.
674 */
675
676 /* Initialize mutex. */
677 gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
678
679 /* Initialize signal id database lock. */
680 spin_lock_init(&os->signalDB.lock);
681
682 /* Initialize signal id database. */
683 idr_init(&os->signalDB.idr);
684
685#if gcdANDROID_NATIVE_FENCE_SYNC
686 /*
687 * Initialize the sync point manager.
688 */
689
690 /* Initialize mutex. */
691 gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex));
692
693 /* Initialize sync point id database lock. */
694 spin_lock_init(&os->syncPointDB.lock);
695
696 /* Initialize sync point id database. */
697 idr_init(&os->syncPointDB.idr);
698#endif
699
700 /* Create a workqueue for os timer. */
701 os->workqueue = create_singlethread_workqueue("galcore workqueue");
702
703 if (os->workqueue == gcvNULL)
704 {
705 /* Out of memory. */
706 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
707 }
708
709 os->paddingPage = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
710 if (os->paddingPage == gcvNULL)
711 {
712 /* Out of memory. */
713 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
714 }
715 else
716 {
717 SetPageReserved(os->paddingPage);
718 }
719
720 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
721 {
722 mutex_init(&os->registerAccessLocks[i]);
723 }
724
725 gckOS_ImportAllocators(os);
726
727#ifdef CONFIG_IOMMU_SUPPORT
728 if (((gckGALDEVICE)(os->device))->mmu == gcvFALSE)
729 {
730 /* Only use IOMMU when internal MMU is not enabled. */
731 status = gckIOMMU_Construct(os, &os->iommu);
732
733 if (gcmIS_ERROR(status))
734 {
735 gcmkTRACE_ZONE(
736 gcvLEVEL_INFO, gcvZONE_OS,
737 "%s(%d): Fail to setup IOMMU",
738 __FUNCTION__, __LINE__
739 );
740 }
741 }
742#endif
743
744 /* Return pointer to the gckOS object. */
745 *Os = os;
746
747 /* Success. */
748 gcmkFOOTER_ARG("*Os=0x%X", *Os);
749 return gcvSTATUS_OK;
750
751OnError:
752
753#if gcdANDROID_NATIVE_FENCE_SYNC
754 if (os->syncPointMutex != gcvNULL)
755 {
756 gcmkVERIFY_OK(
757 gckOS_DeleteMutex(os, os->syncPointMutex));
758 }
759#endif
760
761 if (os->signalMutex != gcvNULL)
762 {
763 gcmkVERIFY_OK(
764 gckOS_DeleteMutex(os, os->signalMutex));
765 }
766
767 if (os->memoryMapLock != gcvNULL)
768 {
769 gcmkVERIFY_OK(
770 gckOS_DeleteMutex(os, os->memoryMapLock));
771 }
772
773 if (os->memoryLock != gcvNULL)
774 {
775 gcmkVERIFY_OK(
776 gckOS_DeleteMutex(os, os->memoryLock));
777 }
778
779 if (os->debugLock != gcvNULL)
780 {
781 gcmkVERIFY_OK(
782 gckOS_DeleteMutex(os, os->debugLock));
783 }
784
785 if (os->workqueue != gcvNULL)
786 {
787 destroy_workqueue(os->workqueue);
788 }
789
790 kfree(os);
791
792 /* Return the error. */
793 gcmkFOOTER();
794 return status;
795}
796
797/*******************************************************************************
798**
799** gckOS_Destroy
800**
801** Destroy an gckOS object.
802**
803** INPUT:
804**
805** gckOS Os
806** Pointer to an gckOS object that needs to be destroyed.
807**
808** OUTPUT:
809**
810** Nothing.
811*/
812gceSTATUS
813gckOS_Destroy(
814 IN gckOS Os
815 )
816{
817 gcmkHEADER_ARG("Os=0x%X", Os);
818
819 /* Verify the arguments. */
820 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
821
822 if (Os->paddingPage != gcvNULL)
823 {
824 ClearPageReserved(Os->paddingPage);
825 __free_page(Os->paddingPage);
826 Os->paddingPage = gcvNULL;
827 }
828
829#if gcdANDROID_NATIVE_FENCE_SYNC
830 /*
831 * Destroy the sync point manager.
832 */
833
834 /* Destroy the mutex. */
835 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex));
836#endif
837
838 /*
839 * Destroy the signal manager.
840 */
841
842 /* Destroy the mutex. */
843 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
844
845 /* Destroy the memory lock. */
846 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
847 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
848
849 /* Destroy debug lock mutex. */
850 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
851
852 /* Wait for all works done. */
853 flush_workqueue(Os->workqueue);
854
855 /* Destory work queue. */
856 destroy_workqueue(Os->workqueue);
857
858 gckOS_FreeAllocators(Os);
859
860#ifdef CONFIG_IOMMU_SUPPORT
861 if (Os->iommu)
862 {
863 gckIOMMU_Destory(Os, Os->iommu);
864 }
865#endif
866
867 /* Flush the debug cache. */
868 gcmkDEBUGFLUSH(~0U);
869
870 /* Mark the gckOS object as unknown. */
871 Os->object.type = gcvOBJ_UNKNOWN;
872
873
874 /* Free the gckOS object. */
875 kfree(Os);
876
877 /* Success. */
878 gcmkFOOTER_NO();
879 return gcvSTATUS_OK;
880}
881
882gceSTATUS
883gckOS_CreateKernelVirtualMapping(
884 IN gckOS Os,
885 IN gctPHYS_ADDR Physical,
886 IN gctSIZE_T Bytes,
887 OUT gctPOINTER * Logical,
888 OUT gctSIZE_T * PageCount
889 )
890{
891 gceSTATUS status;
892 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
893 gckALLOCATOR allocator = mdl->allocator;
894
895 gcmkHEADER();
896
897 *PageCount = mdl->numPages;
898
899 gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, Logical));
900
901 gcmkFOOTER_NO();
902 return gcvSTATUS_OK;
903
904OnError:
905 gcmkFOOTER();
906 return status;
907}
908
909gceSTATUS
910gckOS_DestroyKernelVirtualMapping(
911 IN gckOS Os,
912 IN gctPHYS_ADDR Physical,
913 IN gctSIZE_T Bytes,
914 IN gctPOINTER Logical
915 )
916{
917 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
918 gckALLOCATOR allocator = mdl->allocator;
919
920 gcmkHEADER();
921
922 allocator->ops->UnmapKernel(allocator, mdl, Logical);
923
924 gcmkFOOTER_NO();
925 return gcvSTATUS_OK;
926}
927
928gceSTATUS
929gckOS_CreateUserVirtualMapping(
930 IN gckOS Os,
931 IN gctPHYS_ADDR Physical,
932 IN gctSIZE_T Bytes,
933 OUT gctPOINTER * Logical,
934 OUT gctSIZE_T * PageCount
935 )
936{
937 return gckOS_LockPages(Os, Physical, Bytes, gcvFALSE, Logical, PageCount);
938}
939
940gceSTATUS
941gckOS_DestroyUserVirtualMapping(
942 IN gckOS Os,
943 IN gctPHYS_ADDR Physical,
944 IN gctSIZE_T Bytes,
945 IN gctPOINTER Logical
946 )
947{
948 return gckOS_UnlockPages(Os, Physical, Bytes, Logical);
949}
950
951/*******************************************************************************
952**
953** gckOS_Allocate
954**
955** Allocate memory.
956**
957** INPUT:
958**
959** gckOS Os
960** Pointer to an gckOS object.
961**
962** gctSIZE_T Bytes
963** Number of bytes to allocate.
964**
965** OUTPUT:
966**
967** gctPOINTER * Memory
968** Pointer to a variable that will hold the allocated memory location.
969*/
970gceSTATUS
971gckOS_Allocate(
972 IN gckOS Os,
973 IN gctSIZE_T Bytes,
974 OUT gctPOINTER * Memory
975 )
976{
977 gceSTATUS status;
978
979 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
980
981 /* Verify the arguments. */
982 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
983 gcmkVERIFY_ARGUMENT(Bytes > 0);
984 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
985
986 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
987
988 /* Success. */
989 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
990 return gcvSTATUS_OK;
991
992OnError:
993 /* Return the status. */
994 gcmkFOOTER();
995 return status;
996}
997
998/*******************************************************************************
999**
1000** gckOS_Free
1001**
1002** Free allocated memory.
1003**
1004** INPUT:
1005**
1006** gckOS Os
1007** Pointer to an gckOS object.
1008**
1009** gctPOINTER Memory
1010** Pointer to memory allocation to free.
1011**
1012** OUTPUT:
1013**
1014** Nothing.
1015*/
1016gceSTATUS
1017gckOS_Free(
1018 IN gckOS Os,
1019 IN gctPOINTER Memory
1020 )
1021{
1022 gceSTATUS status;
1023
1024 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
1025
1026 /* Verify the arguments. */
1027 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1028 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1029
1030 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
1031
1032 /* Success. */
1033 gcmkFOOTER_NO();
1034 return gcvSTATUS_OK;
1035
1036OnError:
1037 /* Return the status. */
1038 gcmkFOOTER();
1039 return status;
1040}
1041
1042/*******************************************************************************
1043**
1044** gckOS_AllocateMemory
1045**
1046** Allocate memory wrapper.
1047**
1048** INPUT:
1049**
1050** gctSIZE_T Bytes
1051** Number of bytes to allocate.
1052**
1053** OUTPUT:
1054**
1055** gctPOINTER * Memory
1056** Pointer to a variable that will hold the allocated memory location.
1057*/
1058gceSTATUS
1059gckOS_AllocateMemory(
1060 IN gckOS Os,
1061 IN gctSIZE_T Bytes,
1062 OUT gctPOINTER * Memory
1063 )
1064{
1065 gctPOINTER memory;
1066 gceSTATUS status;
1067
1068 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1069
1070 /* Verify the arguments. */
1071 gcmkVERIFY_ARGUMENT(Bytes > 0);
1072 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1073
1074 if (Bytes > PAGE_SIZE)
1075 {
1076 memory = (gctPOINTER) vmalloc(Bytes);
1077 }
1078 else
1079 {
1080 memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
1081 }
1082
1083 if (memory == gcvNULL)
1084 {
1085 /* Out of memory. */
1086 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1087 }
1088
1089 /* Increase count. */
1090 atomic_inc(&Os->allocateCount);
1091
1092 /* Return pointer to the memory allocation. */
1093 *Memory = memory;
1094
1095 /* Success. */
1096 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1097 return gcvSTATUS_OK;
1098
1099OnError:
1100 /* Return the status. */
1101 gcmkFOOTER();
1102 return status;
1103}
1104
1105/*******************************************************************************
1106**
1107** gckOS_FreeMemory
1108**
1109** Free allocated memory wrapper.
1110**
1111** INPUT:
1112**
1113** gctPOINTER Memory
1114** Pointer to memory allocation to free.
1115**
1116** OUTPUT:
1117**
1118** Nothing.
1119*/
1120gceSTATUS
1121gckOS_FreeMemory(
1122 IN gckOS Os,
1123 IN gctPOINTER Memory
1124 )
1125{
1126 gcmkHEADER_ARG("Memory=0x%X", Memory);
1127
1128 /* Verify the arguments. */
1129 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1130
1131 /* Free the memory from the OS pool. */
1132 if (is_vmalloc_addr(Memory))
1133 {
1134 vfree(Memory);
1135 }
1136 else
1137 {
1138 kfree(Memory);
1139 }
1140
1141 /* Decrease count. */
1142 atomic_dec(&Os->allocateCount);
1143
1144 /* Success. */
1145 gcmkFOOTER_NO();
1146 return gcvSTATUS_OK;
1147}
1148
1149/*******************************************************************************
1150**
1151** gckOS_MapMemory
1152**
1153** Map physical memory into the current process.
1154**
1155** INPUT:
1156**
1157** gckOS Os
1158** Pointer to an gckOS object.
1159**
1160** gctPHYS_ADDR Physical
1161** Start of physical address memory.
1162**
1163** gctSIZE_T Bytes
1164** Number of bytes to map.
1165**
1166** OUTPUT:
1167**
1168** gctPOINTER * Memory
1169** Pointer to a variable that will hold the logical address of the
1170** mapped memory.
1171*/
1172gceSTATUS
1173gckOS_MapMemory(
1174 IN gckOS Os,
1175 IN gctPHYS_ADDR Physical,
1176 IN gctSIZE_T Bytes,
1177 OUT gctPOINTER * Logical
1178 )
1179{
1180 PLINUX_MDL_MAP mdlMap;
1181 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1182
1183 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
1184
1185 /* Verify the arguments. */
1186 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1187 gcmkVERIFY_ARGUMENT(Physical != 0);
1188 gcmkVERIFY_ARGUMENT(Bytes > 0);
1189 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1190
1191 MEMORY_LOCK(Os);
1192
1193 mdlMap = FindMdlMap(mdl, _GetProcessID());
1194
1195 if (mdlMap == gcvNULL)
1196 {
1197 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1198
1199 if (mdlMap == gcvNULL)
1200 {
1201 MEMORY_UNLOCK(Os);
1202
1203 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1204 return gcvSTATUS_OUT_OF_MEMORY;
1205 }
1206 }
1207
1208 if (mdlMap->vmaAddr == gcvNULL)
1209 {
1210#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1211 mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
1212 0L,
1213 mdl->numPages * PAGE_SIZE,
1214 PROT_READ | PROT_WRITE,
1215 MAP_SHARED,
1216 0);
1217#else
1218 down_write(&current->mm->mmap_sem);
1219
1220 mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
1221 0L,
1222 mdl->numPages * PAGE_SIZE,
1223 PROT_READ | PROT_WRITE,
1224 MAP_SHARED,
1225 0);
1226
1227 up_write(&current->mm->mmap_sem);
1228#endif
1229
1230 if (IS_ERR(mdlMap->vmaAddr))
1231 {
1232 gcmkTRACE(
1233 gcvLEVEL_ERROR,
1234 "%s(%d): do_mmap_pgoff error",
1235 __FUNCTION__, __LINE__
1236 );
1237
1238 gcmkTRACE(
1239 gcvLEVEL_ERROR,
1240 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1241 __FUNCTION__, __LINE__,
1242 mdl->numPages,
1243 mdlMap->vmaAddr
1244 );
1245
1246 mdlMap->vmaAddr = gcvNULL;
1247
1248 MEMORY_UNLOCK(Os);
1249
1250 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1251 return gcvSTATUS_OUT_OF_MEMORY;
1252 }
1253
1254 down_write(&current->mm->mmap_sem);
1255
1256 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1257
1258 if (!mdlMap->vma)
1259 {
1260 gcmkTRACE(
1261 gcvLEVEL_ERROR,
1262 "%s(%d): find_vma error.",
1263 __FUNCTION__, __LINE__
1264 );
1265
1266 mdlMap->vmaAddr = gcvNULL;
1267
1268 up_write(&current->mm->mmap_sem);
1269
1270 MEMORY_UNLOCK(Os);
1271
1272 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1273 return gcvSTATUS_OUT_OF_RESOURCES;
1274 }
1275
1276#ifndef NO_DMA_COHERENT
1277 if (dma_mmap_writecombine(gcvNULL,
1278 mdlMap->vma,
1279 mdl->addr,
1280 mdl->dmaHandle,
1281 mdl->numPages * PAGE_SIZE) < 0)
1282 {
1283 up_write(&current->mm->mmap_sem);
1284
1285 gcmkTRACE(
1286 gcvLEVEL_ERROR,
1287 "%s(%d): dma_mmap_coherent error.",
1288 __FUNCTION__, __LINE__
1289 );
1290
1291 mdlMap->vmaAddr = gcvNULL;
1292
1293 MEMORY_UNLOCK(Os);
1294
1295 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1296 return gcvSTATUS_OUT_OF_RESOURCES;
1297 }
1298#else
1299#if !gcdPAGED_MEMORY_CACHEABLE
1300 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1301 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1302# endif
1303 mdlMap->vma->vm_pgoff = 0;
1304
1305 if (remap_pfn_range(mdlMap->vma,
1306 mdlMap->vma->vm_start,
1307 mdl->dmaHandle >> PAGE_SHIFT,
1308 mdl->numPages*PAGE_SIZE,
1309 mdlMap->vma->vm_page_prot) < 0)
1310 {
1311 up_write(&current->mm->mmap_sem);
1312
1313 gcmkTRACE(
1314 gcvLEVEL_ERROR,
1315 "%s(%d): remap_pfn_range error.",
1316 __FUNCTION__, __LINE__
1317 );
1318
1319 mdlMap->vmaAddr = gcvNULL;
1320
1321 MEMORY_UNLOCK(Os);
1322
1323 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1324 return gcvSTATUS_OUT_OF_RESOURCES;
1325 }
1326#endif
1327
1328 up_write(&current->mm->mmap_sem);
1329 }
1330
1331 MEMORY_UNLOCK(Os);
1332
1333 *Logical = mdlMap->vmaAddr;
1334
1335 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
1336 return gcvSTATUS_OK;
1337}
1338
1339/*******************************************************************************
1340**
1341** gckOS_UnmapMemory
1342**
1343** Unmap physical memory out of the current process.
1344**
1345** INPUT:
1346**
1347** gckOS Os
1348** Pointer to an gckOS object.
1349**
1350** gctPHYS_ADDR Physical
1351** Start of physical address memory.
1352**
1353** gctSIZE_T Bytes
1354** Number of bytes to unmap.
1355**
1356** gctPOINTER Memory
1357** Pointer to a previously mapped memory region.
1358**
1359** OUTPUT:
1360**
1361** Nothing.
1362*/
1363gceSTATUS
1364gckOS_UnmapMemory(
1365 IN gckOS Os,
1366 IN gctPHYS_ADDR Physical,
1367 IN gctSIZE_T Bytes,
1368 IN gctPOINTER Logical
1369 )
1370{
1371 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1372 Os, Physical, Bytes, Logical);
1373
1374 /* Verify the arguments. */
1375 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1376 gcmkVERIFY_ARGUMENT(Physical != 0);
1377 gcmkVERIFY_ARGUMENT(Bytes > 0);
1378 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1379
1380 gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
1381
1382 /* Success. */
1383 gcmkFOOTER_NO();
1384 return gcvSTATUS_OK;
1385}
1386
1387
1388/*******************************************************************************
1389**
1390** gckOS_UnmapMemoryEx
1391**
1392** Unmap physical memory in the specified process.
1393**
1394** INPUT:
1395**
1396** gckOS Os
1397** Pointer to an gckOS object.
1398**
1399** gctPHYS_ADDR Physical
1400** Start of physical address memory.
1401**
1402** gctSIZE_T Bytes
1403** Number of bytes to unmap.
1404**
1405** gctPOINTER Memory
1406** Pointer to a previously mapped memory region.
1407**
1408** gctUINT32 PID
1409** Pid of the process that opened the device and mapped this memory.
1410**
1411** OUTPUT:
1412**
1413** Nothing.
1414*/
1415gceSTATUS
1416gckOS_UnmapMemoryEx(
1417 IN gckOS Os,
1418 IN gctPHYS_ADDR Physical,
1419 IN gctSIZE_T Bytes,
1420 IN gctPOINTER Logical,
1421 IN gctUINT32 PID
1422 )
1423{
1424 PLINUX_MDL_MAP mdlMap;
1425 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1426
1427 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1428 Os, Physical, Bytes, Logical, PID);
1429
1430 /* Verify the arguments. */
1431 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1432 gcmkVERIFY_ARGUMENT(Physical != 0);
1433 gcmkVERIFY_ARGUMENT(Bytes > 0);
1434 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1435 gcmkVERIFY_ARGUMENT(PID != 0);
1436
1437 MEMORY_LOCK(Os);
1438
1439 if (Logical)
1440 {
1441 mdlMap = FindMdlMap(mdl, PID);
1442
1443 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1444 {
1445 MEMORY_UNLOCK(Os);
1446
1447 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
1448 return gcvSTATUS_INVALID_ARGUMENT;
1449 }
1450
1451 _UnmapUserLogical(mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
1452
1453 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1454 }
1455
1456 MEMORY_UNLOCK(Os);
1457
1458 /* Success. */
1459 gcmkFOOTER_NO();
1460 return gcvSTATUS_OK;
1461}
1462
1463/*******************************************************************************
1464**
1465** gckOS_UnmapUserLogical
1466**
1467** Unmap user logical memory out of physical memory.
1468**
1469** INPUT:
1470**
1471** gckOS Os
1472** Pointer to an gckOS object.
1473**
1474** gctPHYS_ADDR Physical
1475** Start of physical address memory.
1476**
1477** gctSIZE_T Bytes
1478** Number of bytes to unmap.
1479**
1480** gctPOINTER Memory
1481** Pointer to a previously mapped memory region.
1482**
1483** OUTPUT:
1484**
1485** Nothing.
1486*/
1487gceSTATUS
1488gckOS_UnmapUserLogical(
1489 IN gckOS Os,
1490 IN gctPHYS_ADDR Physical,
1491 IN gctSIZE_T Bytes,
1492 IN gctPOINTER Logical
1493 )
1494{
1495 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1496 Os, Physical, Bytes, Logical);
1497
1498 /* Verify the arguments. */
1499 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1500 gcmkVERIFY_ARGUMENT(Physical != 0);
1501 gcmkVERIFY_ARGUMENT(Bytes > 0);
1502 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1503
1504 gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
1505
1506 /* Success. */
1507 gcmkFOOTER_NO();
1508 return gcvSTATUS_OK;
1509
1510}
1511
1512/*******************************************************************************
1513**
1514** gckOS_AllocateNonPagedMemory
1515**
1516** Allocate a number of pages from non-paged memory.
1517**
1518** INPUT:
1519**
1520** gckOS Os
1521** Pointer to an gckOS object.
1522**
1523** gctBOOL InUserSpace
1524** gcvTRUE if the pages need to be mapped into user space.
1525**
1526** gctSIZE_T * Bytes
1527** Pointer to a variable that holds the number of bytes to allocate.
1528**
1529** OUTPUT:
1530**
1531** gctSIZE_T * Bytes
1532** Pointer to a variable that hold the number of bytes allocated.
1533**
1534** gctPHYS_ADDR * Physical
1535** Pointer to a variable that will hold the physical address of the
1536** allocation.
1537**
1538** gctPOINTER * Logical
1539** Pointer to a variable that will hold the logical address of the
1540** allocation.
1541*/
1542gceSTATUS
1543gckOS_AllocateNonPagedMemory(
1544 IN gckOS Os,
1545 IN gctBOOL InUserSpace,
1546 IN OUT gctSIZE_T * Bytes,
1547 OUT gctPHYS_ADDR * Physical,
1548 OUT gctPOINTER * Logical
1549 )
1550{
1551 gctSIZE_T bytes;
1552 gctINT numPages;
1553 PLINUX_MDL mdl = gcvNULL;
1554 PLINUX_MDL_MAP mdlMap = gcvNULL;
1555 gctSTRING addr;
1556 gckKERNEL kernel;
1557#ifdef NO_DMA_COHERENT
1558 struct page * page;
1559 long size, order;
1560 gctPOINTER vaddr;
1561#endif
1562 gctBOOL locked = gcvFALSE;
1563 gceSTATUS status;
1564
1565 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1566 Os, InUserSpace, gcmOPT_VALUE(Bytes));
1567
1568 /* Verify the arguments. */
1569 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1570 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
1571 gcmkVERIFY_ARGUMENT(*Bytes > 0);
1572 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1573 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1574
1575 /* Align number of bytes to page size. */
1576 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1577
1578 /* Get total number of pages.. */
1579 numPages = GetPageCount(bytes, 0);
1580
1581 /* Allocate mdl+vector structure */
1582 mdl = _CreateMdl();
1583 if (mdl == gcvNULL)
1584 {
1585 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1586 }
1587
1588 mdl->pagedMem = 0;
1589 mdl->numPages = numPages;
1590
1591 MEMORY_LOCK(Os);
1592 locked = gcvTRUE;
1593
1594#ifndef NO_DMA_COHERENT
1595#ifdef CONFIG_ARM64
1596 addr = dma_alloc_coherent(gcvNULL,
1597#else
1598 addr = dma_alloc_writecombine(gcvNULL,
1599#endif
1600 mdl->numPages * PAGE_SIZE,
1601 &mdl->dmaHandle,
1602 GFP_KERNEL | gcdNOWARN);
1603#else
1604 size = mdl->numPages * PAGE_SIZE;
1605 order = get_order(size);
1606
1607 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
1608
1609 if (page == gcvNULL)
1610 {
1611 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1612 }
1613
1614 vaddr = (gctPOINTER)page_address(page);
1615 mdl->contiguous = gcvTRUE;
1616 mdl->u.contiguousPages = page;
1617 addr = _CreateKernelVirtualMapping(mdl);
1618 mdl->dmaHandle = virt_to_phys(vaddr);
1619 mdl->kaddr = vaddr;
1620
1621 /* Trigger a page fault. */
1622 memset(addr, 0, numPages * PAGE_SIZE);
1623
1624#if !defined(CONFIG_PPC)
1625 /* Cache invalidate. */
1626 dma_sync_single_for_device(
1627 gcvNULL,
1628 page_to_phys(page),
1629 bytes,
1630 DMA_FROM_DEVICE);
1631#endif
1632
1633 while (size > 0)
1634 {
1635 SetPageReserved(virt_to_page(vaddr));
1636
1637 vaddr += PAGE_SIZE;
1638 size -= PAGE_SIZE;
1639 }
1640#endif
1641
1642 if (addr == gcvNULL)
1643 {
1644 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1645 }
1646
1647 kernel = Os->device->kernels[gcvCORE_MAJOR] != gcvNULL ?
1648 Os->device->kernels[gcvCORE_MAJOR] : Os->device->kernels[gcvCORE_2D];
1649
1650#ifdef CONFLICT_BETWEEN_BASE_AND_PHYS
1651 if (((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000)) &&
1652 kernel->hardware->mmuVersion == 0)
1653 {
1654 mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
1655 | (Os->device->baseAddress & 0x80000000);
1656 }
1657#endif
1658
1659 mdl->addr = addr;
1660
1661 if (InUserSpace)
1662 {
1663 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1664
1665 if (mdlMap == gcvNULL)
1666 {
1667 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1668 }
1669
1670 /* Only after mmap this will be valid. */
1671
1672 /* We need to map this to user space. */
1673#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1674 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
1675 0L,
1676 mdl->numPages * PAGE_SIZE,
1677 PROT_READ | PROT_WRITE,
1678 MAP_SHARED,
1679 0);
1680#else
1681 down_write(&current->mm->mmap_sem);
1682
1683 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
1684 0L,
1685 mdl->numPages * PAGE_SIZE,
1686 PROT_READ | PROT_WRITE,
1687 MAP_SHARED,
1688 0);
1689
1690 up_write(&current->mm->mmap_sem);
1691#endif
1692
1693 if (IS_ERR(mdlMap->vmaAddr))
1694 {
1695 gcmkTRACE_ZONE(
1696 gcvLEVEL_WARNING, gcvZONE_OS,
1697 "%s(%d): do_mmap_pgoff error",
1698 __FUNCTION__, __LINE__
1699 );
1700
1701 mdlMap->vmaAddr = gcvNULL;
1702
1703 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1704 }
1705
1706 down_write(&current->mm->mmap_sem);
1707
1708 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1709
1710 if (mdlMap->vma == gcvNULL)
1711 {
1712 gcmkTRACE_ZONE(
1713 gcvLEVEL_WARNING, gcvZONE_OS,
1714 "%s(%d): find_vma error",
1715 __FUNCTION__, __LINE__
1716 );
1717
1718 up_write(&current->mm->mmap_sem);
1719
1720 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1721 }
1722
1723#ifndef NO_DMA_COHERENT
1724 if (dma_mmap_coherent(gcvNULL,
1725 mdlMap->vma,
1726 mdl->addr,
1727 mdl->dmaHandle,
1728 mdl->numPages * PAGE_SIZE) < 0)
1729 {
1730 gcmkTRACE_ZONE(
1731 gcvLEVEL_WARNING, gcvZONE_OS,
1732 "%s(%d): dma_mmap_coherent error",
1733 __FUNCTION__, __LINE__
1734 );
1735
1736 up_write(&current->mm->mmap_sem);
1737
1738 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1739 }
1740#else
1741 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1742 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1743 mdlMap->vma->vm_pgoff = 0;
1744
1745 if (remap_pfn_range(mdlMap->vma,
1746 mdlMap->vma->vm_start,
1747 mdl->dmaHandle >> PAGE_SHIFT,
1748 mdl->numPages * PAGE_SIZE,
1749 mdlMap->vma->vm_page_prot))
1750 {
1751 gcmkTRACE_ZONE(
1752 gcvLEVEL_WARNING, gcvZONE_OS,
1753 "%s(%d): remap_pfn_range error",
1754 __FUNCTION__, __LINE__
1755 );
1756
1757 up_write(&current->mm->mmap_sem);
1758
1759 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1760 }
1761#endif /* NO_DMA_COHERENT */
1762
1763 up_write(&current->mm->mmap_sem);
1764
1765 *Logical = mdlMap->vmaAddr;
1766 }
1767 else
1768 {
1769 *Logical = (gctPOINTER)mdl->addr;
1770 }
1771
1772 /*
1773 * Add this to a global list.
1774 * Will be used by get physical address
1775 * and mapuser pointer functions.
1776 */
1777
1778 if (!Os->mdlHead)
1779 {
1780 /* Initialize the queue. */
1781 Os->mdlHead = Os->mdlTail = mdl;
1782 }
1783 else
1784 {
1785 /* Add to the tail. */
1786 mdl->prev = Os->mdlTail;
1787 Os->mdlTail->next = mdl;
1788 Os->mdlTail = mdl;
1789 }
1790
1791 MEMORY_UNLOCK(Os);
1792
1793 /* Return allocated memory. */
1794 *Bytes = bytes;
1795 *Physical = (gctPHYS_ADDR) mdl;
1796
1797 /* Success. */
1798 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
1799 *Bytes, *Physical, *Logical);
1800 return gcvSTATUS_OK;
1801
1802OnError:
1803 if (mdlMap != gcvNULL)
1804 {
1805 /* Free LINUX_MDL_MAP. */
1806 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1807 }
1808
1809 if (mdl != gcvNULL)
1810 {
1811 /* Free LINUX_MDL. */
1812 gcmkVERIFY_OK(_DestroyMdl(mdl));
1813 }
1814
1815 if (locked)
1816 {
1817 /* Unlock memory. */
1818 MEMORY_UNLOCK(Os);
1819 }
1820
1821 /* Return the status. */
1822 gcmkFOOTER();
1823 return status;
1824}
1825
1826/*******************************************************************************
1827**
1828** gckOS_FreeNonPagedMemory
1829**
1830** Free previously allocated and mapped pages from non-paged memory.
1831**
1832** INPUT:
1833**
1834** gckOS Os
1835** Pointer to an gckOS object.
1836**
1837** gctSIZE_T Bytes
1838** Number of bytes allocated.
1839**
1840** gctPHYS_ADDR Physical
1841** Physical address of the allocated memory.
1842**
1843** gctPOINTER Logical
1844** Logical address of the allocated memory.
1845**
1846** OUTPUT:
1847**
1848** Nothing.
1849*/
1850gceSTATUS gckOS_FreeNonPagedMemory(
1851 IN gckOS Os,
1852 IN gctSIZE_T Bytes,
1853 IN gctPHYS_ADDR Physical,
1854 IN gctPOINTER Logical
1855 )
1856{
1857 PLINUX_MDL mdl;
1858 PLINUX_MDL_MAP mdlMap;
1859#ifdef NO_DMA_COHERENT
1860 unsigned size;
1861 gctPOINTER vaddr;
1862#endif /* NO_DMA_COHERENT */
1863
1864 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
1865 Os, Bytes, Physical, Logical);
1866
1867 /* Verify the arguments. */
1868 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1869 gcmkVERIFY_ARGUMENT(Bytes > 0);
1870 gcmkVERIFY_ARGUMENT(Physical != 0);
1871 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1872
1873 /* Convert physical address into a pointer to a MDL. */
1874 mdl = (PLINUX_MDL) Physical;
1875
1876 MEMORY_LOCK(Os);
1877
1878#ifndef NO_DMA_COHERENT
1879#ifdef CONFIG_ARM64
1880 dma_free_coherent(gcvNULL,
1881#else
1882 dma_free_writecombine(gcvNULL,
1883#endif
1884 mdl->numPages * PAGE_SIZE,
1885 mdl->addr,
1886 mdl->dmaHandle);
1887#else
1888 size = mdl->numPages * PAGE_SIZE;
1889 vaddr = mdl->kaddr;
1890
1891 while (size > 0)
1892 {
1893 ClearPageReserved(virt_to_page(vaddr));
1894
1895 vaddr += PAGE_SIZE;
1896 size -= PAGE_SIZE;
1897 }
1898
1899 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
1900
1901 _DestoryKernelVirtualMapping(mdl->addr);
1902#endif /* NO_DMA_COHERENT */
1903
1904 mdlMap = mdl->maps;
1905
1906 while (mdlMap != gcvNULL)
1907 {
1908 /* No mapped memory exists when free nonpaged memory */
1909 gcmkASSERT(mdlMap->vmaAddr == gcvNULL);
1910
1911 mdlMap = mdlMap->next;
1912 }
1913
1914 /* Remove the node from global list.. */
1915 if (mdl == Os->mdlHead)
1916 {
1917 if ((Os->mdlHead = mdl->next) == gcvNULL)
1918 {
1919 Os->mdlTail = gcvNULL;
1920 }
1921 }
1922 else
1923 {
1924 mdl->prev->next = mdl->next;
1925 if (mdl == Os->mdlTail)
1926 {
1927 Os->mdlTail = mdl->prev;
1928 }
1929 else
1930 {
1931 mdl->next->prev = mdl->prev;
1932 }
1933 }
1934
1935 MEMORY_UNLOCK(Os);
1936
1937 gcmkVERIFY_OK(_DestroyMdl(mdl));
1938
1939 /* Success. */
1940 gcmkFOOTER_NO();
1941 return gcvSTATUS_OK;
1942}
1943
1944/*******************************************************************************
1945**
1946** gckOS_ReadRegister
1947**
1948** Read data from a register.
1949**
1950** INPUT:
1951**
1952** gckOS Os
1953** Pointer to an gckOS object.
1954**
1955** gctUINT32 Address
1956** Address of register.
1957**
1958** OUTPUT:
1959**
1960** gctUINT32 * Data
1961** Pointer to a variable that receives the data read from the register.
1962*/
1963gceSTATUS
1964gckOS_ReadRegister(
1965 IN gckOS Os,
1966 IN gctUINT32 Address,
1967 OUT gctUINT32 * Data
1968 )
1969{
1970 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
1971}
1972
1973gceSTATUS
1974gckOS_ReadRegisterEx(
1975 IN gckOS Os,
1976 IN gceCORE Core,
1977 IN gctUINT32 Address,
1978 OUT gctUINT32 * Data
1979 )
1980{
1981 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
1982
1983 /* Verify the arguments. */
1984 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1985 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
1986 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
1987
1988 if (!in_interrupt())
1989 {
1990 mutex_lock(&Os->registerAccessLocks[Core]);
1991 }
1992
1993 BUG_ON(!_AllowAccess(Os, Core, Address));
1994
1995 {
1996 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
1997 }
1998
1999 if (!in_interrupt())
2000 {
2001 mutex_unlock(&Os->registerAccessLocks[Core]);
2002 }
2003
2004 /* Success. */
2005 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2006 return gcvSTATUS_OK;
2007}
2008
2009
2010/*******************************************************************************
2011**
2012** gckOS_WriteRegister
2013**
2014** Write data to a register.
2015**
2016** INPUT:
2017**
2018** gckOS Os
2019** Pointer to an gckOS object.
2020**
2021** gctUINT32 Address
2022** Address of register.
2023**
2024** gctUINT32 Data
2025** Data for register.
2026**
2027** OUTPUT:
2028**
2029** Nothing.
2030*/
2031gceSTATUS
2032gckOS_WriteRegister(
2033 IN gckOS Os,
2034 IN gctUINT32 Address,
2035 IN gctUINT32 Data
2036 )
2037{
2038 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2039}
2040
2041gceSTATUS
2042gckOS_WriteRegisterEx(
2043 IN gckOS Os,
2044 IN gceCORE Core,
2045 IN gctUINT32 Address,
2046 IN gctUINT32 Data
2047 )
2048{
2049 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2050
2051 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2052
2053 if (!in_interrupt())
2054 {
2055 mutex_lock(&Os->registerAccessLocks[Core]);
2056 }
2057
2058 BUG_ON(!_AllowAccess(Os, Core, Address));
2059
2060 {
2061 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2062 }
2063
2064 if (!in_interrupt())
2065 {
2066 mutex_unlock(&Os->registerAccessLocks[Core]);
2067 }
2068
2069 /* Success. */
2070 gcmkFOOTER_NO();
2071 return gcvSTATUS_OK;
2072}
2073
2074
2075/*******************************************************************************
2076**
2077** gckOS_GetPageSize
2078**
2079** Get the system's page size.
2080**
2081** INPUT:
2082**
2083** gckOS Os
2084** Pointer to an gckOS object.
2085**
2086** OUTPUT:
2087**
2088** gctSIZE_T * PageSize
2089** Pointer to a variable that will receive the system's page size.
2090*/
2091gceSTATUS gckOS_GetPageSize(
2092 IN gckOS Os,
2093 OUT gctSIZE_T * PageSize
2094 )
2095{
2096 gcmkHEADER_ARG("Os=0x%X", Os);
2097
2098 /* Verify the arguments. */
2099 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2100 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2101
2102 /* Return the page size. */
2103 *PageSize = (gctSIZE_T) PAGE_SIZE;
2104
2105 /* Success. */
2106 gcmkFOOTER_ARG("*PageSize", *PageSize);
2107 return gcvSTATUS_OK;
2108}
2109
2110/*******************************************************************************
2111**
2112** gckOS_GetPhysicalAddressProcess
2113**
2114** Get the physical system address of a corresponding virtual address for a
2115** given process.
2116**
2117** INPUT:
2118**
2119** gckOS Os
2120** Pointer to gckOS object.
2121**
2122** gctPOINTER Logical
2123** Logical address.
2124**
2125** gctUINT32 ProcessID
2126** Process ID.
2127**
2128** OUTPUT:
2129**
2130** gctUINT32 * Address
2131** Poinetr to a variable that receives the 32-bit physical adress.
2132*/
2133gceSTATUS
2134_GetPhysicalAddressProcess(
2135 IN gckOS Os,
2136 IN gctPOINTER Logical,
2137 IN gctUINT32 ProcessID,
2138 OUT gctPHYS_ADDR_T * Address
2139 )
2140{
2141 PLINUX_MDL mdl;
2142 gctINT8_PTR base;
2143 gckALLOCATOR allocator = gcvNULL;
2144 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2145
2146 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2147
2148 /* Verify the arguments. */
2149 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2150 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2151
2152 MEMORY_LOCK(Os);
2153
2154 /* First try the contiguous memory pool. */
2155 if (Os->device->contiguousMapped)
2156 {
2157 base = (gctINT8_PTR) Os->device->contiguousBase;
2158
2159 if (((gctINT8_PTR) Logical >= base)
2160 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2161 )
2162 {
2163 /* Convert logical address into physical. */
2164 *Address = Os->device->contiguousVidMem->baseAddress
2165 + (gctINT8_PTR) Logical - base;
2166 status = gcvSTATUS_OK;
2167 }
2168 }
2169 else
2170 {
2171 /* Try the contiguous memory pool. */
2172 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2173 status = _ConvertLogical2Physical(Os,
2174 Logical,
2175 ProcessID,
2176 mdl,
2177 Address);
2178 }
2179
2180 if (gcmIS_ERROR(status))
2181 {
2182 /* Walk all MDLs. */
2183 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2184 {
2185 /* Try this MDL. */
2186 allocator = mdl->allocator;
2187
2188 if (allocator)
2189 {
2190 status = allocator->ops->LogicalToPhysical(
2191 allocator,
2192 mdl,
2193 Logical,
2194 ProcessID,
2195 Address
2196 );
2197 }
2198 else
2199 {
2200 status = _ConvertLogical2Physical(Os,
2201 Logical,
2202 ProcessID,
2203 mdl,
2204 Address);
2205 }
2206
2207 if (gcmIS_SUCCESS(status))
2208 {
2209 break;
2210 }
2211 }
2212 }
2213
2214 MEMORY_UNLOCK(Os);
2215
2216 gcmkONERROR(status);
2217
2218 /* Success. */
2219 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2220 return gcvSTATUS_OK;
2221
2222OnError:
2223 /* Return the status. */
2224 gcmkFOOTER();
2225 return status;
2226}
2227
2228
2229
2230/*******************************************************************************
2231**
2232** gckOS_GetPhysicalAddress
2233**
2234** Get the physical system address of a corresponding virtual address.
2235**
2236** INPUT:
2237**
2238** gckOS Os
2239** Pointer to an gckOS object.
2240**
2241** gctPOINTER Logical
2242** Logical address.
2243**
2244** OUTPUT:
2245**
2246** gctUINT32 * Address
2247** Poinetr to a variable that receives the 32-bit physical adress.
2248*/
2249gceSTATUS
2250gckOS_GetPhysicalAddress(
2251 IN gckOS Os,
2252 IN gctPOINTER Logical,
2253 OUT gctPHYS_ADDR_T * Address
2254 )
2255{
2256 gceSTATUS status;
2257 gctUINT32 processID;
2258
2259 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2260
2261 /* Verify the arguments. */
2262 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2263 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2264
2265 /* Query page table of current process first. */
2266 status = _QueryProcessPageTable(Logical, Address);
2267
2268 if (gcmIS_ERROR(status))
2269 {
2270 /* Get current process ID. */
2271 processID = _GetProcessID();
2272
2273 /* Route through other function. */
2274 gcmkONERROR(
2275 _GetPhysicalAddressProcess(Os, Logical, processID, Address));
2276 }
2277
2278 gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, *Address, Address));
2279
2280 /* Success. */
2281 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2282 return gcvSTATUS_OK;
2283
2284OnError:
2285 /* Return the status. */
2286 gcmkFOOTER();
2287 return status;
2288}
2289
2290/*******************************************************************************
2291**
2292** gckOS_UserLogicalToPhysical
2293**
2294** Get the physical system address of a corresponding user virtual address.
2295**
2296** INPUT:
2297**
2298** gckOS Os
2299** Pointer to an gckOS object.
2300**
2301** gctPOINTER Logical
2302** Logical address.
2303**
2304** OUTPUT:
2305**
2306** gctUINT32 * Address
2307** Pointer to a variable that receives the 32-bit physical address.
2308*/
2309gceSTATUS gckOS_UserLogicalToPhysical(
2310 IN gckOS Os,
2311 IN gctPOINTER Logical,
2312 OUT gctPHYS_ADDR_T * Address
2313 )
2314{
2315 return gckOS_GetPhysicalAddress(Os, Logical, Address);
2316}
2317
2318#if gcdSECURE_USER
2319static gceSTATUS
2320gckOS_AddMapping(
2321 IN gckOS Os,
2322 IN gctUINT32 Physical,
2323 IN gctPOINTER Logical,
2324 IN gctSIZE_T Bytes
2325 )
2326{
2327 gceSTATUS status;
2328 gcsUSER_MAPPING_PTR map;
2329
2330 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2331 Os, Physical, Logical, Bytes);
2332
2333 gcmkONERROR(gckOS_Allocate(Os,
2334 gcmSIZEOF(gcsUSER_MAPPING),
2335 (gctPOINTER *) &map));
2336
2337 map->next = Os->userMap;
2338 map->physical = Physical - Os->device->baseAddress;
2339 map->logical = Logical;
2340 map->bytes = Bytes;
2341 map->start = (gctINT8_PTR) Logical;
2342 map->end = map->start + Bytes;
2343
2344 Os->userMap = map;
2345
2346 gcmkFOOTER_NO();
2347 return gcvSTATUS_OK;
2348
2349OnError:
2350 gcmkFOOTER();
2351 return status;
2352}
2353
2354static gceSTATUS
2355gckOS_RemoveMapping(
2356 IN gckOS Os,
2357 IN gctPOINTER Logical,
2358 IN gctSIZE_T Bytes
2359 )
2360{
2361 gceSTATUS status;
2362 gcsUSER_MAPPING_PTR map, prev;
2363
2364 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2365
2366 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2367 {
2368 if ((map->logical == Logical)
2369 && (map->bytes == Bytes)
2370 )
2371 {
2372 break;
2373 }
2374
2375 prev = map;
2376 }
2377
2378 if (map == gcvNULL)
2379 {
2380 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2381 }
2382
2383 if (prev == gcvNULL)
2384 {
2385 Os->userMap = map->next;
2386 }
2387 else
2388 {
2389 prev->next = map->next;
2390 }
2391
2392 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2393
2394 gcmkFOOTER_NO();
2395 return gcvSTATUS_OK;
2396
2397OnError:
2398 gcmkFOOTER();
2399 return status;
2400}
2401#endif
2402
2403gceSTATUS
2404_ConvertLogical2Physical(
2405 IN gckOS Os,
2406 IN gctPOINTER Logical,
2407 IN gctUINT32 ProcessID,
2408 IN PLINUX_MDL Mdl,
2409 OUT gctPHYS_ADDR_T * Physical
2410 )
2411{
2412 gctINT8_PTR base, vBase;
2413 gctUINT32 offset;
2414 PLINUX_MDL_MAP map;
2415 gcsUSER_MAPPING_PTR userMap;
2416
2417 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2418
2419 /* Check for the logical address match. */
2420 if ((base != gcvNULL)
2421 && ((gctINT8_PTR) Logical >= base)
2422 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2423 )
2424 {
2425 offset = (gctINT8_PTR) Logical - base;
2426
2427 if (Mdl->dmaHandle != 0)
2428 {
2429 /* The memory was from coherent area. */
2430 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2431 }
2432 else if (Mdl->pagedMem && !Mdl->contiguous)
2433 {
2434 /* paged memory is not mapped to kernel space. */
2435 return gcvSTATUS_INVALID_ADDRESS;
2436 }
2437 else
2438 {
2439 *Physical = gcmPTR2INT32(virt_to_phys(base)) + offset;
2440 }
2441
2442 return gcvSTATUS_OK;
2443 }
2444
2445 /* Walk user maps. */
2446 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2447 {
2448 if (((gctINT8_PTR) Logical >= userMap->start)
2449 && ((gctINT8_PTR) Logical < userMap->end)
2450 )
2451 {
2452 *Physical = userMap->physical
2453 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2454
2455 return gcvSTATUS_OK;
2456 }
2457 }
2458
2459 if (ProcessID != Os->kernelProcessID)
2460 {
2461 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2462 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2463
2464 /* Is the given address within that range. */
2465 if ((vBase != gcvNULL)
2466 && ((gctINT8_PTR) Logical >= vBase)
2467 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2468 )
2469 {
2470 offset = (gctINT8_PTR) Logical - vBase;
2471
2472 if (Mdl->dmaHandle != 0)
2473 {
2474 /* The memory was from coherent area. */
2475 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2476 }
2477 else if (Mdl->pagedMem && !Mdl->contiguous)
2478 {
2479 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2480 }
2481 else
2482 {
2483 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2484 }
2485
2486 return gcvSTATUS_OK;
2487 }
2488 }
2489
2490 /* Address not yet found. */
2491 return gcvSTATUS_INVALID_ADDRESS;
2492}
2493
2494/*******************************************************************************
2495**
2496** gckOS_MapPhysical
2497**
2498** Map a physical address into kernel space.
2499**
2500** INPUT:
2501**
2502** gckOS Os
2503** Pointer to an gckOS object.
2504**
2505** gctUINT32 Physical
2506** Physical address of the memory to map.
2507**
2508** gctSIZE_T Bytes
2509** Number of bytes to map.
2510**
2511** OUTPUT:
2512**
2513** gctPOINTER * Logical
2514** Pointer to a variable that receives the base address of the mapped
2515** memory.
2516*/
2517gceSTATUS
2518gckOS_MapPhysical(
2519 IN gckOS Os,
2520 IN gctUINT32 Physical,
2521 IN gctSIZE_T Bytes,
2522 OUT gctPOINTER * Logical
2523 )
2524{
2525 gctPOINTER logical;
2526 PLINUX_MDL mdl;
2527 gctUINT32 physical = Physical;
2528
2529 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2530
2531 /* Verify the arguments. */
2532 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2533 gcmkVERIFY_ARGUMENT(Bytes > 0);
2534 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2535
2536 MEMORY_LOCK(Os);
2537
2538 /* Go through our mapping to see if we know this physical address already. */
2539 mdl = Os->mdlHead;
2540
2541 while (mdl != gcvNULL)
2542 {
2543 if (mdl->dmaHandle != 0)
2544 {
2545 if ((physical >= mdl->dmaHandle)
2546 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2547 )
2548 {
2549 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2550 break;
2551 }
2552 }
2553
2554 mdl = mdl->next;
2555 }
2556
2557 MEMORY_UNLOCK(Os);
2558
2559 if (mdl == gcvNULL)
2560 {
2561 struct page * page = pfn_to_page(physical >> PAGE_SHIFT);
2562
2563 if (pfn_valid(page_to_pfn(page)))
2564 {
2565 gctUINT32 offset = physical & ~PAGE_MASK;
2566 struct page ** pages;
2567 gctUINT numPages;
2568 gctINT i;
2569
2570 numPages = GetPageCount(PAGE_ALIGN(offset + Bytes), 0);
2571
2572 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
2573
2574 if (!pages)
2575 {
2576 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
2577 return gcvSTATUS_OUT_OF_MEMORY;
2578 }
2579
2580 for (i = 0; i < numPages; i++)
2581 {
2582 pages[i] = nth_page(page, i);
2583 }
2584
2585 logical = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
2586
2587 kfree(pages);
2588
2589 if (logical == gcvNULL)
2590 {
2591 gcmkTRACE_ZONE(
2592 gcvLEVEL_INFO, gcvZONE_OS,
2593 "%s(%d): Failed to vmap",
2594 __FUNCTION__, __LINE__
2595 );
2596
2597 /* Out of resources. */
2598 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2599 return gcvSTATUS_OUT_OF_RESOURCES;
2600 }
2601
2602 logical += offset;
2603 }
2604 else
2605 {
2606 /* Map memory as cached memory. */
2607 request_mem_region(physical, Bytes, "MapRegion");
2608 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2609
2610 if (logical == gcvNULL)
2611 {
2612 gcmkTRACE_ZONE(
2613 gcvLEVEL_INFO, gcvZONE_OS,
2614 "%s(%d): Failed to ioremap",
2615 __FUNCTION__, __LINE__
2616 );
2617
2618 /* Out of resources. */
2619 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2620 return gcvSTATUS_OUT_OF_RESOURCES;
2621 }
2622 }
2623
2624 /* Return pointer to mapped memory. */
2625 *Logical = logical;
2626 }
2627
2628
2629 /* Success. */
2630 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2631 return gcvSTATUS_OK;
2632}
2633
2634/*******************************************************************************
2635**
2636** gckOS_UnmapPhysical
2637**
2638** Unmap a previously mapped memory region from kernel memory.
2639**
2640** INPUT:
2641**
2642** gckOS Os
2643** Pointer to an gckOS object.
2644**
2645** gctPOINTER Logical
2646** Pointer to the base address of the memory to unmap.
2647**
2648** gctSIZE_T Bytes
2649** Number of bytes to unmap.
2650**
2651** OUTPUT:
2652**
2653** Nothing.
2654*/
2655gceSTATUS
2656gckOS_UnmapPhysical(
2657 IN gckOS Os,
2658 IN gctPOINTER Logical,
2659 IN gctSIZE_T Bytes
2660 )
2661{
2662 PLINUX_MDL mdl;
2663
2664 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2665
2666 /* Verify the arguments. */
2667 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2668 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2669 gcmkVERIFY_ARGUMENT(Bytes > 0);
2670
2671 MEMORY_LOCK(Os);
2672
2673 mdl = Os->mdlHead;
2674
2675 while (mdl != gcvNULL)
2676 {
2677 if (mdl->addr != gcvNULL)
2678 {
2679 if (Logical >= (gctPOINTER)mdl->addr
2680 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
2681 {
2682 break;
2683 }
2684 }
2685
2686 mdl = mdl->next;
2687 }
2688
2689 if (mdl == gcvNULL)
2690 {
2691 /* Unmap the memory. */
2692 vunmap((void *)((unsigned long)Logical & PAGE_MASK));
2693 }
2694
2695 MEMORY_UNLOCK(Os);
2696
2697 /* Success. */
2698 gcmkFOOTER_NO();
2699 return gcvSTATUS_OK;
2700}
2701
2702/*******************************************************************************
2703**
2704** gckOS_DeleteMutex
2705**
2706** Delete a mutex.
2707**
2708** INPUT:
2709**
2710** gckOS Os
2711** Pointer to an gckOS object.
2712**
2713** gctPOINTER Mutex
2714** Pointer to the mute to be deleted.
2715**
2716** OUTPUT:
2717**
2718** Nothing.
2719*/
2720gceSTATUS
2721gckOS_DeleteMutex(
2722 IN gckOS Os,
2723 IN gctPOINTER Mutex
2724 )
2725{
2726 gceSTATUS status;
2727
2728 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
2729
2730 /* Validate the arguments. */
2731 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2732 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2733
2734 /* Destroy the mutex. */
2735 mutex_destroy((struct mutex *)Mutex);
2736
2737 /* Free the mutex structure. */
2738 gcmkONERROR(gckOS_Free(Os, Mutex));
2739
2740 gcmkFOOTER_NO();
2741 return gcvSTATUS_OK;
2742
2743OnError:
2744 /* Return status. */
2745 gcmkFOOTER();
2746 return status;
2747}
2748
2749/*******************************************************************************
2750**
2751** gckOS_AcquireMutex
2752**
2753** Acquire a mutex.
2754**
2755** INPUT:
2756**
2757** gckOS Os
2758** Pointer to an gckOS object.
2759**
2760** gctPOINTER Mutex
2761** Pointer to the mutex to be acquired.
2762**
2763** gctUINT32 Timeout
2764** Timeout value specified in milliseconds.
2765** Specify the value of gcvINFINITE to keep the thread suspended
2766** until the mutex has been acquired.
2767**
2768** OUTPUT:
2769**
2770** Nothing.
2771*/
2772gceSTATUS
2773gckOS_AcquireMutex(
2774 IN gckOS Os,
2775 IN gctPOINTER Mutex,
2776 IN gctUINT32 Timeout
2777 )
2778{
2779 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
2780
2781 /* Validate the arguments. */
2782 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2783 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2784
2785 if (Timeout == gcvINFINITE)
2786 {
2787 /* Lock the mutex. */
2788 mutex_lock(Mutex);
2789
2790 /* Success. */
2791 gcmkFOOTER_NO();
2792 return gcvSTATUS_OK;
2793 }
2794
2795 for (;;)
2796 {
2797 /* Try to acquire the mutex. */
2798 if (mutex_trylock(Mutex))
2799 {
2800 /* Success. */
2801 gcmkFOOTER_NO();
2802 return gcvSTATUS_OK;
2803 }
2804
2805 if (Timeout-- == 0)
2806 {
2807 break;
2808 }
2809
2810 /* Wait for 1 millisecond. */
2811 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
2812 }
2813
2814 /* Timeout. */
2815 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
2816 return gcvSTATUS_TIMEOUT;
2817}
2818
2819/*******************************************************************************
2820**
2821** gckOS_ReleaseMutex
2822**
2823** Release an acquired mutex.
2824**
2825** INPUT:
2826**
2827** gckOS Os
2828** Pointer to an gckOS object.
2829**
2830** gctPOINTER Mutex
2831** Pointer to the mutex to be released.
2832**
2833** OUTPUT:
2834**
2835** Nothing.
2836*/
2837gceSTATUS
2838gckOS_ReleaseMutex(
2839 IN gckOS Os,
2840 IN gctPOINTER Mutex
2841 )
2842{
2843 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
2844
2845 /* Validate the arguments. */
2846 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2847 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2848
2849 /* Release the mutex. */
2850 mutex_unlock(Mutex);
2851
2852 /* Success. */
2853 gcmkFOOTER_NO();
2854 return gcvSTATUS_OK;
2855}
2856
2857/*******************************************************************************
2858**
2859** gckOS_AtomicExchange
2860**
2861** Atomically exchange a pair of 32-bit values.
2862**
2863** INPUT:
2864**
2865** gckOS Os
2866** Pointer to an gckOS object.
2867**
2868** IN OUT gctINT32_PTR Target
2869** Pointer to the 32-bit value to exchange.
2870**
2871** IN gctINT32 NewValue
2872** Specifies a new value for the 32-bit value pointed to by Target.
2873**
2874** OUT gctINT32_PTR OldValue
2875** The old value of the 32-bit value pointed to by Target.
2876**
2877** OUTPUT:
2878**
2879** Nothing.
2880*/
2881gceSTATUS
2882gckOS_AtomicExchange(
2883 IN gckOS Os,
2884 IN OUT gctUINT32_PTR Target,
2885 IN gctUINT32 NewValue,
2886 OUT gctUINT32_PTR OldValue
2887 )
2888{
2889 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
2890
2891 /* Verify the arguments. */
2892 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2893 gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
2894
2895 /* Exchange the pair of 32-bit values. */
2896 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
2897
2898 /* Success. */
2899 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
2900 return gcvSTATUS_OK;
2901}
2902
2903/*******************************************************************************
2904**
2905** gckOS_AtomicExchangePtr
2906**
2907** Atomically exchange a pair of pointers.
2908**
2909** INPUT:
2910**
2911** gckOS Os
2912** Pointer to an gckOS object.
2913**
2914** IN OUT gctPOINTER * Target
2915** Pointer to the 32-bit value to exchange.
2916**
2917** IN gctPOINTER NewValue
2918** Specifies a new value for the pointer pointed to by Target.
2919**
2920** OUT gctPOINTER * OldValue
2921** The old value of the pointer pointed to by Target.
2922**
2923** OUTPUT:
2924**
2925** Nothing.
2926*/
2927gceSTATUS
2928gckOS_AtomicExchangePtr(
2929 IN gckOS Os,
2930 IN OUT gctPOINTER * Target,
2931 IN gctPOINTER NewValue,
2932 OUT gctPOINTER * OldValue
2933 )
2934{
2935 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
2936
2937 /* Verify the arguments. */
2938 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2939 gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
2940
2941 /* Exchange the pair of pointers. */
2942 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
2943
2944 /* Success. */
2945 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
2946 return gcvSTATUS_OK;
2947}
2948
2949/*******************************************************************************
2950**
2951** gckOS_AtomicSetMask
2952**
2953** Atomically set mask to Atom
2954**
2955** INPUT:
2956** IN OUT gctPOINTER Atom
2957** Pointer to the atom to set.
2958**
2959** IN gctUINT32 Mask
2960** Mask to set.
2961**
2962** OUTPUT:
2963**
2964** Nothing.
2965*/
2966gceSTATUS
2967gckOS_AtomSetMask(
2968 IN gctPOINTER Atom,
2969 IN gctUINT32 Mask
2970 )
2971{
2972 gctUINT32 oval, nval;
2973
2974 gcmkHEADER_ARG("Atom=0x%0x", Atom);
2975 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2976
2977 do
2978 {
2979 oval = atomic_read((atomic_t *) Atom);
2980 nval = oval | Mask;
2981 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
2982
2983 gcmkFOOTER_NO();
2984 return gcvSTATUS_OK;
2985}
2986
2987/*******************************************************************************
2988**
2989** gckOS_AtomClearMask
2990**
2991** Atomically clear mask from Atom
2992**
2993** INPUT:
2994** IN OUT gctPOINTER Atom
2995** Pointer to the atom to clear.
2996**
2997** IN gctUINT32 Mask
2998** Mask to clear.
2999**
3000** OUTPUT:
3001**
3002** Nothing.
3003*/
3004gceSTATUS
3005gckOS_AtomClearMask(
3006 IN gctPOINTER Atom,
3007 IN gctUINT32 Mask
3008 )
3009{
3010 gctUINT32 oval, nval;
3011
3012 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3013 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3014
3015 do
3016 {
3017 oval = atomic_read((atomic_t *) Atom);
3018 nval = oval & ~Mask;
3019 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3020
3021 gcmkFOOTER_NO();
3022 return gcvSTATUS_OK;
3023}
3024
3025/*******************************************************************************
3026**
3027** gckOS_AtomConstruct
3028**
3029** Create an atom.
3030**
3031** INPUT:
3032**
3033** gckOS Os
3034** Pointer to a gckOS object.
3035**
3036** OUTPUT:
3037**
3038** gctPOINTER * Atom
3039** Pointer to a variable receiving the constructed atom.
3040*/
3041gceSTATUS
3042gckOS_AtomConstruct(
3043 IN gckOS Os,
3044 OUT gctPOINTER * Atom
3045 )
3046{
3047 gceSTATUS status;
3048
3049 gcmkHEADER_ARG("Os=0x%X", Os);
3050
3051 /* Verify the arguments. */
3052 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3053 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3054
3055 /* Allocate the atom. */
3056 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3057
3058 /* Initialize the atom. */
3059 atomic_set((atomic_t *) *Atom, 0);
3060
3061 /* Success. */
3062 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3063 return gcvSTATUS_OK;
3064
3065OnError:
3066 /* Return the status. */
3067 gcmkFOOTER();
3068 return status;
3069}
3070
3071/*******************************************************************************
3072**
3073** gckOS_AtomDestroy
3074**
3075** Destroy an atom.
3076**
3077** INPUT:
3078**
3079** gckOS Os
3080** Pointer to a gckOS object.
3081**
3082** gctPOINTER Atom
3083** Pointer to the atom to destroy.
3084**
3085** OUTPUT:
3086**
3087** Nothing.
3088*/
3089gceSTATUS
3090gckOS_AtomDestroy(
3091 IN gckOS Os,
3092 OUT gctPOINTER Atom
3093 )
3094{
3095 gceSTATUS status;
3096
3097 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3098
3099 /* Verify the arguments. */
3100 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3101 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3102
3103 /* Free the atom. */
3104 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3105
3106 /* Success. */
3107 gcmkFOOTER_NO();
3108 return gcvSTATUS_OK;
3109
3110OnError:
3111 /* Return the status. */
3112 gcmkFOOTER();
3113 return status;
3114}
3115
3116/*******************************************************************************
3117**
3118** gckOS_AtomGet
3119**
3120** Get the 32-bit value protected by an atom.
3121**
3122** INPUT:
3123**
3124** gckOS Os
3125** Pointer to a gckOS object.
3126**
3127** gctPOINTER Atom
3128** Pointer to the atom.
3129**
3130** OUTPUT:
3131**
3132** gctINT32_PTR Value
3133** Pointer to a variable the receives the value of the atom.
3134*/
3135gceSTATUS
3136gckOS_AtomGet(
3137 IN gckOS Os,
3138 IN gctPOINTER Atom,
3139 OUT gctINT32_PTR Value
3140 )
3141{
3142 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3143
3144 /* Verify the arguments. */
3145 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3146 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3147
3148 /* Return the current value of atom. */
3149 *Value = atomic_read((atomic_t *) Atom);
3150
3151 /* Success. */
3152 gcmkFOOTER_ARG("*Value=%d", *Value);
3153 return gcvSTATUS_OK;
3154}
3155
3156/*******************************************************************************
3157**
3158** gckOS_AtomSet
3159**
3160** Set the 32-bit value protected by an atom.
3161**
3162** INPUT:
3163**
3164** gckOS Os
3165** Pointer to a gckOS object.
3166**
3167** gctPOINTER Atom
3168** Pointer to the atom.
3169**
3170** gctINT32 Value
3171** The value of the atom.
3172**
3173** OUTPUT:
3174**
3175** Nothing.
3176*/
3177gceSTATUS
3178gckOS_AtomSet(
3179 IN gckOS Os,
3180 IN gctPOINTER Atom,
3181 IN gctINT32 Value
3182 )
3183{
3184 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3185
3186 /* Verify the arguments. */
3187 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3188 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3189
3190 /* Set the current value of atom. */
3191 atomic_set((atomic_t *) Atom, Value);
3192
3193 /* Success. */
3194 gcmkFOOTER_NO();
3195 return gcvSTATUS_OK;
3196}
3197
3198/*******************************************************************************
3199**
3200** gckOS_AtomIncrement
3201**
3202** Atomically increment the 32-bit integer value inside an atom.
3203**
3204** INPUT:
3205**
3206** gckOS Os
3207** Pointer to a gckOS object.
3208**
3209** gctPOINTER Atom
3210** Pointer to the atom.
3211**
3212** OUTPUT:
3213**
3214** gctINT32_PTR Value
3215** Pointer to a variable that receives the original value of the atom.
3216*/
3217gceSTATUS
3218gckOS_AtomIncrement(
3219 IN gckOS Os,
3220 IN gctPOINTER Atom,
3221 OUT gctINT32_PTR Value
3222 )
3223{
3224 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3225
3226 /* Verify the arguments. */
3227 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3228 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3229
3230 /* Increment the atom. */
3231 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3232
3233 /* Success. */
3234 gcmkFOOTER_ARG("*Value=%d", *Value);
3235 return gcvSTATUS_OK;
3236}
3237
3238/*******************************************************************************
3239**
3240** gckOS_AtomDecrement
3241**
3242** Atomically decrement the 32-bit integer value inside an atom.
3243**
3244** INPUT:
3245**
3246** gckOS Os
3247** Pointer to a gckOS object.
3248**
3249** gctPOINTER Atom
3250** Pointer to the atom.
3251**
3252** OUTPUT:
3253**
3254** gctINT32_PTR Value
3255** Pointer to a variable that receives the original value of the atom.
3256*/
3257gceSTATUS
3258gckOS_AtomDecrement(
3259 IN gckOS Os,
3260 IN gctPOINTER Atom,
3261 OUT gctINT32_PTR Value
3262 )
3263{
3264 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3265
3266 /* Verify the arguments. */
3267 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3268 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3269
3270 /* Decrement the atom. */
3271 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3272
3273 /* Success. */
3274 gcmkFOOTER_ARG("*Value=%d", *Value);
3275 return gcvSTATUS_OK;
3276}
3277
3278/*******************************************************************************
3279**
3280** gckOS_Delay
3281**
3282** Delay execution of the current thread for a number of milliseconds.
3283**
3284** INPUT:
3285**
3286** gckOS Os
3287** Pointer to an gckOS object.
3288**
3289** gctUINT32 Delay
3290** Delay to sleep, specified in milliseconds.
3291**
3292** OUTPUT:
3293**
3294** Nothing.
3295*/
3296gceSTATUS
3297gckOS_Delay(
3298 IN gckOS Os,
3299 IN gctUINT32 Delay
3300 )
3301{
3302 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3303
3304 if (Delay > 0)
3305 {
3306#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3307 ktime_t delay = ktime_set((Delay / MSEC_PER_SEC), (Delay % MSEC_PER_SEC) * NSEC_PER_MSEC);
3308 __set_current_state(TASK_UNINTERRUPTIBLE);
3309 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3310#else
3311 msleep(Delay);
3312#endif
3313 }
3314
3315 /* Success. */
3316 gcmkFOOTER_NO();
3317 return gcvSTATUS_OK;
3318}
3319
3320/*******************************************************************************
3321**
3322** gckOS_GetTicks
3323**
3324** Get the number of milliseconds since the system started.
3325**
3326** INPUT:
3327**
3328** OUTPUT:
3329**
3330** gctUINT32_PTR Time
3331** Pointer to a variable to get time.
3332**
3333*/
3334gceSTATUS
3335gckOS_GetTicks(
3336 OUT gctUINT32_PTR Time
3337 )
3338{
3339 gcmkHEADER();
3340
3341 *Time = jiffies_to_msecs(jiffies);
3342
3343 gcmkFOOTER_NO();
3344 return gcvSTATUS_OK;
3345}
3346
3347/*******************************************************************************
3348**
3349** gckOS_TicksAfter
3350**
3351** Compare time values got from gckOS_GetTicks.
3352**
3353** INPUT:
3354** gctUINT32 Time1
3355** First time value to be compared.
3356**
3357** gctUINT32 Time2
3358** Second time value to be compared.
3359**
3360** OUTPUT:
3361**
3362** gctBOOL_PTR IsAfter
3363** Pointer to a variable to result.
3364**
3365*/
3366gceSTATUS
3367gckOS_TicksAfter(
3368 IN gctUINT32 Time1,
3369 IN gctUINT32 Time2,
3370 OUT gctBOOL_PTR IsAfter
3371 )
3372{
3373 gcmkHEADER();
3374
3375 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3376
3377 gcmkFOOTER_NO();
3378 return gcvSTATUS_OK;
3379}
3380
3381/*******************************************************************************
3382**
3383** gckOS_GetTime
3384**
3385** Get the number of microseconds since the system started.
3386**
3387** INPUT:
3388**
3389** OUTPUT:
3390**
3391** gctUINT64_PTR Time
3392** Pointer to a variable to get time.
3393**
3394*/
3395gceSTATUS
3396gckOS_GetTime(
3397 OUT gctUINT64_PTR Time
3398 )
3399{
3400 struct timeval tv;
3401 gcmkHEADER();
3402
3403 /* Return the time of day in microseconds. */
3404 do_gettimeofday(&tv);
3405 *Time = (tv.tv_sec * 1000000ULL) + tv.tv_usec;
3406
3407 gcmkFOOTER_NO();
3408 return gcvSTATUS_OK;
3409}
3410
3411/*******************************************************************************
3412**
3413** gckOS_MemoryBarrier
3414**
3415** Make sure the CPU has executed everything up to this point and the data got
3416** written to the specified pointer.
3417**
3418** INPUT:
3419**
3420** gckOS Os
3421** Pointer to an gckOS object.
3422**
3423** gctPOINTER Address
3424** Address of memory that needs to be barriered.
3425**
3426** OUTPUT:
3427**
3428** Nothing.
3429*/
3430gceSTATUS
3431gckOS_MemoryBarrier(
3432 IN gckOS Os,
3433 IN gctPOINTER Address
3434 )
3435{
3436 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3437
3438 /* Verify the arguments. */
3439 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3440
3441#if gcdNONPAGED_MEMORY_BUFFERABLE \
3442 && defined (CONFIG_ARM) \
3443 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3444 /* drain write buffer */
3445 dsb();
3446
3447 /* drain outer cache's write buffer? */
3448#else
3449 mb();
3450#endif
3451
3452 /* Success. */
3453 gcmkFOOTER_NO();
3454 return gcvSTATUS_OK;
3455}
3456
3457/*******************************************************************************
3458**
3459** gckOS_AllocatePagedMemory
3460**
3461** Allocate memory from the paged pool.
3462**
3463** INPUT:
3464**
3465** gckOS Os
3466** Pointer to an gckOS object.
3467**
3468** gctSIZE_T Bytes
3469** Number of bytes to allocate.
3470**
3471** OUTPUT:
3472**
3473** gctPHYS_ADDR * Physical
3474** Pointer to a variable that receives the physical address of the
3475** memory allocation.
3476*/
3477gceSTATUS
3478gckOS_AllocatePagedMemory(
3479 IN gckOS Os,
3480 IN gctSIZE_T Bytes,
3481 OUT gctPHYS_ADDR * Physical
3482 )
3483{
3484 gceSTATUS status;
3485
3486 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3487
3488 /* Verify the arguments. */
3489 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3490 gcmkVERIFY_ARGUMENT(Bytes > 0);
3491 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3492
3493 /* Allocate the memory. */
3494 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvALLOC_FLAG_NONE, Bytes, gcvNULL, Physical));
3495
3496 /* Success. */
3497 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3498 return gcvSTATUS_OK;
3499
3500OnError:
3501 /* Return the status. */
3502 gcmkFOOTER();
3503 return status;
3504}
3505
3506/*******************************************************************************
3507**
3508** gckOS_AllocatePagedMemoryEx
3509**
3510** Allocate memory from the paged pool.
3511**
3512** INPUT:
3513**
3514** gckOS Os
3515** Pointer to an gckOS object.
3516**
3517** gctUINT32 Flag
3518** Allocation attribute.
3519**
3520** gctSIZE_T Bytes
3521** Number of bytes to allocate.
3522**
3523** OUTPUT:
3524**
3525** gctUINT32 * Gid
3526** Save the global ID for the piece of allocated memory.
3527**
3528** gctPHYS_ADDR * Physical
3529** Pointer to a variable that receives the physical address of the
3530** memory allocation.
3531*/
3532gceSTATUS
3533gckOS_AllocatePagedMemoryEx(
3534 IN gckOS Os,
3535 IN gctUINT32 Flag,
3536 IN gctSIZE_T Bytes,
3537 OUT gctUINT32 * Gid,
3538 OUT gctPHYS_ADDR * Physical
3539 )
3540{
3541 gctINT numPages;
3542 PLINUX_MDL mdl = gcvNULL;
3543 gctSIZE_T bytes;
3544 gceSTATUS status = gcvSTATUS_OUT_OF_MEMORY;
3545 gckALLOCATOR allocator;
3546
3547 gcmkHEADER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
3548
3549 /* Verify the arguments. */
3550 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3551 gcmkVERIFY_ARGUMENT(Bytes > 0);
3552 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3553
3554 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3555
3556 numPages = GetPageCount(bytes, 0);
3557
3558 mdl = _CreateMdl();
3559 if (mdl == gcvNULL)
3560 {
3561 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3562 }
3563
3564 /* Walk all allocators. */
3565 list_for_each_entry(allocator, &Os->allocatorList, head)
3566 {
3567 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
3568 "%s(%d) flag = %x allocator->capability = %x",
3569 __FUNCTION__, __LINE__, Flag, allocator->capability);
3570
3571 if ((Flag & allocator->capability) != Flag)
3572 {
3573 continue;
3574 }
3575
3576 status = allocator->ops->Alloc(allocator, mdl, numPages, Flag);
3577
3578 if (gcmIS_SUCCESS(status))
3579 {
3580 mdl->allocator = allocator;
3581 break;
3582 }
3583 }
3584
3585 /* Check status. */
3586 gcmkONERROR(status);
3587
3588 mdl->dmaHandle = 0;
3589 mdl->addr = 0;
3590 mdl->numPages = numPages;
3591 mdl->pagedMem = 1;
3592 mdl->contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
3593
3594 if (Gid != gcvNULL)
3595 {
3596 *Gid = mdl->gid;
3597 }
3598
3599 MEMORY_LOCK(Os);
3600
3601 /*
3602 * Add this to a global list.
3603 * Will be used by get physical address
3604 * and mapuser pointer functions.
3605 */
3606 if (!Os->mdlHead)
3607 {
3608 /* Initialize the queue. */
3609 Os->mdlHead = Os->mdlTail = mdl;
3610 }
3611 else
3612 {
3613 /* Add to tail. */
3614 mdl->prev = Os->mdlTail;
3615 Os->mdlTail->next = mdl;
3616 Os->mdlTail = mdl;
3617 }
3618
3619 MEMORY_UNLOCK(Os);
3620
3621 /* Return physical address. */
3622 *Physical = (gctPHYS_ADDR) mdl;
3623
3624 /* Success. */
3625 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3626 return gcvSTATUS_OK;
3627
3628OnError:
3629 if (mdl != gcvNULL)
3630 {
3631 /* Free the memory. */
3632 _DestroyMdl(mdl);
3633 }
3634
3635 /* Return the status. */
3636 gcmkFOOTER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
3637 return status;
3638}
3639
3640/*******************************************************************************
3641**
3642** gckOS_FreePagedMemory
3643**
3644** Free memory allocated from the paged pool.
3645**
3646** INPUT:
3647**
3648** gckOS Os
3649** Pointer to an gckOS object.
3650**
3651** gctPHYS_ADDR Physical
3652** Physical address of the allocation.
3653**
3654** gctSIZE_T Bytes
3655** Number of bytes of the allocation.
3656**
3657** OUTPUT:
3658**
3659** Nothing.
3660*/
3661gceSTATUS
3662gckOS_FreePagedMemory(
3663 IN gckOS Os,
3664 IN gctPHYS_ADDR Physical,
3665 IN gctSIZE_T Bytes
3666 )
3667{
3668 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
3669 gckALLOCATOR allocator = (gckALLOCATOR)mdl->allocator;
3670
3671 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
3672
3673 /* Verify the arguments. */
3674 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3675 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3676 gcmkVERIFY_ARGUMENT(Bytes > 0);
3677
3678 MEMORY_LOCK(Os);
3679
3680 /* Remove the node from global list. */
3681 if (mdl == Os->mdlHead)
3682 {
3683 if ((Os->mdlHead = mdl->next) == gcvNULL)
3684 {
3685 Os->mdlTail = gcvNULL;
3686 }
3687 }
3688 else
3689 {
3690 mdl->prev->next = mdl->next;
3691
3692 if (mdl == Os->mdlTail)
3693 {
3694 Os->mdlTail = mdl->prev;
3695 }
3696 else
3697 {
3698 mdl->next->prev = mdl->prev;
3699 }
3700 }
3701
3702 MEMORY_UNLOCK(Os);
3703
3704 allocator->ops->Free(allocator, mdl);
3705
3706 /* Free the structure... */
3707 gcmkVERIFY_OK(_DestroyMdl(mdl));
3708
3709 /* Success. */
3710 gcmkFOOTER_NO();
3711 return gcvSTATUS_OK;
3712}
3713
3714/*******************************************************************************
3715**
3716** gckOS_LockPages
3717**
3718** Lock memory allocated from the paged pool.
3719**
3720** INPUT:
3721**
3722** gckOS Os
3723** Pointer to an gckOS object.
3724**
3725** gctPHYS_ADDR Physical
3726** Physical address of the allocation.
3727**
3728** gctSIZE_T Bytes
3729** Number of bytes of the allocation.
3730**
3731** gctBOOL Cacheable
3732** Cache mode of mapping.
3733**
3734** OUTPUT:
3735**
3736** gctPOINTER * Logical
3737** Pointer to a variable that receives the address of the mapped
3738** memory.
3739**
3740** gctSIZE_T * PageCount
3741** Pointer to a variable that receives the number of pages required for
3742** the page table according to the GPU page size.
3743*/
3744gceSTATUS
3745gckOS_LockPages(
3746 IN gckOS Os,
3747 IN gctPHYS_ADDR Physical,
3748 IN gctSIZE_T Bytes,
3749 IN gctBOOL Cacheable,
3750 OUT gctPOINTER * Logical,
3751 OUT gctSIZE_T * PageCount
3752 )
3753{
3754 gceSTATUS status;
3755 PLINUX_MDL mdl;
3756 PLINUX_MDL_MAP mdlMap;
3757 gckALLOCATOR allocator;
3758
3759 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
3760
3761 /* Verify the arguments. */
3762 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3763 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3764 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
3765 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
3766
3767 mdl = (PLINUX_MDL) Physical;
3768 allocator = mdl->allocator;
3769
3770 MEMORY_LOCK(Os);
3771
3772 mdlMap = FindMdlMap(mdl, _GetProcessID());
3773
3774 if (mdlMap == gcvNULL)
3775 {
3776 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
3777
3778 if (mdlMap == gcvNULL)
3779 {
3780 MEMORY_UNLOCK(Os);
3781
3782 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
3783 return gcvSTATUS_OUT_OF_MEMORY;
3784 }
3785 }
3786
3787 if (mdlMap->vmaAddr == gcvNULL)
3788 {
3789 status = allocator->ops->MapUser(allocator, mdl, mdlMap, Cacheable);
3790
3791 if (gcmIS_ERROR(status))
3792 {
3793 MEMORY_UNLOCK(Os);
3794
3795 gcmkFOOTER_ARG("*status=%d", status);
3796 return status;
3797 }
3798 }
3799
3800 mdlMap->count++;
3801
3802 /* Convert pointer to MDL. */
3803 *Logical = mdlMap->vmaAddr;
3804
3805 /* Return the page number according to the GPU page size. */
3806 gcmkASSERT((PAGE_SIZE % 4096) == 0);
3807 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
3808
3809 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
3810
3811 MEMORY_UNLOCK(Os);
3812
3813 gcmkVERIFY_OK(gckOS_CacheFlush(
3814 Os,
3815 _GetProcessID(),
3816 Physical,
3817 gcvINVALID_ADDRESS,
3818 (gctPOINTER)mdlMap->vmaAddr,
3819 mdl->numPages * PAGE_SIZE
3820 ));
3821
3822 /* Success. */
3823 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
3824 return gcvSTATUS_OK;
3825}
3826
3827/*******************************************************************************
3828**
3829** gckOS_MapPages
3830**
3831** Map paged memory into a page table.
3832**
3833** INPUT:
3834**
3835** gckOS Os
3836** Pointer to an gckOS object.
3837**
3838** gctPHYS_ADDR Physical
3839** Physical address of the allocation.
3840**
3841** gctSIZE_T PageCount
3842** Number of pages required for the physical address.
3843**
3844** gctPOINTER PageTable
3845** Pointer to the page table to fill in.
3846**
3847** OUTPUT:
3848**
3849** Nothing.
3850*/
3851gceSTATUS
3852gckOS_MapPages(
3853 IN gckOS Os,
3854 IN gctPHYS_ADDR Physical,
3855 IN gctSIZE_T PageCount,
3856 IN gctPOINTER PageTable
3857 )
3858{
3859 return gckOS_MapPagesEx(Os,
3860 gcvCORE_MAJOR,
3861 Physical,
3862 PageCount,
3863 0,
3864 PageTable);
3865}
3866
3867gceSTATUS
3868gckOS_MapPagesEx(
3869 IN gckOS Os,
3870 IN gceCORE Core,
3871 IN gctPHYS_ADDR Physical,
3872 IN gctSIZE_T PageCount,
3873 IN gctUINT32 Address,
3874 IN gctPOINTER PageTable
3875 )
3876{
3877 gceSTATUS status = gcvSTATUS_OK;
3878 PLINUX_MDL mdl;
3879 gctUINT32* table;
3880 gctUINT32 offset;
3881#if gcdNONPAGED_MEMORY_CACHEABLE
3882 gckMMU mmu;
3883 PLINUX_MDL mmuMdl;
3884 gctUINT32 bytes;
3885 gctPHYS_ADDR pageTablePhysical;
3886#endif
3887
3888#if gcdPROCESS_ADDRESS_SPACE
3889 gckKERNEL kernel = Os->device->kernels[Core];
3890 gckMMU mmu;
3891#endif
3892 gckALLOCATOR allocator;
3893
3894 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
3895 Os, Core, Physical, PageCount, PageTable);
3896
3897 /* Verify the arguments. */
3898 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3899 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3900 gcmkVERIFY_ARGUMENT(PageCount > 0);
3901 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
3902
3903 /* Convert pointer to MDL. */
3904 mdl = (PLINUX_MDL)Physical;
3905
3906 allocator = mdl->allocator;
3907
3908 gcmkTRACE_ZONE(
3909 gcvLEVEL_INFO, gcvZONE_OS,
3910 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
3911 __FUNCTION__, __LINE__,
3912 (gctUINT32)(gctUINTPTR_T)Physical,
3913 (gctUINT32)(gctUINTPTR_T)PageCount,
3914 mdl->pagedMem
3915 );
3916
3917#if gcdPROCESS_ADDRESS_SPACE
3918 gcmkONERROR(gckKERNEL_GetProcessMMU(kernel, &mmu));
3919#endif
3920
3921 table = (gctUINT32 *)PageTable;
3922#if gcdNONPAGED_MEMORY_CACHEABLE
3923 mmu = Os->device->kernels[Core]->mmu;
3924 bytes = PageCount * sizeof(*table);
3925 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
3926#endif
3927
3928 /* Get all the physical addresses and store them in the page table. */
3929
3930 offset = 0;
3931 PageCount = PageCount / (PAGE_SIZE / 4096);
3932
3933 /* Try to get the user pages so DMA can happen. */
3934 while (PageCount-- > 0)
3935 {
3936 gctUINT i;
3937 gctPHYS_ADDR_T phys = ~0U;
3938
3939 if (mdl->pagedMem && !mdl->contiguous)
3940 {
3941 allocator->ops->Physical(allocator, mdl, offset, &phys);
3942 }
3943 else
3944 {
3945 if (!mdl->pagedMem)
3946 {
3947 gcmkTRACE_ZONE(
3948 gcvLEVEL_INFO, gcvZONE_OS,
3949 "%s(%d): we should not get this call for Non Paged Memory!",
3950 __FUNCTION__, __LINE__
3951 );
3952 }
3953
3954 phys = page_to_phys(nth_page(mdl->u.contiguousPages, offset));
3955 }
3956
3957 gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, phys, &phys));
3958
3959#ifdef CONFIG_IOMMU_SUPPORT
3960 if (Os->iommu)
3961 {
3962 gcmkTRACE_ZONE(
3963 gcvLEVEL_INFO, gcvZONE_OS,
3964 "%s(%d): Setup mapping in IOMMU %x => %x",
3965 __FUNCTION__, __LINE__,
3966 Address + (offset * PAGE_SIZE), phys
3967 );
3968
3969 /* When use IOMMU, GPU use system PAGE_SIZE. */
3970 gcmkONERROR(gckIOMMU_Map(
3971 Os->iommu, Address + (offset * PAGE_SIZE), phys, PAGE_SIZE));
3972 }
3973 else
3974#endif
3975 {
3976
3977 {
3978 for (i = 0; i < (PAGE_SIZE / 4096); i++)
3979 {
3980#if gcdPROCESS_ADDRESS_SPACE
3981 gctUINT32_PTR pageTableEntry;
3982 gckMMU_GetPageEntry(mmu, Address + (offset * 4096), &pageTableEntry);
3983 gcmkONERROR(
3984 gckMMU_SetPage(mmu,
3985 phys + (i * 4096),
3986 pageTableEntry));
3987#else
3988 gcmkONERROR(
3989 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
3990 phys + (i * 4096),
3991 table++));
3992#endif
3993 }
3994 }
3995 }
3996
3997 offset += 1;
3998 }
3999
4000#if gcdNONPAGED_MEMORY_CACHEABLE
4001 /* Get physical address of pageTable */
4002 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4003 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4004
4005 /* Flush the mmu page table cache. */
4006 gcmkONERROR(gckOS_CacheClean(
4007 Os,
4008 _GetProcessID(),
4009 gcvNULL,
4010 pageTablePhysical,
4011 PageTable,
4012 bytes
4013 ));
4014#endif
4015
4016OnError:
4017
4018 /* Return the status. */
4019 gcmkFOOTER();
4020 return status;
4021}
4022
4023gceSTATUS
4024gckOS_UnmapPages(
4025 IN gckOS Os,
4026 IN gctSIZE_T PageCount,
4027 IN gctUINT32 Address
4028 )
4029{
4030#ifdef CONFIG_IOMMU_SUPPORT
4031 if (Os->iommu)
4032 {
4033 gcmkVERIFY_OK(gckIOMMU_Unmap(
4034 Os->iommu, Address, PageCount * PAGE_SIZE));
4035 }
4036#endif
4037
4038 return gcvSTATUS_OK;
4039}
4040
4041/*******************************************************************************
4042**
4043** gckOS_UnlockPages
4044**
4045** Unlock memory allocated from the paged pool.
4046**
4047** INPUT:
4048**
4049** gckOS Os
4050** Pointer to an gckOS object.
4051**
4052** gctPHYS_ADDR Physical
4053** Physical address of the allocation.
4054**
4055** gctSIZE_T Bytes
4056** Number of bytes of the allocation.
4057**
4058** gctPOINTER Logical
4059** Address of the mapped memory.
4060**
4061** OUTPUT:
4062**
4063** Nothing.
4064*/
4065gceSTATUS
4066gckOS_UnlockPages(
4067 IN gckOS Os,
4068 IN gctPHYS_ADDR Physical,
4069 IN gctSIZE_T Bytes,
4070 IN gctPOINTER Logical
4071 )
4072{
4073 PLINUX_MDL_MAP mdlMap;
4074 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4075 gckALLOCATOR allocator = mdl->allocator;
4076
4077 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4078 Os, Physical, Bytes, Logical);
4079
4080 /* Verify the arguments. */
4081 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4082 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4083 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4084
4085 MEMORY_LOCK(Os);
4086
4087 mdlMap = mdl->maps;
4088
4089 while (mdlMap != gcvNULL)
4090 {
4091 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4092 {
4093 if (--mdlMap->count == 0)
4094 {
4095 allocator->ops->UnmapUser(
4096 allocator,
4097 mdlMap->vmaAddr,
4098 mdl->numPages * PAGE_SIZE);
4099
4100 mdlMap->vmaAddr = gcvNULL;
4101 }
4102 }
4103
4104 mdlMap = mdlMap->next;
4105 }
4106
4107 MEMORY_UNLOCK(Os);
4108
4109 /* Success. */
4110 gcmkFOOTER_NO();
4111 return gcvSTATUS_OK;
4112}
4113
4114
4115/*******************************************************************************
4116**
4117** gckOS_AllocateContiguous
4118**
4119** Allocate memory from the contiguous pool.
4120**
4121** INPUT:
4122**
4123** gckOS Os
4124** Pointer to an gckOS object.
4125**
4126** gctBOOL InUserSpace
4127** gcvTRUE if the pages need to be mapped into user space.
4128**
4129** gctSIZE_T * Bytes
4130** Pointer to the number of bytes to allocate.
4131**
4132** OUTPUT:
4133**
4134** gctSIZE_T * Bytes
4135** Pointer to a variable that receives the number of bytes allocated.
4136**
4137** gctPHYS_ADDR * Physical
4138** Pointer to a variable that receives the physical address of the
4139** memory allocation.
4140**
4141** gctPOINTER * Logical
4142** Pointer to a variable that receives the logical address of the
4143** memory allocation.
4144*/
4145gceSTATUS
4146gckOS_AllocateContiguous(
4147 IN gckOS Os,
4148 IN gctBOOL InUserSpace,
4149 IN OUT gctSIZE_T * Bytes,
4150 OUT gctPHYS_ADDR * Physical,
4151 OUT gctPOINTER * Logical
4152 )
4153{
4154 gceSTATUS status;
4155
4156 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4157 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4158
4159 /* Verify the arguments. */
4160 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4161 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4162 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4163 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4164 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4165
4166 /* Same as non-paged memory for now. */
4167 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4168 InUserSpace,
4169 Bytes,
4170 Physical,
4171 Logical));
4172
4173 /* Success. */
4174 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4175 *Bytes, *Physical, *Logical);
4176 return gcvSTATUS_OK;
4177
4178OnError:
4179 /* Return the status. */
4180 gcmkFOOTER();
4181 return status;
4182}
4183
4184/*******************************************************************************
4185**
4186** gckOS_FreeContiguous
4187**
4188** Free memory allocated from the contiguous pool.
4189**
4190** INPUT:
4191**
4192** gckOS Os
4193** Pointer to an gckOS object.
4194**
4195** gctPHYS_ADDR Physical
4196** Physical address of the allocation.
4197**
4198** gctPOINTER Logical
4199** Logicval address of the allocation.
4200**
4201** gctSIZE_T Bytes
4202** Number of bytes of the allocation.
4203**
4204** OUTPUT:
4205**
4206** Nothing.
4207*/
4208gceSTATUS
4209gckOS_FreeContiguous(
4210 IN gckOS Os,
4211 IN gctPHYS_ADDR Physical,
4212 IN gctPOINTER Logical,
4213 IN gctSIZE_T Bytes
4214 )
4215{
4216 gceSTATUS status;
4217
4218 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4219 Os, Physical, Logical, Bytes);
4220
4221 /* Verify the arguments. */
4222 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4223 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4224 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4225 gcmkVERIFY_ARGUMENT(Bytes > 0);
4226
4227 /* Same of non-paged memory for now. */
4228 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4229
4230 /* Success. */
4231 gcmkFOOTER_NO();
4232 return gcvSTATUS_OK;
4233
4234OnError:
4235 /* Return the status. */
4236 gcmkFOOTER();
4237 return status;
4238}
4239
4240
4241/*******************************************************************************
4242**
4243** gckOS_MapUserPointer
4244**
4245** Map a pointer from the user process into the kernel address space.
4246**
4247** INPUT:
4248**
4249** gckOS Os
4250** Pointer to an gckOS object.
4251**
4252** gctPOINTER Pointer
4253** Pointer in user process space that needs to be mapped.
4254**
4255** gctSIZE_T Size
4256** Number of bytes that need to be mapped.
4257**
4258** OUTPUT:
4259**
4260** gctPOINTER * KernelPointer
4261** Pointer to a variable receiving the mapped pointer in kernel address
4262** space.
4263*/
4264gceSTATUS
4265gckOS_MapUserPointer(
4266 IN gckOS Os,
4267 IN gctPOINTER Pointer,
4268 IN gctSIZE_T Size,
4269 OUT gctPOINTER * KernelPointer
4270 )
4271{
4272 gctPOINTER buf = gcvNULL;
4273 gctUINT32 len;
4274
4275 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
4276
4277 /* Verify the arguments. */
4278 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4279 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4280 gcmkVERIFY_ARGUMENT(Size > 0);
4281 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4282
4283 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
4284 if (buf == gcvNULL)
4285 {
4286 gcmkTRACE(
4287 gcvLEVEL_ERROR,
4288 "%s(%d): Failed to allocate memory.",
4289 __FUNCTION__, __LINE__
4290 );
4291
4292 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4293 return gcvSTATUS_OUT_OF_MEMORY;
4294 }
4295
4296 len = copy_from_user(buf, Pointer, Size);
4297 if (len != 0)
4298 {
4299 gcmkTRACE(
4300 gcvLEVEL_ERROR,
4301 "%s(%d): Failed to copy data from user.",
4302 __FUNCTION__, __LINE__
4303 );
4304
4305 if (buf != gcvNULL)
4306 {
4307 kfree(buf);
4308 }
4309
4310 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
4311 return gcvSTATUS_GENERIC_IO;
4312 }
4313
4314 *KernelPointer = buf;
4315
4316 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4317 return gcvSTATUS_OK;
4318}
4319
4320/*******************************************************************************
4321**
4322** gckOS_UnmapUserPointer
4323**
4324** Unmap a user process pointer from the kernel address space.
4325**
4326** INPUT:
4327**
4328** gckOS Os
4329** Pointer to an gckOS object.
4330**
4331** gctPOINTER Pointer
4332** Pointer in user process space that needs to be unmapped.
4333**
4334** gctSIZE_T Size
4335** Number of bytes that need to be unmapped.
4336**
4337** gctPOINTER KernelPointer
4338** Pointer in kernel address space that needs to be unmapped.
4339**
4340** OUTPUT:
4341**
4342** Nothing.
4343*/
4344gceSTATUS
4345gckOS_UnmapUserPointer(
4346 IN gckOS Os,
4347 IN gctPOINTER Pointer,
4348 IN gctSIZE_T Size,
4349 IN gctPOINTER KernelPointer
4350 )
4351{
4352 gctUINT32 len;
4353
4354 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
4355 Os, Pointer, Size, KernelPointer);
4356
4357
4358 /* Verify the arguments. */
4359 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4360 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4361 gcmkVERIFY_ARGUMENT(Size > 0);
4362 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4363
4364 len = copy_to_user(Pointer, KernelPointer, Size);
4365
4366 kfree(KernelPointer);
4367
4368 if (len != 0)
4369 {
4370 gcmkTRACE(
4371 gcvLEVEL_ERROR,
4372 "%s(%d): Failed to copy data to user.",
4373 __FUNCTION__, __LINE__
4374 );
4375
4376 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
4377 return gcvSTATUS_GENERIC_IO;
4378 }
4379
4380 gcmkFOOTER_NO();
4381 return gcvSTATUS_OK;
4382}
4383
4384/*******************************************************************************
4385**
4386** gckOS_QueryNeedCopy
4387**
4388** Query whether the memory can be accessed or mapped directly or it has to be
4389** copied.
4390**
4391** INPUT:
4392**
4393** gckOS Os
4394** Pointer to an gckOS object.
4395**
4396** gctUINT32 ProcessID
4397** Process ID of the current process.
4398**
4399** OUTPUT:
4400**
4401** gctBOOL_PTR NeedCopy
4402** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
4403** gcvFALSE if the memory can be accessed or mapped dircetly.
4404*/
4405gceSTATUS
4406gckOS_QueryNeedCopy(
4407 IN gckOS Os,
4408 IN gctUINT32 ProcessID,
4409 OUT gctBOOL_PTR NeedCopy
4410 )
4411{
4412 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
4413
4414 /* Verify the arguments. */
4415 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4416 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
4417
4418 /* We need to copy data. */
4419 *NeedCopy = gcvTRUE;
4420
4421 /* Success. */
4422 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
4423 return gcvSTATUS_OK;
4424}
4425
4426/*******************************************************************************
4427**
4428** gckOS_CopyFromUserData
4429**
4430** Copy data from user to kernel memory.
4431**
4432** INPUT:
4433**
4434** gckOS Os
4435** Pointer to an gckOS object.
4436**
4437** gctPOINTER KernelPointer
4438** Pointer to kernel memory.
4439**
4440** gctPOINTER Pointer
4441** Pointer to user memory.
4442**
4443** gctSIZE_T Size
4444** Number of bytes to copy.
4445**
4446** OUTPUT:
4447**
4448** Nothing.
4449*/
4450gceSTATUS
4451gckOS_CopyFromUserData(
4452 IN gckOS Os,
4453 IN gctPOINTER KernelPointer,
4454 IN gctPOINTER Pointer,
4455 IN gctSIZE_T Size
4456 )
4457{
4458 gceSTATUS status;
4459
4460 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
4461 Os, KernelPointer, Pointer, Size);
4462
4463 /* Verify the arguments. */
4464 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4465 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4466 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4467 gcmkVERIFY_ARGUMENT(Size > 0);
4468
4469 /* Copy data from user. */
4470 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
4471 {
4472 /* Could not copy all the bytes. */
4473 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4474 }
4475
4476 /* Success. */
4477 gcmkFOOTER_NO();
4478 return gcvSTATUS_OK;
4479
4480OnError:
4481 /* Return the status. */
4482 gcmkFOOTER();
4483 return status;
4484}
4485
4486/*******************************************************************************
4487**
4488** gckOS_CopyToUserData
4489**
4490** Copy data from kernel to user memory.
4491**
4492** INPUT:
4493**
4494** gckOS Os
4495** Pointer to an gckOS object.
4496**
4497** gctPOINTER KernelPointer
4498** Pointer to kernel memory.
4499**
4500** gctPOINTER Pointer
4501** Pointer to user memory.
4502**
4503** gctSIZE_T Size
4504** Number of bytes to copy.
4505**
4506** OUTPUT:
4507**
4508** Nothing.
4509*/
4510gceSTATUS
4511gckOS_CopyToUserData(
4512 IN gckOS Os,
4513 IN gctPOINTER KernelPointer,
4514 IN gctPOINTER Pointer,
4515 IN gctSIZE_T Size
4516 )
4517{
4518 gceSTATUS status;
4519
4520 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
4521 Os, KernelPointer, Pointer, Size);
4522
4523 /* Verify the arguments. */
4524 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4525 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4526 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4527 gcmkVERIFY_ARGUMENT(Size > 0);
4528
4529 /* Copy data to user. */
4530 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
4531 {
4532 /* Could not copy all the bytes. */
4533 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4534 }
4535
4536 /* Success. */
4537 gcmkFOOTER_NO();
4538 return gcvSTATUS_OK;
4539
4540OnError:
4541 /* Return the status. */
4542 gcmkFOOTER();
4543 return status;
4544}
4545
4546/*******************************************************************************
4547**
4548** gckOS_WriteMemory
4549**
4550** Write data to a memory.
4551**
4552** INPUT:
4553**
4554** gckOS Os
4555** Pointer to an gckOS object.
4556**
4557** gctPOINTER Address
4558** Address of the memory to write to.
4559**
4560** gctUINT32 Data
4561** Data for register.
4562**
4563** OUTPUT:
4564**
4565** Nothing.
4566*/
4567gceSTATUS
4568gckOS_WriteMemory(
4569 IN gckOS Os,
4570 IN gctPOINTER Address,
4571 IN gctUINT32 Data
4572 )
4573{
4574 gceSTATUS status;
4575 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
4576
4577 /* Verify the arguments. */
4578 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
4579
4580 /* Write memory. */
4581 if (access_ok(VERIFY_WRITE, Address, 4))
4582 {
4583 /* User address. */
4584 if(put_user(Data, (gctUINT32*)Address))
4585 {
4586 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
4587 }
4588 }
4589 else
4590 {
4591 /* Kernel address. */
4592 *(gctUINT32 *)Address = Data;
4593 }
4594
4595 /* Success. */
4596 gcmkFOOTER_NO();
4597 return gcvSTATUS_OK;
4598
4599OnError:
4600 gcmkFOOTER();
4601 return status;
4602}
4603
4604/*******************************************************************************
4605**
4606** gckOS_MapUserMemory
4607**
4608** Lock down a user buffer and return an DMA'able address to be used by the
4609** hardware to access it.
4610**
4611** INPUT:
4612**
4613** gctPOINTER Memory
4614** Pointer to memory to lock down.
4615**
4616** gctSIZE_T Size
4617** Size in bytes of the memory to lock down.
4618**
4619** OUTPUT:
4620**
4621** gctPOINTER * Info
4622** Pointer to variable receiving the information record required by
4623** gckOS_UnmapUserMemory.
4624**
4625** gctUINT32_PTR Address
4626** Pointer to a variable that will receive the address DMA'able by the
4627** hardware.
4628*/
4629gceSTATUS
4630gckOS_MapUserMemory(
4631 IN gckOS Os,
4632 IN gceCORE Core,
4633 IN gctPOINTER Memory,
4634 IN gctUINT32 Physical,
4635 IN gctSIZE_T Size,
4636 OUT gctPOINTER * Info,
4637 OUT gctUINT32_PTR Address
4638 )
4639{
4640 gceSTATUS status;
4641
4642 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
4643
4644#if gcdSECURE_USER
4645 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
4646
4647 gcmkFOOTER_NO();
4648 return gcvSTATUS_OK;
4649
4650OnError:
4651 gcmkFOOTER();
4652 return status;
4653#else
4654{
4655 gctSIZE_T pageCount, i, j;
4656 gctUINT32_PTR pageTable;
4657 gctUINT32 address = 0, physical = ~0U;
4658 gctUINTPTR_T start, end, memory;
4659 gctUINT32 offset;
4660 gctINT result = 0;
4661#if gcdPROCESS_ADDRESS_SPACE
4662 gckMMU mmu;
4663#endif
4664
4665 gcsPageInfo_PTR info = gcvNULL;
4666 struct page **pages = gcvNULL;
4667
4668 /* Verify the arguments. */
4669 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4670 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
4671 gcmkVERIFY_ARGUMENT(Size > 0);
4672 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
4673 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
4674
4675 do
4676 {
4677 gctSIZE_T extraPage;
4678
4679 memory = (gctUINTPTR_T) Memory;
4680
4681 /* Get the number of required pages. */
4682 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
4683 start = memory >> PAGE_SHIFT;
4684 pageCount = end - start;
4685
4686 /* Allocate extra page to avoid cache overflow */
4687 extraPage = 2;
4688
4689
4690 gcmkTRACE_ZONE(
4691 gcvLEVEL_INFO, gcvZONE_OS,
4692 "%s(%d): pageCount: %d.",
4693 __FUNCTION__, __LINE__,
4694 pageCount
4695 );
4696
4697 /* Overflow. */
4698 if ((memory + Size) < memory)
4699 {
4700 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
4701 return gcvSTATUS_INVALID_ARGUMENT;
4702 }
4703
4704 MEMORY_MAP_LOCK(Os);
4705
4706 /* Allocate the Info struct. */
4707 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
4708
4709 if (info == gcvNULL)
4710 {
4711 status = gcvSTATUS_OUT_OF_MEMORY;
4712 break;
4713 }
4714
4715 info->extraPage = 0;
4716
4717 /* Allocate the array of page addresses. */
4718 pages = (struct page **)kmalloc((pageCount + extraPage) * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
4719
4720 if (pages == gcvNULL)
4721 {
4722 status = gcvSTATUS_OUT_OF_MEMORY;
4723 break;
4724 }
4725
4726 if (Physical != ~0U)
4727 {
4728 for (i = 0; i < pageCount; i++)
4729 {
4730 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
4731
4732 if (pfn_valid(page_to_pfn(pages[i])))
4733 {
4734 get_page(pages[i]);
4735 }
4736 }
4737 }
4738 else
4739 {
4740 /* Get the user pages. */
4741 down_read(&current->mm->mmap_sem);
4742
4743 result = get_user_pages(current,
4744 current->mm,
4745 memory & PAGE_MASK,
4746 pageCount,
4747 1,
4748 0,
4749 pages,
4750 gcvNULL
4751 );
4752
4753 up_read(&current->mm->mmap_sem);
4754
4755 if (result <=0 || result < pageCount)
4756 {
4757 struct vm_area_struct *vma;
4758
4759 /* Release the pages if any. */
4760 gckOS_DebugTrace(gcvLEVEL_INFO,
4761 "get_user_pages failed (%d/%d pages), trying to acquire from CPU page table\n",
4762 result, pageCount);
4763 if (result > 0)
4764 {
4765 for (i = 0; i < result; i++)
4766 {
4767 if (pages[i] == gcvNULL)
4768 {
4769 break;
4770 }
4771
4772 page_cache_release(pages[i]);
4773 pages[i] = gcvNULL;
4774 }
4775
4776 result = 0;
4777 }
4778
4779 /*
4780 * get_user_pages didn't work, look for the pages in the
4781 * appropriate memory region of the process. Region might
4782 * correspond to memory mapped I/O.
4783 */
4784 vma = find_vma(current->mm, memory);
4785
4786 if (vma &&
4787 ((vma->vm_flags & VM_PFNMAP) || (vma->vm_flags & VM_IO)))
4788 {
4789 pte_t * pte;
4790 spinlock_t * ptl;
4791 gctUINTPTR_T logical = memory;
4792
4793 /*
4794 * `find_vma` finds memory region with an end point past the
4795 * given address, make sure that the address is within the
4796 * returned vma region.
4797 */
4798 if (logical < vma->vm_start)
4799 {
4800 gckOS_DebugTrace(gcvLEVEL_ERROR,
4801 "address: 0x%08x is outside the region returned by find_vma (start: 0x%08x\n",
4802 logical, vma->vm_start);
4803 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4804 }
4805 /* check for end address */
4806 if (logical + Size > vma->vm_end)
4807 {
4808 gckOS_DebugTrace(gcvLEVEL_ERROR,
4809 "end address 0x%08x is outside the region returned by find_vma (end: 0x%08x\n",
4810 logical + Size, vma->vm_end);
4811 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4812 }
4813
4814 for (i = 0; i < pageCount; i++)
4815 {
4816 pgd_t * pgd = pgd_offset(current->mm, logical);
4817 pud_t * pud = pud_offset(pgd, logical);
4818
4819 if (pud)
4820 {
4821 pmd_t * pmd = pmd_offset(pud, logical);
4822 pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
4823 if (!pte)
4824 {
4825 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4826 }
4827 }
4828 else
4829 {
4830 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4831 }
4832
4833 pages[i] = pte_page(*pte);
4834 /*
4835 * inc refcount for the page, refcount is decremented by
4836 * the kernel when the vma is unmapped.
4837 */
4838 get_page(pages[i]);
4839 pte_unmap_unlock(pte, ptl);
4840
4841 /*
4842 * TODO: pages[i] is NULL for Tiler memory. Need to
4843 * handle them.
4844 */
4845 if (pages[i] == gcvNULL)
4846 {
4847 /* FIXME */
4848 gckOS_DebugTrace(gcvLEVEL_ERROR,
4849 "page table returned NULL page, could be TILER memory which is currently not handled\n");
4850 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
4851 }
4852
4853 /* Advance to next. */
4854 logical += PAGE_SIZE;
4855 }
4856 }
4857 else
4858 {
4859 gckOS_DebugTrace(gcvLEVEL_ERROR,
4860 "find_vma returned NULL or uidentified region\n");
4861 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4862 }
4863
4864 /* Check if this memory is contiguous for old mmu. */
4865 if (Os->device->kernels[Core]->hardware->mmuVersion == 0)
4866 {
4867 for (i = 1; i < pageCount; i++)
4868 {
4869 if (pages[i] != nth_page(pages[0], i))
4870 {
4871 /* Non-contiguous. */
4872 break;
4873 }
4874 }
4875
4876 if (i == pageCount)
4877 {
4878 /* Contiguous memory. */
4879 physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK);
4880
4881 if (!((physical - Os->device->baseAddress) & 0x80000000))
4882 {
4883 gctPHYS_ADDR_T gpuPhysical;
4884 kfree(pages);
4885 pages = gcvNULL;
4886
4887 info->pages = gcvNULL;
4888 info->pageTable = gcvNULL;
4889
4890 MEMORY_MAP_UNLOCK(Os);
4891
4892 *Address = physical - Os->device->baseAddress;
4893 *Info = info;
4894
4895 gcmkVERIFY_OK(
4896 gckOS_CPUPhysicalToGPUPhysical(Os, *Address, &gpuPhysical));
4897
4898 gcmkSAFECASTPHYSADDRT(*Address, gpuPhysical);
4899
4900 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
4901 *Info, *Address);
4902
4903 return gcvSTATUS_OK;
4904 }
4905 }
4906 }
4907
4908 /* Reference pages. */
4909 for (i = 0; i < pageCount; i++)
4910 {
4911 if (pfn_valid(page_to_pfn(pages[i])))
4912 {
4913 get_page(pages[i]);
4914 }
4915 }
4916 }
4917 }
4918
4919 for (i = 0; i < pageCount; i++)
4920 {
4921#ifdef CONFIG_ARM
4922 gctUINT32 data;
4923 get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
4924#endif
4925
4926 /* Flush(clean) the data cache. */
4927 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
4928 page_to_phys(pages[i]),
4929 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
4930 PAGE_SIZE));
4931 }
4932
4933#if gcdPROCESS_ADDRESS_SPACE
4934 gcmkONERROR(gckKERNEL_GetProcessMMU(Os->device->kernels[Core], &mmu));
4935#endif
4936
4937 if (extraPage)
4938 {
4939 for (i = 0; i < extraPage; i++)
4940 {
4941 pages[pageCount++] = Os->paddingPage;
4942 }
4943 info->extraPage = extraPage;
4944 }
4945
4946 {
4947#if gcdPROCESS_ADDRESS_SPACE
4948 /* Allocate pages inside the page table. */
4949 gcmkERR_BREAK(gckMMU_AllocatePages(mmu,
4950 pageCount * (PAGE_SIZE/4096),
4951 (gctPOINTER *) &pageTable,
4952 &address));
4953#else
4954 /* Allocate pages inside the page table. */
4955 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
4956 pageCount * (PAGE_SIZE/4096),
4957 (gctPOINTER *) &pageTable,
4958 &address));
4959#endif
4960 }
4961
4962 /* Fill the page table. */
4963 for (i = 0; i < pageCount; i++)
4964 {
4965 gctPHYS_ADDR_T phys;
4966 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
4967
4968#if gcdPROCESS_ADDRESS_SPACE
4969 gckMMU_GetPageEntry(mmu, address + i * 4096, &tab);
4970#endif
4971 phys = page_to_phys(pages[i]);
4972
4973#ifdef CONFIG_IOMMU_SUPPORT
4974 if (Os->iommu)
4975 {
4976 gcmkTRACE_ZONE(
4977 gcvLEVEL_INFO, gcvZONE_OS,
4978 "%s(%d): Setup mapping in IOMMU %x => %x",
4979 __FUNCTION__, __LINE__,
4980 Address + (i * PAGE_SIZE), phys
4981 );
4982
4983 gcmkONERROR(gckIOMMU_Map(
4984 Os->iommu, address + i * PAGE_SIZE, phys, PAGE_SIZE));
4985 }
4986 else
4987#endif
4988 {
4989
4990 {
4991 /* Get the physical address from page struct. */
4992 gcmkONERROR(
4993 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4994 phys,
4995 tab));
4996 }
4997
4998 for (j = 1; j < (PAGE_SIZE/4096); j++)
4999 {
5000 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5001 }
5002 }
5003
5004#if !gcdPROCESS_ADDRESS_SPACE
5005 gcmkTRACE_ZONE(
5006 gcvLEVEL_INFO, gcvZONE_OS,
5007 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5008 __FUNCTION__, __LINE__,
5009 i, phys, pageTable[i]);
5010#endif
5011 }
5012
5013 {
5014#if gcdPROCESS_ADDRESS_SPACE
5015 info->mmu = mmu;
5016 gcmkONERROR(gckMMU_Flush(mmu));
5017#else
5018 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu, gcvSURF_TYPE_UNKNOWN));
5019#endif
5020 }
5021 info->address = address;
5022
5023 /* Save pointer to page table. */
5024 info->pageTable = pageTable;
5025 info->pages = pages;
5026
5027 *Info = (gctPOINTER) info;
5028
5029 gcmkTRACE_ZONE(
5030 gcvLEVEL_INFO, gcvZONE_OS,
5031 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5032 __FUNCTION__, __LINE__,
5033 info->pages,
5034 info->pageTable,
5035 info
5036 );
5037
5038 offset = (Physical != ~0U)
5039 ? (Physical & ~PAGE_MASK)
5040 : (memory & ~PAGE_MASK);
5041
5042 /* Return address. */
5043 *Address = address + offset;
5044
5045 gcmkTRACE_ZONE(
5046 gcvLEVEL_INFO, gcvZONE_OS,
5047 "%s(%d): Address: 0x%X.",
5048 __FUNCTION__, __LINE__,
5049 *Address
5050 );
5051
5052 /* Success. */
5053 status = gcvSTATUS_OK;
5054 }
5055 while (gcvFALSE);
5056
5057OnError:
5058
5059 if (gcmIS_ERROR(status))
5060 {
5061 gcmkTRACE(
5062 gcvLEVEL_ERROR,
5063 "%s(%d): error occured: %d.",
5064 __FUNCTION__, __LINE__,
5065 status
5066 );
5067
5068 /* Release page array. */
5069 if (result > 0 && pages != gcvNULL)
5070 {
5071 gcmkTRACE(
5072 gcvLEVEL_ERROR,
5073 "%s(%d): error: page table is freed.",
5074 __FUNCTION__, __LINE__
5075 );
5076
5077 for (i = 0; i < result; i++)
5078 {
5079 if (pages[i] == gcvNULL)
5080 {
5081 break;
5082 }
5083 page_cache_release(pages[i]);
5084 }
5085 }
5086
5087 if (info!= gcvNULL && pages != gcvNULL)
5088 {
5089 gcmkTRACE(
5090 gcvLEVEL_ERROR,
5091 "%s(%d): error: pages is freed.",
5092 __FUNCTION__, __LINE__
5093 );
5094
5095 /* Free the page table. */
5096 kfree(pages);
5097 info->pages = gcvNULL;
5098 }
5099
5100 /* Release page info struct. */
5101 if (info != gcvNULL)
5102 {
5103 gcmkTRACE(
5104 gcvLEVEL_ERROR,
5105 "%s(%d): error: info is freed.",
5106 __FUNCTION__, __LINE__
5107 );
5108
5109 /* Free the page info struct. */
5110 kfree(info);
5111 *Info = gcvNULL;
5112 }
5113 }
5114
5115 MEMORY_MAP_UNLOCK(Os);
5116
5117 /* Return the status. */
5118 if (gcmIS_SUCCESS(status))
5119 {
5120 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5121 }
5122 else
5123 {
5124 gcmkFOOTER();
5125 }
5126
5127 return status;
5128}
5129#endif
5130}
5131
5132/*******************************************************************************
5133**
5134** gckOS_UnmapUserMemory
5135**
5136** Unlock a user buffer and that was previously locked down by
5137** gckOS_MapUserMemory.
5138**
5139** INPUT:
5140**
5141** gctPOINTER Memory
5142** Pointer to memory to unlock.
5143**
5144** gctSIZE_T Size
5145** Size in bytes of the memory to unlock.
5146**
5147** gctPOINTER Info
5148** Information record returned by gckOS_MapUserMemory.
5149**
5150** gctUINT32_PTR Address
5151** The address returned by gckOS_MapUserMemory.
5152**
5153** OUTPUT:
5154**
5155** Nothing.
5156*/
5157gceSTATUS
5158gckOS_UnmapUserMemory(
5159 IN gckOS Os,
5160 IN gceCORE Core,
5161 IN gctPOINTER Memory,
5162 IN gctSIZE_T Size,
5163 IN gctPOINTER Info,
5164 IN gctUINT32 Address
5165 )
5166{
5167 gceSTATUS status;
5168
5169 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5170 Os, Core, Memory, Size, Info, Address);
5171
5172#if gcdSECURE_USER
5173 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5174
5175 gcmkFOOTER_NO();
5176 return gcvSTATUS_OK;
5177
5178OnError:
5179 gcmkFOOTER();
5180 return status;
5181#else
5182{
5183 gctUINTPTR_T memory, start, end;
5184 gcsPageInfo_PTR info;
5185 gctSIZE_T pageCount, i;
5186 struct page **pages;
5187
5188 /* Verify the arguments. */
5189 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5190 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5191 gcmkVERIFY_ARGUMENT(Size > 0);
5192 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5193
5194 do
5195 {
5196 info = (gcsPageInfo_PTR) Info;
5197
5198 pages = info->pages;
5199
5200 gcmkTRACE_ZONE(
5201 gcvLEVEL_INFO, gcvZONE_OS,
5202 "%s(%d): info=0x%X, pages=0x%X.",
5203 __FUNCTION__, __LINE__,
5204 info, pages
5205 );
5206
5207 /* Invalid page array. */
5208 if (pages == gcvNULL && info->pageTable == gcvNULL)
5209 {
5210 kfree(info);
5211
5212 gcmkFOOTER_NO();
5213 return gcvSTATUS_OK;
5214 }
5215
5216 memory = (gctUINTPTR_T)Memory;
5217 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5218 start = memory >> PAGE_SHIFT;
5219 pageCount = end - start;
5220
5221 /* Overflow. */
5222 if ((memory + Size) < memory)
5223 {
5224 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5225 return gcvSTATUS_INVALID_ARGUMENT;
5226 }
5227
5228 gcmkTRACE_ZONE(
5229 gcvLEVEL_INFO, gcvZONE_OS,
5230 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5231 __FUNCTION__, __LINE__,
5232 memory, pageCount, info->pageTable
5233 );
5234
5235 MEMORY_MAP_LOCK(Os);
5236
5237 gcmkASSERT(info->pageTable != gcvNULL);
5238
5239 if (info->extraPage)
5240 {
5241 pageCount += info->extraPage;
5242 }
5243
5244 {
5245 /* Free the pages from the MMU. */
5246#if gcdPROCESS_ADDRESS_SPACE
5247 gcmkERR_BREAK(gckMMU_FreePagesEx(info->mmu,
5248 info->address,
5249 pageCount * (PAGE_SIZE/4096)
5250 ));
5251
5252#else
5253 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5254 info->pageTable,
5255 pageCount * (PAGE_SIZE/4096)
5256 ));
5257#endif
5258
5259 gcmkERR_BREAK(gckOS_UnmapPages(
5260 Os,
5261 pageCount * (PAGE_SIZE/4096),
5262 info->address
5263 ));
5264 }
5265
5266 if (info->extraPage)
5267 {
5268 pageCount -= info->extraPage;
5269 info->extraPage = 0;
5270 }
5271
5272 /* Release the page cache. */
5273 if (pages)
5274 {
5275 for (i = 0; i < pageCount; i++)
5276 {
5277 gcmkTRACE_ZONE(
5278 gcvLEVEL_INFO, gcvZONE_OS,
5279 "%s(%d): pages[%d]: 0x%X.",
5280 __FUNCTION__, __LINE__,
5281 i, pages[i]
5282 );
5283
5284 if (!PageReserved(pages[i]))
5285 {
5286 SetPageDirty(pages[i]);
5287 }
5288
5289 if (pfn_valid(page_to_pfn(pages[i])))
5290 {
5291 page_cache_release(pages[i]);
5292 }
5293 }
5294 }
5295
5296 /* Success. */
5297 status = gcvSTATUS_OK;
5298 }
5299 while (gcvFALSE);
5300
5301 if (info != gcvNULL)
5302 {
5303 /* Free the page array. */
5304 if (info->pages != gcvNULL)
5305 {
5306 kfree(info->pages);
5307 }
5308
5309 kfree(info);
5310 }
5311
5312 MEMORY_MAP_UNLOCK(Os);
5313
5314 /* Return the status. */
5315 gcmkFOOTER();
5316 return status;
5317}
5318#endif
5319}
5320
5321/*******************************************************************************
5322**
5323** gckOS_GetBaseAddress
5324**
5325** Get the base address for the physical memory.
5326**
5327** INPUT:
5328**
5329** gckOS Os
5330** Pointer to the gckOS object.
5331**
5332** OUTPUT:
5333**
5334** gctUINT32_PTR BaseAddress
5335** Pointer to a variable that will receive the base address.
5336*/
5337gceSTATUS
5338gckOS_GetBaseAddress(
5339 IN gckOS Os,
5340 OUT gctUINT32_PTR BaseAddress
5341 )
5342{
5343 gcmkHEADER_ARG("Os=0x%X", Os);
5344
5345 /* Verify the arguments. */
5346 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5347 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5348
5349 /* Return base address. */
5350 *BaseAddress = Os->device->baseAddress;
5351
5352 /* Success. */
5353 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5354 return gcvSTATUS_OK;
5355}
5356
5357gceSTATUS
5358gckOS_SuspendInterrupt(
5359 IN gckOS Os
5360 )
5361{
5362 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5363}
5364
5365gceSTATUS
5366gckOS_SuspendInterruptEx(
5367 IN gckOS Os,
5368 IN gceCORE Core
5369 )
5370{
5371 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5372
5373 /* Verify the arguments. */
5374 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5375
5376 disable_irq(Os->device->irqLines[Core]);
5377
5378 gcmkFOOTER_NO();
5379 return gcvSTATUS_OK;
5380}
5381
5382gceSTATUS
5383gckOS_ResumeInterrupt(
5384 IN gckOS Os
5385 )
5386{
5387 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
5388}
5389
5390gceSTATUS
5391gckOS_ResumeInterruptEx(
5392 IN gckOS Os,
5393 IN gceCORE Core
5394 )
5395{
5396 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5397
5398 /* Verify the arguments. */
5399 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5400
5401 enable_irq(Os->device->irqLines[Core]);
5402
5403 gcmkFOOTER_NO();
5404 return gcvSTATUS_OK;
5405}
5406
5407gceSTATUS
5408gckOS_MemCopy(
5409 IN gctPOINTER Destination,
5410 IN gctCONST_POINTER Source,
5411 IN gctSIZE_T Bytes
5412 )
5413{
5414 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
5415 Destination, Source, Bytes);
5416
5417 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
5418 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
5419 gcmkVERIFY_ARGUMENT(Bytes > 0);
5420
5421 memcpy(Destination, Source, Bytes);
5422
5423 gcmkFOOTER_NO();
5424 return gcvSTATUS_OK;
5425}
5426
5427gceSTATUS
5428gckOS_ZeroMemory(
5429 IN gctPOINTER Memory,
5430 IN gctSIZE_T Bytes
5431 )
5432{
5433 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
5434
5435 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5436 gcmkVERIFY_ARGUMENT(Bytes > 0);
5437
5438 memset(Memory, 0, Bytes);
5439
5440 gcmkFOOTER_NO();
5441 return gcvSTATUS_OK;
5442}
5443
5444/*******************************************************************************
5445********************************* Cache Control ********************************
5446*******************************************************************************/
5447
5448/*******************************************************************************
5449** gckOS_CacheClean
5450**
5451** Clean the cache for the specified addresses. The GPU is going to need the
5452** data. If the system is allocating memory as non-cachable, this function can
5453** be ignored.
5454**
5455** ARGUMENTS:
5456**
5457** gckOS Os
5458** Pointer to gckOS object.
5459**
5460** gctUINT32 ProcessID
5461** Process ID Logical belongs.
5462**
5463** gctPHYS_ADDR Handle
5464** Physical address handle. If gcvNULL it is video memory.
5465**
5466** gctPOINTER Physical
5467** Physical address to flush.
5468**
5469** gctPOINTER Logical
5470** Logical address to flush.
5471**
5472** gctSIZE_T Bytes
5473** Size of the address range in bytes to flush.
5474*/
5475gceSTATUS
5476gckOS_CacheClean(
5477 IN gckOS Os,
5478 IN gctUINT32 ProcessID,
5479 IN gctPHYS_ADDR Handle,
5480 IN gctPHYS_ADDR_T Physical,
5481 IN gctPOINTER Logical,
5482 IN gctSIZE_T Bytes
5483 )
5484{
5485 gcsPLATFORM * platform;
5486
5487 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5488 Os, ProcessID, Handle, Logical, Bytes);
5489
5490 /* Verify the arguments. */
5491 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5492 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
5493 gcmkVERIFY_ARGUMENT(Bytes > 0);
5494
5495 platform = Os->device->platform;
5496
5497 if (platform && platform->ops->cache)
5498 {
5499 platform->ops->cache(
5500 platform,
5501 ProcessID,
5502 Handle,
5503 Physical,
5504 Logical,
5505 Bytes,
5506 gcvCACHE_CLEAN
5507 );
5508
5509 /* Success. */
5510 gcmkFOOTER_NO();
5511 return gcvSTATUS_OK;
5512 }
5513
5514 /* @tga dmac_map_area is not exported starting from k4.3
5515 * using arm_dma_ops ops. Ideally place this in platform
5516 * specific function above.
5517 */
5518 arm_dma_ops.sync_single_for_device(gcvNULL,
5519 (dma_addr_t)Physical, Bytes, DMA_TO_DEVICE);
5520#if 0
5521#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5522#ifdef CONFIG_ARM
5523
5524 /* Inner cache. */
5525#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
5526 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
5527# else
5528 dmac_clean_range(Logical, Logical + Bytes);
5529# endif
5530
5531#if defined(CONFIG_OUTER_CACHE)
5532 /* Outer cache. */
5533#if gcdENABLE_OUTER_CACHE_PATCH
5534 _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_CLEAN);
5535#else
5536 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
5537#endif
5538#endif
5539
5540#elif defined(CONFIG_MIPS)
5541
5542 dma_cache_wback((unsigned long) Logical, Bytes);
5543
5544#elif defined(CONFIG_PPC)
5545
5546 /* TODO */
5547
5548#else
5549 dma_sync_single_for_device(
5550 gcvNULL,
5551 (dma_addr_t)Physical,
5552 Bytes,
5553 DMA_TO_DEVICE);
5554#endif
5555#endif
5556#endif
5557
5558 /* Success. */
5559 gcmkFOOTER_NO();
5560 return gcvSTATUS_OK;
5561}
5562
5563/*******************************************************************************
5564** gckOS_CacheInvalidate
5565**
5566** Invalidate the cache for the specified addresses. The GPU is going to need
5567** data. If the system is allocating memory as non-cachable, this function can
5568** be ignored.
5569**
5570** ARGUMENTS:
5571**
5572** gckOS Os
5573** Pointer to gckOS object.
5574**
5575** gctUINT32 ProcessID
5576** Process ID Logical belongs.
5577**
5578** gctPHYS_ADDR Handle
5579** Physical address handle. If gcvNULL it is video memory.
5580**
5581** gctPOINTER Logical
5582** Logical address to flush.
5583**
5584** gctSIZE_T Bytes
5585** Size of the address range in bytes to flush.
5586*/
5587gceSTATUS
5588gckOS_CacheInvalidate(
5589 IN gckOS Os,
5590 IN gctUINT32 ProcessID,
5591 IN gctPHYS_ADDR Handle,
5592 IN gctPHYS_ADDR_T Physical,
5593 IN gctPOINTER Logical,
5594 IN gctSIZE_T Bytes
5595 )
5596{
5597 gcsPLATFORM * platform;
5598
5599 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5600 Os, ProcessID, Handle, Logical, Bytes);
5601
5602 /* Verify the arguments. */
5603 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5604 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
5605 gcmkVERIFY_ARGUMENT(Bytes > 0);
5606
5607 platform = Os->device->platform;
5608
5609 if (platform && platform->ops->cache)
5610 {
5611 platform->ops->cache(
5612 platform,
5613 ProcessID,
5614 Handle,
5615 Physical,
5616 Logical,
5617 Bytes,
5618 gcvCACHE_INVALIDATE
5619 );
5620
5621 /* Success. */
5622 gcmkFOOTER_NO();
5623 return gcvSTATUS_OK;
5624 }
5625
5626 /* @tga `dmac_map_area` function/macro is no longer exported starting
5627 * from k4.3. Using dma mappings API ops instead, ideally these need
5628 * to go inside platform specific ops above. TODO
5629 */
5630 arm_dma_ops.sync_single_for_cpu(gcvNULL,
5631 (dma_addr_t)Physical, Bytes, DMA_FROM_DEVICE);
5632#if 0
5633#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5634#ifdef CONFIG_ARM
5635
5636 /* Inner cache. */
5637#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
5638 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
5639# else
5640 dmac_inv_range(Logical, Logical + Bytes);
5641# endif
5642
5643#if defined(CONFIG_OUTER_CACHE)
5644 /* Outer cache. */
5645#if gcdENABLE_OUTER_CACHE_PATCH
5646 _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
5647#else
5648 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
5649#endif
5650#endif
5651
5652#elif defined(CONFIG_MIPS)
5653 dma_cache_inv((unsigned long) Logical, Bytes);
5654#elif defined(CONFIG_PPC)
5655 /* TODO */
5656#else
5657 dma_sync_single_for_device(
5658 gcvNULL,
5659 (dma_addr_t)Physical,
5660 Bytes,
5661 DMA_FROM_DEVICE);
5662#endif
5663#endif
5664#endif
5665
5666 /* Success. */
5667 gcmkFOOTER_NO();
5668 return gcvSTATUS_OK;
5669}
5670
5671/*******************************************************************************
5672** gckOS_CacheFlush
5673**
5674** Clean the cache for the specified addresses and invalidate the lines as
5675** well. The GPU is going to need and modify the data. If the system is
5676** allocating memory as non-cachable, this function can be ignored.
5677**
5678** ARGUMENTS:
5679**
5680** gckOS Os
5681** Pointer to gckOS object.
5682**
5683** gctUINT32 ProcessID
5684** Process ID Logical belongs.
5685**
5686** gctPHYS_ADDR Handle
5687** Physical address handle. If gcvNULL it is video memory.
5688**
5689** gctPOINTER Logical
5690** Logical address to flush.
5691**
5692** gctSIZE_T Bytes
5693** Size of the address range in bytes to flush.
5694*/
5695gceSTATUS
5696gckOS_CacheFlush(
5697 IN gckOS Os,
5698 IN gctUINT32 ProcessID,
5699 IN gctPHYS_ADDR Handle,
5700 IN gctPHYS_ADDR_T Physical,
5701 IN gctPOINTER Logical,
5702 IN gctSIZE_T Bytes
5703 )
5704{
5705 gcsPLATFORM * platform;
5706
5707 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5708 Os, ProcessID, Handle, Logical, Bytes);
5709
5710 /* Verify the arguments. */
5711 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5712 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
5713 gcmkVERIFY_ARGUMENT(Bytes > 0);
5714
5715 platform = Os->device->platform;
5716
5717 if (platform && platform->ops->cache)
5718 {
5719 platform->ops->cache(
5720 platform,
5721 ProcessID,
5722 Handle,
5723 Physical,
5724 Logical,
5725 Bytes,
5726 gcvCACHE_FLUSH
5727 );
5728
5729 /* Success. */
5730 gcmkFOOTER_NO();
5731 return gcvSTATUS_OK;
5732 }
5733
5734#if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5735#ifdef CONFIG_ARM
5736 /* Inner cache. */
5737 dmac_flush_range(Logical, Logical + Bytes);
5738
5739#if defined(CONFIG_OUTER_CACHE)
5740 /* Outer cache. */
5741#if gcdENABLE_OUTER_CACHE_PATCH
5742 _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_FLUSH);
5743#else
5744 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
5745#endif
5746#endif
5747
5748#elif defined(CONFIG_MIPS)
5749 dma_cache_wback_inv((unsigned long) Logical, Bytes);
5750#elif defined(CONFIG_PPC)
5751 /* TODO */
5752#else
5753 dma_sync_single_for_device(
5754 gcvNULL,
5755 (dma_addr_t)Physical,
5756 Bytes,
5757 DMA_BIDIRECTIONAL);
5758#endif
5759#endif
5760
5761 /* Success. */
5762 gcmkFOOTER_NO();
5763 return gcvSTATUS_OK;
5764}
5765
5766/*******************************************************************************
5767********************************* Broadcasting *********************************
5768*******************************************************************************/
5769
5770/*******************************************************************************
5771**
5772** gckOS_Broadcast
5773**
5774** System hook for broadcast events from the kernel driver.
5775**
5776** INPUT:
5777**
5778** gckOS Os
5779** Pointer to the gckOS object.
5780**
5781** gckHARDWARE Hardware
5782** Pointer to the gckHARDWARE object.
5783**
5784** gceBROADCAST Reason
5785** Reason for the broadcast. Can be one of the following values:
5786**
5787** gcvBROADCAST_GPU_IDLE
5788** Broadcasted when the kernel driver thinks the GPU might be
5789** idle. This can be used to handle power management.
5790**
5791** gcvBROADCAST_GPU_COMMIT
5792** Broadcasted when any client process commits a command
5793** buffer. This can be used to handle power management.
5794**
5795** gcvBROADCAST_GPU_STUCK
5796** Broadcasted when the kernel driver hits the timeout waiting
5797** for the GPU.
5798**
5799** gcvBROADCAST_FIRST_PROCESS
5800** First process is trying to connect to the kernel.
5801**
5802** gcvBROADCAST_LAST_PROCESS
5803** Last process has detached from the kernel.
5804**
5805** OUTPUT:
5806**
5807** Nothing.
5808*/
5809gceSTATUS
5810gckOS_Broadcast(
5811 IN gckOS Os,
5812 IN gckHARDWARE Hardware,
5813 IN gceBROADCAST Reason
5814 )
5815{
5816 gceSTATUS status;
5817
5818 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
5819
5820 /* Verify the arguments. */
5821 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5822 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5823
5824 switch (Reason)
5825 {
5826 case gcvBROADCAST_FIRST_PROCESS:
5827 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
5828 break;
5829
5830 case gcvBROADCAST_LAST_PROCESS:
5831 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
5832
5833 /* Put GPU OFF. */
5834 gcmkONERROR(
5835 gckHARDWARE_SetPowerManagementState(Hardware,
5836 gcvPOWER_OFF_BROADCAST));
5837 break;
5838
5839 case gcvBROADCAST_GPU_IDLE:
5840 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
5841
5842 /* Put GPU IDLE. */
5843 gcmkONERROR(
5844 gckHARDWARE_SetPowerManagementState(Hardware,
5845#if gcdPOWER_SUSPEND_WHEN_IDLE
5846 gcvPOWER_SUSPEND_BROADCAST));
5847#else
5848 gcvPOWER_IDLE_BROADCAST));
5849#endif
5850
5851 /* Add idle process DB. */
5852 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
5853 1,
5854 gcvDB_IDLE,
5855 gcvNULL, gcvNULL, 0));
5856 break;
5857
5858 case gcvBROADCAST_GPU_COMMIT:
5859 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
5860
5861 /* Add busy process DB. */
5862 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
5863 0,
5864 gcvDB_IDLE,
5865 gcvNULL, gcvNULL, 0));
5866
5867 /* Put GPU ON. */
5868 gcmkONERROR(
5869 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
5870 break;
5871
5872 case gcvBROADCAST_GPU_STUCK:
5873 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
5874 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
5875 break;
5876
5877 case gcvBROADCAST_AXI_BUS_ERROR:
5878 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
5879 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
5880 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
5881 break;
5882
5883 case gcvBROADCAST_OUT_OF_MEMORY:
5884 gcmkTRACE_N(gcvLEVEL_INFO, 0, "gcvBROADCAST_OUT_OF_MEMORY\n");
5885
5886 status = _ShrinkMemory(Os);
5887
5888 if (status == gcvSTATUS_NOT_SUPPORTED)
5889 {
5890 goto OnError;
5891 }
5892
5893 gcmkONERROR(status);
5894
5895 break;
5896
5897 default:
5898 /* Skip unimplemented broadcast. */
5899 break;
5900 }
5901
5902 /* Success. */
5903 gcmkFOOTER_NO();
5904 return gcvSTATUS_OK;
5905
5906OnError:
5907 /* Return the status. */
5908 gcmkFOOTER();
5909 return status;
5910}
5911
5912/*******************************************************************************
5913**
5914** gckOS_BroadcastHurry
5915**
5916** The GPU is running too slow.
5917**
5918** INPUT:
5919**
5920** gckOS Os
5921** Pointer to the gckOS object.
5922**
5923** gckHARDWARE Hardware
5924** Pointer to the gckHARDWARE object.
5925**
5926** gctUINT Urgency
5927** The higher the number, the higher the urgency to speed up the GPU.
5928** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
5929**
5930** OUTPUT:
5931**
5932** Nothing.
5933*/
5934gceSTATUS
5935gckOS_BroadcastHurry(
5936 IN gckOS Os,
5937 IN gckHARDWARE Hardware,
5938 IN gctUINT Urgency
5939 )
5940{
5941 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
5942
5943 /* Do whatever you need to do to speed up the GPU now. */
5944
5945 /* Success. */
5946 gcmkFOOTER_NO();
5947 return gcvSTATUS_OK;
5948}
5949
5950/*******************************************************************************
5951**
5952** gckOS_BroadcastCalibrateSpeed
5953**
5954** Calibrate the speed of the GPU.
5955**
5956** INPUT:
5957**
5958** gckOS Os
5959** Pointer to the gckOS object.
5960**
5961** gckHARDWARE Hardware
5962** Pointer to the gckHARDWARE object.
5963**
5964** gctUINT Idle, Time
5965** Idle/Time will give the percentage the GPU is idle, so you can use
5966** this to calibrate the working point of the GPU.
5967**
5968** OUTPUT:
5969**
5970** Nothing.
5971*/
5972gceSTATUS
5973gckOS_BroadcastCalibrateSpeed(
5974 IN gckOS Os,
5975 IN gckHARDWARE Hardware,
5976 IN gctUINT Idle,
5977 IN gctUINT Time
5978 )
5979{
5980 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
5981 Os, Hardware, Idle, Time);
5982
5983 /* Do whatever you need to do to callibrate the GPU speed. */
5984
5985 /* Success. */
5986 gcmkFOOTER_NO();
5987 return gcvSTATUS_OK;
5988}
5989
5990/*******************************************************************************
5991********************************** Semaphores **********************************
5992*******************************************************************************/
5993
5994/*******************************************************************************
5995**
5996** gckOS_CreateSemaphore
5997**
5998** Create a semaphore.
5999**
6000** INPUT:
6001**
6002** gckOS Os
6003** Pointer to the gckOS object.
6004**
6005** OUTPUT:
6006**
6007** gctPOINTER * Semaphore
6008** Pointer to the variable that will receive the created semaphore.
6009*/
6010gceSTATUS
6011gckOS_CreateSemaphore(
6012 IN gckOS Os,
6013 OUT gctPOINTER * Semaphore
6014 )
6015{
6016 gceSTATUS status;
6017 struct semaphore *sem = gcvNULL;
6018
6019 gcmkHEADER_ARG("Os=0x%X", Os);
6020
6021 /* Verify the arguments. */
6022 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6023 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6024
6025 /* Allocate the semaphore structure. */
6026 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6027 if (sem == gcvNULL)
6028 {
6029 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6030 }
6031
6032 /* Initialize the semaphore. */
6033 sema_init(sem, 1);
6034
6035 /* Return to caller. */
6036 *Semaphore = (gctPOINTER) sem;
6037
6038 /* Success. */
6039 gcmkFOOTER_NO();
6040 return gcvSTATUS_OK;
6041
6042OnError:
6043 /* Return the status. */
6044 gcmkFOOTER();
6045 return status;
6046}
6047
6048/*******************************************************************************
6049**
6050** gckOS_AcquireSemaphore
6051**
6052** Acquire a semaphore.
6053**
6054** INPUT:
6055**
6056** gckOS Os
6057** Pointer to the gckOS object.
6058**
6059** gctPOINTER Semaphore
6060** Pointer to the semaphore thet needs to be acquired.
6061**
6062** OUTPUT:
6063**
6064** Nothing.
6065*/
6066gceSTATUS
6067gckOS_AcquireSemaphore(
6068 IN gckOS Os,
6069 IN gctPOINTER Semaphore
6070 )
6071{
6072 gceSTATUS status;
6073
6074 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6075
6076 /* Verify the arguments. */
6077 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6078 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6079
6080 /* Acquire the semaphore. */
6081 if (down_interruptible((struct semaphore *) Semaphore))
6082 {
6083 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6084 }
6085
6086 /* Success. */
6087 gcmkFOOTER_NO();
6088 return gcvSTATUS_OK;
6089
6090OnError:
6091 /* Return the status. */
6092 gcmkFOOTER();
6093 return status;
6094}
6095
6096/*******************************************************************************
6097**
6098** gckOS_TryAcquireSemaphore
6099**
6100** Try to acquire a semaphore.
6101**
6102** INPUT:
6103**
6104** gckOS Os
6105** Pointer to the gckOS object.
6106**
6107** gctPOINTER Semaphore
6108** Pointer to the semaphore thet needs to be acquired.
6109**
6110** OUTPUT:
6111**
6112** Nothing.
6113*/
6114gceSTATUS
6115gckOS_TryAcquireSemaphore(
6116 IN gckOS Os,
6117 IN gctPOINTER Semaphore
6118 )
6119{
6120 gceSTATUS status;
6121
6122 gcmkHEADER_ARG("Os=0x%x", Os);
6123
6124 /* Verify the arguments. */
6125 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6126 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6127
6128 /* Acquire the semaphore. */
6129 if (down_trylock((struct semaphore *) Semaphore))
6130 {
6131 /* Timeout. */
6132 status = gcvSTATUS_TIMEOUT;
6133 gcmkFOOTER();
6134 return status;
6135 }
6136
6137 /* Success. */
6138 gcmkFOOTER_NO();
6139 return gcvSTATUS_OK;
6140}
6141
6142/*******************************************************************************
6143**
6144** gckOS_ReleaseSemaphore
6145**
6146** Release a previously acquired semaphore.
6147**
6148** INPUT:
6149**
6150** gckOS Os
6151** Pointer to the gckOS object.
6152**
6153** gctPOINTER Semaphore
6154** Pointer to the semaphore thet needs to be released.
6155**
6156** OUTPUT:
6157**
6158** Nothing.
6159*/
6160gceSTATUS
6161gckOS_ReleaseSemaphore(
6162 IN gckOS Os,
6163 IN gctPOINTER Semaphore
6164 )
6165{
6166 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6167
6168 /* Verify the arguments. */
6169 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6170 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6171
6172 /* Release the semaphore. */
6173 up((struct semaphore *) Semaphore);
6174
6175 /* Success. */
6176 gcmkFOOTER_NO();
6177 return gcvSTATUS_OK;
6178}
6179
6180/*******************************************************************************
6181**
6182** gckOS_DestroySemaphore
6183**
6184** Destroy a semaphore.
6185**
6186** INPUT:
6187**
6188** gckOS Os
6189** Pointer to the gckOS object.
6190**
6191** gctPOINTER Semaphore
6192** Pointer to the semaphore thet needs to be destroyed.
6193**
6194** OUTPUT:
6195**
6196** Nothing.
6197*/
6198gceSTATUS
6199gckOS_DestroySemaphore(
6200 IN gckOS Os,
6201 IN gctPOINTER Semaphore
6202 )
6203{
6204 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6205
6206 /* Verify the arguments. */
6207 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6208 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6209
6210 /* Free the sempahore structure. */
6211 kfree(Semaphore);
6212
6213 /* Success. */
6214 gcmkFOOTER_NO();
6215 return gcvSTATUS_OK;
6216}
6217
6218/*******************************************************************************
6219**
6220** gckOS_GetProcessID
6221**
6222** Get current process ID.
6223**
6224** INPUT:
6225**
6226** Nothing.
6227**
6228** OUTPUT:
6229**
6230** gctUINT32_PTR ProcessID
6231** Pointer to the variable that receives the process ID.
6232*/
6233gceSTATUS
6234gckOS_GetProcessID(
6235 OUT gctUINT32_PTR ProcessID
6236 )
6237{
6238 /* Get process ID. */
6239 if (ProcessID != gcvNULL)
6240 {
6241 *ProcessID = _GetProcessID();
6242 }
6243
6244 /* Success. */
6245 return gcvSTATUS_OK;
6246}
6247
6248/*******************************************************************************
6249**
6250** gckOS_GetThreadID
6251**
6252** Get current thread ID.
6253**
6254** INPUT:
6255**
6256** Nothing.
6257**
6258** OUTPUT:
6259**
6260** gctUINT32_PTR ThreadID
6261** Pointer to the variable that receives the thread ID.
6262*/
6263gceSTATUS
6264gckOS_GetThreadID(
6265 OUT gctUINT32_PTR ThreadID
6266 )
6267{
6268 /* Get thread ID. */
6269 if (ThreadID != gcvNULL)
6270 {
6271 *ThreadID = _GetThreadID();
6272 }
6273
6274 /* Success. */
6275 return gcvSTATUS_OK;
6276}
6277
6278/*******************************************************************************
6279**
6280** gckOS_SetGPUPower
6281**
6282** Set the power of the GPU on or off.
6283**
6284** INPUT:
6285**
6286** gckOS Os
6287** Pointer to a gckOS object.
6288**
6289** gceCORE Core
6290** GPU whose power is set.
6291**
6292** gctBOOL Clock
6293** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6294**
6295** gctBOOL Power
6296** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6297**
6298** OUTPUT:
6299**
6300** Nothing.
6301*/
6302gceSTATUS
6303gckOS_SetGPUPower(
6304 IN gckOS Os,
6305 IN gceCORE Core,
6306 IN gctBOOL Clock,
6307 IN gctBOOL Power
6308 )
6309{
6310 gcsPLATFORM * platform;
6311
6312 gctBOOL powerChange = gcvFALSE;
6313 gctBOOL clockChange = gcvFALSE;
6314
6315 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6316 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6317
6318 platform = Os->device->platform;
6319
6320 powerChange = (Power != Os->powerStates[Core]);
6321
6322 clockChange = (Clock != Os->clockStates[Core]);
6323
6324 if (powerChange && (Power == gcvTRUE))
6325 {
6326 if (platform && platform->ops->setPower)
6327 {
6328 gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
6329 }
6330
6331 Os->powerStates[Core] = Power;
6332 }
6333
6334 if (clockChange)
6335 {
6336 mutex_lock(&Os->registerAccessLocks[Core]);
6337
6338 if (platform && platform->ops->setClock)
6339 {
6340 gcmkVERIFY_OK(platform->ops->setClock(platform, Core, Clock));
6341 }
6342
6343 Os->clockStates[Core] = Clock;
6344
6345 mutex_unlock(&Os->registerAccessLocks[Core]);
6346 }
6347
6348 if (powerChange && (Power == gcvFALSE))
6349 {
6350 if (platform && platform->ops->setPower)
6351 {
6352 gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
6353 }
6354
6355 Os->powerStates[Core] = Power;
6356 }
6357
6358 gcmkFOOTER_NO();
6359 return gcvSTATUS_OK;
6360}
6361
6362/*******************************************************************************
6363**
6364** gckOS_ResetGPU
6365**
6366** Reset the GPU.
6367**
6368** INPUT:
6369**
6370** gckOS Os
6371** Pointer to a gckOS object.
6372**
6373** gckCORE Core
6374** GPU whose power is set.
6375**
6376** OUTPUT:
6377**
6378** Nothing.
6379*/
6380gceSTATUS
6381gckOS_ResetGPU(
6382 IN gckOS Os,
6383 IN gceCORE Core
6384 )
6385{
6386 gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
6387 gcsPLATFORM * platform;
6388
6389 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
6390 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6391
6392 platform = Os->device->platform;
6393
6394 if (platform && platform->ops->reset)
6395 {
6396 status = platform->ops->reset(platform, Core);
6397 }
6398
6399 gcmkFOOTER_NO();
6400 return status;
6401}
6402
6403/*******************************************************************************
6404**
6405** gckOS_PrepareGPUFrequency
6406**
6407** Prepare to set GPU frequency and voltage.
6408**
6409** INPUT:
6410**
6411** gckOS Os
6412** Pointer to a gckOS object.
6413**
6414** gckCORE Core
6415** GPU whose frequency and voltage will be set.
6416**
6417** OUTPUT:
6418**
6419** Nothing.
6420*/
6421gceSTATUS
6422gckOS_PrepareGPUFrequency(
6423 IN gckOS Os,
6424 IN gceCORE Core
6425 )
6426{
6427 return gcvSTATUS_OK;
6428}
6429
6430/*******************************************************************************
6431**
6432** gckOS_FinishGPUFrequency
6433**
6434** Finish GPU frequency setting.
6435**
6436** INPUT:
6437**
6438** gckOS Os
6439** Pointer to a gckOS object.
6440**
6441** gckCORE Core
6442** GPU whose frequency and voltage is set.
6443**
6444** OUTPUT:
6445**
6446** Nothing.
6447*/
6448gceSTATUS
6449gckOS_FinishGPUFrequency(
6450 IN gckOS Os,
6451 IN gceCORE Core
6452 )
6453{
6454 return gcvSTATUS_OK;
6455}
6456
6457/*******************************************************************************
6458**
6459** gckOS_QueryGPUFrequency
6460**
6461** Query the current frequency of the GPU.
6462**
6463** INPUT:
6464**
6465** gckOS Os
6466** Pointer to a gckOS object.
6467**
6468** gckCORE Core
6469** GPU whose power is set.
6470**
6471** gctUINT32 * Frequency
6472** Pointer to a gctUINT32 to obtain current frequency, in MHz.
6473**
6474** gctUINT8 * Scale
6475** Pointer to a gctUINT8 to obtain current scale(1 - 64).
6476**
6477** OUTPUT:
6478**
6479** Nothing.
6480*/
6481gceSTATUS
6482gckOS_QueryGPUFrequency(
6483 IN gckOS Os,
6484 IN gceCORE Core,
6485 OUT gctUINT32 * Frequency,
6486 OUT gctUINT8 * Scale
6487 )
6488{
6489 return gcvSTATUS_OK;
6490}
6491
6492/*******************************************************************************
6493**
6494** gckOS_SetGPUFrequency
6495**
6496** Set frequency and voltage of the GPU.
6497**
6498** 1. DVFS manager gives the target scale of full frequency, BSP must find
6499** a real frequency according to this scale and board's configure.
6500**
6501** 2. BSP should find a suitable voltage for this frequency.
6502**
6503** 3. BSP must make sure setting take effect before this function returns.
6504**
6505** INPUT:
6506**
6507** gckOS Os
6508** Pointer to a gckOS object.
6509**
6510** gckCORE Core
6511** GPU whose power is set.
6512**
6513** gctUINT8 Scale
6514** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
6515** full frequency and 64 means 64/64 of full frequency.
6516**
6517** OUTPUT:
6518**
6519** Nothing.
6520*/
6521gceSTATUS
6522gckOS_SetGPUFrequency(
6523 IN gckOS Os,
6524 IN gceCORE Core,
6525 IN gctUINT8 Scale
6526 )
6527{
6528 return gcvSTATUS_OK;
6529}
6530
6531/*----------------------------------------------------------------------------*/
6532/*----- Profile --------------------------------------------------------------*/
6533
6534gceSTATUS
6535gckOS_GetProfileTick(
6536 OUT gctUINT64_PTR Tick
6537 )
6538{
6539 struct timespec time;
6540
6541 ktime_get_ts(&time);
6542
6543 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
6544
6545 return gcvSTATUS_OK;
6546}
6547
6548gceSTATUS
6549gckOS_QueryProfileTickRate(
6550 OUT gctUINT64_PTR TickRate
6551 )
6552{
6553 struct timespec res;
6554
6555 res.tv_sec = 0;
6556 res.tv_nsec = hrtimer_resolution;
6557
6558 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
6559
6560 return gcvSTATUS_OK;
6561}
6562
6563gctUINT32
6564gckOS_ProfileToMS(
6565 IN gctUINT64 Ticks
6566 )
6567{
6568#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
6569 return div_u64(Ticks, 1000000);
6570#else
6571 gctUINT64 rem = Ticks;
6572 gctUINT64 b = 1000000;
6573 gctUINT64 res, d = 1;
6574 gctUINT32 high = rem >> 32;
6575
6576 /* Reduce the thing a bit first */
6577 res = 0;
6578 if (high >= 1000000)
6579 {
6580 high /= 1000000;
6581 res = (gctUINT64) high << 32;
6582 rem -= (gctUINT64) (high * 1000000) << 32;
6583 }
6584
6585 while (((gctINT64) b > 0) && (b < rem))
6586 {
6587 b <<= 1;
6588 d <<= 1;
6589 }
6590
6591 do
6592 {
6593 if (rem >= b)
6594 {
6595 rem -= b;
6596 res += d;
6597 }
6598
6599 b >>= 1;
6600 d >>= 1;
6601 }
6602 while (d);
6603
6604 return (gctUINT32) res;
6605#endif
6606}
6607
6608/******************************************************************************\
6609******************************* Signal Management ******************************
6610\******************************************************************************/
6611
6612#undef _GC_OBJ_ZONE
6613#define _GC_OBJ_ZONE gcvZONE_SIGNAL
6614
6615/*******************************************************************************
6616**
6617** gckOS_CreateSignal
6618**
6619** Create a new signal.
6620**
6621** INPUT:
6622**
6623** gckOS Os
6624** Pointer to an gckOS object.
6625**
6626** gctBOOL ManualReset
6627** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
6628** order to set the signal to nonsignaled state.
6629** If set to gcvFALSE, the signal will automatically be set to
6630** nonsignaled state by gckOS_WaitSignal function.
6631**
6632** OUTPUT:
6633**
6634** gctSIGNAL * Signal
6635** Pointer to a variable receiving the created gctSIGNAL.
6636*/
6637gceSTATUS
6638gckOS_CreateSignal(
6639 IN gckOS Os,
6640 IN gctBOOL ManualReset,
6641 OUT gctSIGNAL * Signal
6642 )
6643{
6644 gceSTATUS status;
6645 gcsSIGNAL_PTR signal;
6646
6647 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
6648
6649 /* Verify the arguments. */
6650 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6651 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
6652
6653 /* Create an event structure. */
6654 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
6655
6656 if (signal == gcvNULL)
6657 {
6658 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6659 }
6660
6661 /* Save the process ID. */
6662 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
6663 signal->manualReset = ManualReset;
6664 signal->hardware = gcvNULL;
6665 init_completion(&signal->obj);
6666 atomic_set(&signal->ref, 1);
6667
6668 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
6669
6670 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
6671
6672 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
6673 return gcvSTATUS_OK;
6674
6675OnError:
6676 if (signal != gcvNULL)
6677 {
6678 kfree(signal);
6679 }
6680
6681 gcmkFOOTER_NO();
6682 return status;
6683}
6684
6685gceSTATUS
6686gckOS_SignalQueryHardware(
6687 IN gckOS Os,
6688 IN gctSIGNAL Signal,
6689 OUT gckHARDWARE * Hardware
6690 )
6691{
6692 gceSTATUS status;
6693 gcsSIGNAL_PTR signal;
6694
6695 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
6696
6697 /* Verify the arguments. */
6698 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6699 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
6700 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
6701
6702 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
6703
6704 *Hardware = signal->hardware;
6705
6706 gcmkFOOTER_NO();
6707 return gcvSTATUS_OK;
6708OnError:
6709 gcmkFOOTER();
6710 return status;
6711}
6712
6713gceSTATUS
6714gckOS_SignalSetHardware(
6715 IN gckOS Os,
6716 IN gctSIGNAL Signal,
6717 IN gckHARDWARE Hardware
6718 )
6719{
6720 gceSTATUS status;
6721 gcsSIGNAL_PTR signal;
6722
6723 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
6724
6725 /* Verify the arguments. */
6726 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6727 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
6728
6729 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
6730
6731 signal->hardware = Hardware;
6732
6733 gcmkFOOTER_NO();
6734 return gcvSTATUS_OK;
6735OnError:
6736 gcmkFOOTER();
6737 return status;
6738}
6739
6740/*******************************************************************************
6741**
6742** gckOS_DestroySignal
6743**
6744** Destroy a signal.
6745**
6746** INPUT:
6747**
6748** gckOS Os
6749** Pointer to an gckOS object.
6750**
6751** gctSIGNAL Signal
6752** Pointer to the gctSIGNAL.
6753**
6754** OUTPUT:
6755**
6756** Nothing.
6757*/
6758gceSTATUS
6759gckOS_DestroySignal(
6760 IN gckOS Os,
6761 IN gctSIGNAL Signal
6762 )
6763{
6764 gceSTATUS status;
6765 gcsSIGNAL_PTR signal;
6766 gctBOOL acquired = gcvFALSE;
6767
6768 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
6769
6770 /* Verify the arguments. */
6771 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6772 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
6773
6774 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
6775 acquired = gcvTRUE;
6776
6777 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
6778
6779 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
6780
6781 if (atomic_dec_and_test(&signal->ref))
6782 {
6783 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
6784
6785 /* Free the sgianl. */
6786 kfree(signal);
6787 }
6788
6789 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
6790 acquired = gcvFALSE;
6791
6792 /* Success. */
6793 gcmkFOOTER_NO();
6794 return gcvSTATUS_OK;
6795
6796OnError:
6797 if (acquired)
6798 {
6799 /* Release the mutex. */
6800 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
6801 }
6802
6803 gcmkFOOTER();
6804 return status;
6805}
6806
6807/*******************************************************************************
6808**
6809** gckOS_Signal
6810**
6811** Set a state of the specified signal.
6812**
6813** INPUT:
6814**
6815** gckOS Os
6816** Pointer to an gckOS object.
6817**
6818** gctSIGNAL Signal
6819** Pointer to the gctSIGNAL.
6820**
6821** gctBOOL State
6822** If gcvTRUE, the signal will be set to signaled state.
6823** If gcvFALSE, the signal will be set to nonsignaled state.
6824**
6825** OUTPUT:
6826**
6827** Nothing.
6828*/
6829gceSTATUS
6830gckOS_Signal(
6831 IN gckOS Os,
6832 IN gctSIGNAL Signal,
6833 IN gctBOOL State
6834 )
6835{
6836 gceSTATUS status;
6837 gcsSIGNAL_PTR signal;
6838 gctBOOL acquired = gcvFALSE;
6839
6840 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
6841
6842 /* Verify the arguments. */
6843 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6844 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
6845
6846 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
6847 acquired = gcvTRUE;
6848
6849 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
6850
6851 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
6852
6853 if (State)
6854 {
6855 /* unbind the signal from hardware. */
6856 signal->hardware = gcvNULL;
6857
6858 /* Set the event to a signaled state. */
6859 complete(&signal->obj);
6860 }
6861 else
6862 {
6863 /* Set the event to an unsignaled state. */
6864#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
6865 reinit_completion(&signal->obj);
6866#else
6867 INIT_COMPLETION(signal->obj);
6868#endif
6869 }
6870
6871 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
6872 acquired = gcvFALSE;
6873
6874 /* Success. */
6875 gcmkFOOTER_NO();
6876 return gcvSTATUS_OK;
6877
6878OnError:
6879 if (acquired)
6880 {
6881 /* Release the mutex. */
6882 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
6883 }
6884
6885 gcmkFOOTER();
6886 return status;
6887}
6888
6889
6890/*******************************************************************************
6891**
6892** gckOS_UserSignal
6893**
6894** Set the specified signal which is owned by a process to signaled state.
6895**
6896** INPUT:
6897**
6898** gckOS Os
6899** Pointer to an gckOS object.
6900**
6901** gctSIGNAL Signal
6902** Pointer to the gctSIGNAL.
6903**
6904** gctHANDLE Process
6905** Handle of process owning the signal.
6906**
6907** OUTPUT:
6908**
6909** Nothing.
6910*/
6911gceSTATUS
6912gckOS_UserSignal(
6913 IN gckOS Os,
6914 IN gctSIGNAL Signal,
6915 IN gctHANDLE Process
6916 )
6917{
6918 gceSTATUS status;
6919 gctSIGNAL signal;
6920
6921 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
6922 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
6923
6924 /* Map the signal into kernel space. */
6925 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
6926
6927 /* Signal. */
6928 status = gckOS_Signal(Os, signal, gcvTRUE);
6929
6930 /* Unmap the signal */
6931 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
6932
6933 gcmkFOOTER();
6934 return status;
6935
6936OnError:
6937 /* Return the status. */
6938 gcmkFOOTER();
6939 return status;
6940}
6941
6942/*******************************************************************************
6943**
6944** gckOS_WaitSignal
6945**
6946** Wait for a signal to become signaled.
6947**
6948** INPUT:
6949**
6950** gckOS Os
6951** Pointer to an gckOS object.
6952**
6953** gctSIGNAL Signal
6954** Pointer to the gctSIGNAL.
6955**
6956** gctUINT32 Wait
6957** Number of milliseconds to wait.
6958** Pass the value of gcvINFINITE for an infinite wait.
6959**
6960** OUTPUT:
6961**
6962** Nothing.
6963*/
6964gceSTATUS
6965gckOS_WaitSignal(
6966 IN gckOS Os,
6967 IN gctSIGNAL Signal,
6968 IN gctUINT32 Wait
6969 )
6970{
6971 gceSTATUS status = gcvSTATUS_OK;
6972 gcsSIGNAL_PTR signal;
6973
6974 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
6975
6976 /* Verify the arguments. */
6977 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6978 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
6979
6980 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
6981
6982 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
6983
6984 might_sleep();
6985
6986 spin_lock_irq(&signal->obj.wait.lock);
6987
6988 if (signal->obj.done)
6989 {
6990 if (!signal->manualReset)
6991 {
6992 signal->obj.done = 0;
6993 }
6994
6995 status = gcvSTATUS_OK;
6996 }
6997 else if (Wait == 0)
6998 {
6999 status = gcvSTATUS_TIMEOUT;
7000 }
7001 else
7002 {
7003 /* Convert wait to milliseconds. */
7004 long timeout = (Wait == gcvINFINITE)
7005 ? MAX_SCHEDULE_TIMEOUT
7006 : Wait * HZ / 1000;
7007
7008 DECLARE_WAITQUEUE(wait, current);
7009 wait.flags |= WQ_FLAG_EXCLUSIVE;
7010 __add_wait_queue_tail(&signal->obj.wait, &wait);
7011
7012 while (gcvTRUE)
7013 {
7014 if (signal_pending(current))
7015 {
7016 /* Interrupt received. */
7017 status = gcvSTATUS_INTERRUPTED;
7018 break;
7019 }
7020
7021 __set_current_state(TASK_INTERRUPTIBLE);
7022 spin_unlock_irq(&signal->obj.wait.lock);
7023 timeout = schedule_timeout(timeout);
7024 spin_lock_irq(&signal->obj.wait.lock);
7025
7026 if (signal->obj.done)
7027 {
7028 if (!signal->manualReset)
7029 {
7030 signal->obj.done = 0;
7031 }
7032
7033 status = gcvSTATUS_OK;
7034 break;
7035 }
7036
7037 if (timeout == 0)
7038 {
7039
7040 status = gcvSTATUS_TIMEOUT;
7041 break;
7042 }
7043 }
7044
7045 __remove_wait_queue(&signal->obj.wait, &wait);
7046 }
7047
7048 spin_unlock_irq(&signal->obj.wait.lock);
7049
7050OnError:
7051 /* Return status. */
7052 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7053 return status;
7054}
7055
7056/*******************************************************************************
7057**
7058** gckOS_MapSignal
7059**
7060** Map a signal in to the current process space.
7061**
7062** INPUT:
7063**
7064** gckOS Os
7065** Pointer to an gckOS object.
7066**
7067** gctSIGNAL Signal
7068** Pointer to tha gctSIGNAL to map.
7069**
7070** gctHANDLE Process
7071** Handle of process owning the signal.
7072**
7073** OUTPUT:
7074**
7075** gctSIGNAL * MappedSignal
7076** Pointer to a variable receiving the mapped gctSIGNAL.
7077*/
7078gceSTATUS
7079gckOS_MapSignal(
7080 IN gckOS Os,
7081 IN gctSIGNAL Signal,
7082 IN gctHANDLE Process,
7083 OUT gctSIGNAL * MappedSignal
7084 )
7085{
7086 gceSTATUS status;
7087 gcsSIGNAL_PTR signal;
7088 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7089
7090 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7091 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
7092
7093 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7094
7095 if(atomic_inc_return(&signal->ref) <= 1)
7096 {
7097 /* The previous value is 0, it has been deleted. */
7098 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7099 }
7100
7101 *MappedSignal = (gctSIGNAL) Signal;
7102
7103 /* Success. */
7104 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
7105 return gcvSTATUS_OK;
7106
7107OnError:
7108 gcmkFOOTER_NO();
7109 return status;
7110}
7111
7112/*******************************************************************************
7113**
7114** gckOS_UnmapSignal
7115**
7116** Unmap a signal .
7117**
7118** INPUT:
7119**
7120** gckOS Os
7121** Pointer to an gckOS object.
7122**
7123** gctSIGNAL Signal
7124** Pointer to that gctSIGNAL mapped.
7125*/
7126gceSTATUS
7127gckOS_UnmapSignal(
7128 IN gckOS Os,
7129 IN gctSIGNAL Signal
7130 )
7131{
7132 return gckOS_DestroySignal(Os, Signal);
7133}
7134
7135/*******************************************************************************
7136**
7137** gckOS_CreateUserSignal
7138**
7139** Create a new signal to be used in the user space.
7140**
7141** INPUT:
7142**
7143** gckOS Os
7144** Pointer to an gckOS object.
7145**
7146** gctBOOL ManualReset
7147** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7148** order to set the signal to nonsignaled state.
7149** If set to gcvFALSE, the signal will automatically be set to
7150** nonsignaled state by gckOS_WaitSignal function.
7151**
7152** OUTPUT:
7153**
7154** gctINT * SignalID
7155** Pointer to a variable receiving the created signal's ID.
7156*/
7157gceSTATUS
7158gckOS_CreateUserSignal(
7159 IN gckOS Os,
7160 IN gctBOOL ManualReset,
7161 OUT gctINT * SignalID
7162 )
7163{
7164 gceSTATUS status;
7165 gctSIZE_T signal;
7166
7167 /* Create a new signal. */
7168 gcmkONERROR(gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
7169 *SignalID = (gctINT) signal;
7170
7171OnError:
7172 return status;
7173}
7174
7175/*******************************************************************************
7176**
7177** gckOS_DestroyUserSignal
7178**
7179** Destroy a signal to be used in the user space.
7180**
7181** INPUT:
7182**
7183** gckOS Os
7184** Pointer to an gckOS object.
7185**
7186** gctINT SignalID
7187** The signal's ID.
7188**
7189** OUTPUT:
7190**
7191** Nothing.
7192*/
7193gceSTATUS
7194gckOS_DestroyUserSignal(
7195 IN gckOS Os,
7196 IN gctINT SignalID
7197 )
7198{
7199 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
7200}
7201
7202/*******************************************************************************
7203**
7204** gckOS_WaitUserSignal
7205**
7206** Wait for a signal used in the user mode to become signaled.
7207**
7208** INPUT:
7209**
7210** gckOS Os
7211** Pointer to an gckOS object.
7212**
7213** gctINT SignalID
7214** Signal ID.
7215**
7216** gctUINT32 Wait
7217** Number of milliseconds to wait.
7218** Pass the value of gcvINFINITE for an infinite wait.
7219**
7220** OUTPUT:
7221**
7222** Nothing.
7223*/
7224gceSTATUS
7225gckOS_WaitUserSignal(
7226 IN gckOS Os,
7227 IN gctINT SignalID,
7228 IN gctUINT32 Wait
7229 )
7230{
7231 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
7232}
7233
7234/*******************************************************************************
7235**
7236** gckOS_SignalUserSignal
7237**
7238** Set a state of the specified signal to be used in the user space.
7239**
7240** INPUT:
7241**
7242** gckOS Os
7243** Pointer to an gckOS object.
7244**
7245** gctINT SignalID
7246** SignalID.
7247**
7248** gctBOOL State
7249** If gcvTRUE, the signal will be set to signaled state.
7250** If gcvFALSE, the signal will be set to nonsignaled state.
7251**
7252** OUTPUT:
7253**
7254** Nothing.
7255*/
7256gceSTATUS
7257gckOS_SignalUserSignal(
7258 IN gckOS Os,
7259 IN gctINT SignalID,
7260 IN gctBOOL State
7261 )
7262{
7263 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
7264}
7265
7266
7267/******************************************************************************\
7268******************************** Software Timer ********************************
7269\******************************************************************************/
7270
7271void
7272_TimerFunction(
7273 struct work_struct * work
7274 )
7275{
7276 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
7277
7278 gctTIMERFUNCTION function = timer->function;
7279
7280 function(timer->data);
7281}
7282
7283/*******************************************************************************
7284**
7285** gckOS_CreateTimer
7286**
7287** Create a software timer.
7288**
7289** INPUT:
7290**
7291** gckOS Os
7292** Pointer to the gckOS object.
7293**
7294** gctTIMERFUNCTION Function.
7295** Pointer to a call back function which will be called when timer is
7296** expired.
7297**
7298** gctPOINTER Data.
7299** Private data which will be passed to call back function.
7300**
7301** OUTPUT:
7302**
7303** gctPOINTER * Timer
7304** Pointer to a variable receiving the created timer.
7305*/
7306gceSTATUS
7307gckOS_CreateTimer(
7308 IN gckOS Os,
7309 IN gctTIMERFUNCTION Function,
7310 IN gctPOINTER Data,
7311 OUT gctPOINTER * Timer
7312 )
7313{
7314 gceSTATUS status;
7315 gcsOSTIMER_PTR pointer;
7316 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
7317
7318 /* Verify the arguments. */
7319 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7320 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
7321
7322 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
7323
7324 pointer->function = Function;
7325 pointer->data = Data;
7326
7327 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
7328
7329 *Timer = pointer;
7330
7331 gcmkFOOTER_NO();
7332 return gcvSTATUS_OK;
7333
7334OnError:
7335 gcmkFOOTER();
7336 return status;
7337}
7338
7339/*******************************************************************************
7340**
7341** gckOS_DestroyTimer
7342**
7343** Destory a software timer.
7344**
7345** INPUT:
7346**
7347** gckOS Os
7348** Pointer to the gckOS object.
7349**
7350** gctPOINTER Timer
7351** Pointer to the timer to be destoryed.
7352**
7353** OUTPUT:
7354**
7355** Nothing.
7356*/
7357gceSTATUS
7358gckOS_DestroyTimer(
7359 IN gckOS Os,
7360 IN gctPOINTER Timer
7361 )
7362{
7363 gcsOSTIMER_PTR timer;
7364 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
7365
7366 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7367 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
7368
7369 timer = (gcsOSTIMER_PTR)Timer;
7370
7371#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
7372 cancel_delayed_work_sync(&timer->work);
7373#else
7374 cancel_delayed_work(&timer->work);
7375 flush_workqueue(Os->workqueue);
7376#endif
7377
7378 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
7379
7380 gcmkFOOTER_NO();
7381 return gcvSTATUS_OK;
7382}
7383
7384/*******************************************************************************
7385**
7386** gckOS_StartTimer
7387**
7388** Schedule a software timer.
7389**
7390** INPUT:
7391**
7392** gckOS Os
7393** Pointer to the gckOS object.
7394**
7395** gctPOINTER Timer
7396** Pointer to the timer to be scheduled.
7397**
7398** gctUINT32 Delay
7399** Delay in milliseconds.
7400**
7401** OUTPUT:
7402**
7403** Nothing.
7404*/
7405gceSTATUS
7406gckOS_StartTimer(
7407 IN gckOS Os,
7408 IN gctPOINTER Timer,
7409 IN gctUINT32 Delay
7410 )
7411{
7412 gcsOSTIMER_PTR timer;
7413
7414 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
7415
7416 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7417 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
7418 gcmkVERIFY_ARGUMENT(Delay != 0);
7419
7420 timer = (gcsOSTIMER_PTR)Timer;
7421
7422#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
7423 mod_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
7424#else
7425 if (unlikely(delayed_work_pending(&timer->work)))
7426 {
7427#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
7428 cancel_delayed_work_sync(&timer->work);
7429#else
7430 cancel_delayed_work(&timer->work);
7431 flush_workqueue(Os->workqueue);
7432#endif
7433 }
7434
7435 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
7436#endif
7437
7438 gcmkFOOTER_NO();
7439 return gcvSTATUS_OK;
7440}
7441
7442/*******************************************************************************
7443**
7444** gckOS_StopTimer
7445**
7446** Cancel a unscheduled timer.
7447**
7448** INPUT:
7449**
7450** gckOS Os
7451** Pointer to the gckOS object.
7452**
7453** gctPOINTER Timer
7454** Pointer to the timer to be cancel.
7455**
7456** OUTPUT:
7457**
7458** Nothing.
7459*/
7460gceSTATUS
7461gckOS_StopTimer(
7462 IN gckOS Os,
7463 IN gctPOINTER Timer
7464 )
7465{
7466 gcsOSTIMER_PTR timer;
7467 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
7468
7469 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7470 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
7471
7472 timer = (gcsOSTIMER_PTR)Timer;
7473
7474 cancel_delayed_work(&timer->work);
7475
7476 gcmkFOOTER_NO();
7477 return gcvSTATUS_OK;
7478}
7479
7480gceSTATUS
7481gckOS_GetProcessNameByPid(
7482 IN gctINT Pid,
7483 IN gctSIZE_T Length,
7484 OUT gctUINT8_PTR String
7485 )
7486{
7487 struct task_struct *task;
7488
7489 /* Get the task_struct of the task with pid. */
7490 rcu_read_lock();
7491
7492 task = FIND_TASK_BY_PID(Pid);
7493
7494 if (task == gcvNULL)
7495 {
7496 rcu_read_unlock();
7497 return gcvSTATUS_NOT_FOUND;
7498 }
7499
7500 /* Get name of process. */
7501 strncpy(String, task->comm, Length);
7502
7503 rcu_read_unlock();
7504
7505 return gcvSTATUS_OK;
7506}
7507
7508gceSTATUS
7509gckOS_DumpCallStack(
7510 IN gckOS Os
7511 )
7512{
7513 gcmkHEADER_ARG("Os=0x%X", Os);
7514
7515 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7516
7517 dump_stack();
7518
7519 gcmkFOOTER_NO();
7520 return gcvSTATUS_OK;
7521}
7522
7523/*******************************************************************************
7524**
7525** gckOS_DetectProcessByName
7526**
7527** task->comm maybe part of process name, so this function
7528** can only be used for debugging.
7529**
7530** INPUT:
7531**
7532** gctCONST_POINTER Name
7533** Pointer to a string to hold name to be check. If the length
7534** of name is longer than TASK_COMM_LEN (16), use part of name
7535** to detect.
7536**
7537** OUTPUT:
7538**
7539** gcvSTATUS_TRUE if name of current process matches Name.
7540**
7541*/
7542gceSTATUS
7543gckOS_DetectProcessByName(
7544 IN gctCONST_POINTER Name
7545 )
7546{
7547 char comm[sizeof(current->comm)];
7548
7549 memset(comm, 0, sizeof(comm));
7550
7551 gcmkVERIFY_OK(
7552 gckOS_GetProcessNameByPid(_GetProcessID(), sizeof(current->comm), comm));
7553
7554 return strstr(comm, Name) ? gcvSTATUS_TRUE
7555 : gcvSTATUS_FALSE;
7556}
7557
7558#if gcdANDROID_NATIVE_FENCE_SYNC
7559
7560gceSTATUS
7561gckOS_CreateSyncPoint(
7562 IN gckOS Os,
7563 OUT gctSYNC_POINT * SyncPoint
7564 )
7565{
7566 gceSTATUS status;
7567 gcsSYNC_POINT_PTR syncPoint;
7568
7569 gcmkHEADER_ARG("Os=0x%X", Os);
7570
7571 /* Verify the arguments. */
7572 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7573
7574 /* Create an sync point structure. */
7575 syncPoint = (gcsSYNC_POINT_PTR) kmalloc(
7576 sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN);
7577
7578 if (syncPoint == gcvNULL)
7579 {
7580 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7581 }
7582
7583 /* Initialize the sync point. */
7584 atomic_set(&syncPoint->ref, 1);
7585 atomic_set(&syncPoint->state, 0);
7586
7587 gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id));
7588
7589 *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id;
7590
7591 gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id);
7592 return gcvSTATUS_OK;
7593
7594OnError:
7595 if (syncPoint != gcvNULL)
7596 {
7597 kfree(syncPoint);
7598 }
7599
7600 gcmkFOOTER();
7601 return status;
7602}
7603
7604gceSTATUS
7605gckOS_ReferenceSyncPoint(
7606 IN gckOS Os,
7607 IN gctSYNC_POINT SyncPoint
7608 )
7609{
7610 gceSTATUS status;
7611 gcsSYNC_POINT_PTR syncPoint;
7612
7613 gcmkHEADER_ARG("Os=0x%X", Os);
7614
7615 /* Verify the arguments. */
7616 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7617 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
7618
7619 gcmkONERROR(
7620 _QueryIntegerId(&Os->syncPointDB,
7621 (gctUINT32)(gctUINTPTR_T)SyncPoint,
7622 (gctPOINTER)&syncPoint));
7623
7624 /* Initialize the sync point. */
7625 atomic_inc(&syncPoint->ref);
7626
7627 gcmkFOOTER_NO();
7628 return gcvSTATUS_OK;
7629
7630OnError:
7631 gcmkFOOTER();
7632 return status;
7633}
7634
7635gceSTATUS
7636gckOS_DestroySyncPoint(
7637 IN gckOS Os,
7638 IN gctSYNC_POINT SyncPoint
7639 )
7640{
7641 gceSTATUS status;
7642 gcsSYNC_POINT_PTR syncPoint;
7643 gctBOOL acquired = gcvFALSE;
7644
7645 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
7646
7647 /* Verify the arguments. */
7648 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7649 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
7650
7651 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
7652 acquired = gcvTRUE;
7653
7654 gcmkONERROR(
7655 _QueryIntegerId(&Os->syncPointDB,
7656 (gctUINT32)(gctUINTPTR_T)SyncPoint,
7657 (gctPOINTER)&syncPoint));
7658
7659 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
7660
7661 if (atomic_dec_and_test(&syncPoint->ref))
7662 {
7663 gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id));
7664
7665 /* Free the sgianl. */
7666 syncPoint->timeline = gcvNULL;
7667 kfree(syncPoint);
7668 }
7669
7670 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
7671 acquired = gcvFALSE;
7672
7673 /* Success. */
7674 gcmkFOOTER_NO();
7675 return gcvSTATUS_OK;
7676
7677OnError:
7678 if (acquired)
7679 {
7680 /* Release the mutex. */
7681 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
7682 }
7683
7684 gcmkFOOTER();
7685 return status;
7686}
7687
7688gceSTATUS
7689gckOS_SignalSyncPoint(
7690 IN gckOS Os,
7691 IN gctSYNC_POINT SyncPoint
7692 )
7693{
7694 gceSTATUS status;
7695 gcsSYNC_POINT_PTR syncPoint;
7696 struct sync_timeline * timeline;
7697 gctBOOL acquired = gcvFALSE;
7698
7699 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
7700
7701 /* Verify the arguments. */
7702 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7703 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
7704
7705 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
7706 acquired = gcvTRUE;
7707
7708 gcmkONERROR(
7709 _QueryIntegerId(&Os->syncPointDB,
7710 (gctUINT32)(gctUINTPTR_T)SyncPoint,
7711 (gctPOINTER)&syncPoint));
7712
7713 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
7714
7715 /* Set signaled state. */
7716 atomic_set(&syncPoint->state, 1);
7717
7718 /* Get parent timeline. */
7719 timeline = syncPoint->timeline;
7720
7721 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
7722 acquired = gcvFALSE;
7723
7724 /* Signal timeline. */
7725 if (timeline)
7726 {
7727 sync_timeline_signal(timeline);
7728 }
7729
7730 /* Success. */
7731 gcmkFOOTER_NO();
7732 return gcvSTATUS_OK;
7733
7734OnError:
7735 if (acquired)
7736 {
7737 /* Release the mutex. */
7738 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
7739 }
7740
7741 gcmkFOOTER();
7742 return status;
7743}
7744
7745gceSTATUS
7746gckOS_QuerySyncPoint(
7747 IN gckOS Os,
7748 IN gctSYNC_POINT SyncPoint,
7749 OUT gctBOOL_PTR State
7750 )
7751{
7752 gceSTATUS status;
7753 gcsSYNC_POINT_PTR syncPoint;
7754
7755 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
7756
7757 /* Verify the arguments. */
7758 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7759 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
7760
7761 gcmkONERROR(
7762 _QueryIntegerId(&Os->syncPointDB,
7763 (gctUINT32)(gctUINTPTR_T)SyncPoint,
7764 (gctPOINTER)&syncPoint));
7765
7766 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
7767
7768 /* Get state. */
7769 *State = atomic_read(&syncPoint->state);
7770
7771 /* Success. */
7772 gcmkFOOTER_ARG("*State=%d", *State);
7773 return gcvSTATUS_OK;
7774
7775OnError:
7776 gcmkFOOTER();
7777 return status;
7778}
7779
7780gceSTATUS
7781gckOS_CreateSyncTimeline(
7782 IN gckOS Os,
7783 OUT gctHANDLE * Timeline
7784 )
7785{
7786 struct viv_sync_timeline * timeline;
7787
7788 /* Create viv sync timeline. */
7789 timeline = viv_sync_timeline_create("viv timeline", Os);
7790
7791 if (timeline == gcvNULL)
7792 {
7793 /* Out of memory. */
7794 return gcvSTATUS_OUT_OF_MEMORY;
7795 }
7796
7797 *Timeline = (gctHANDLE) timeline;
7798 return gcvSTATUS_OK;
7799}
7800
7801gceSTATUS
7802gckOS_DestroySyncTimeline(
7803 IN gckOS Os,
7804 IN gctHANDLE Timeline
7805 )
7806{
7807 struct viv_sync_timeline * timeline;
7808 gcmkASSERT(Timeline != gcvNULL);
7809
7810 /* Destroy timeline. */
7811 timeline = (struct viv_sync_timeline *) Timeline;
7812 sync_timeline_destroy(&timeline->obj);
7813
7814 return gcvSTATUS_OK;
7815}
7816
7817gceSTATUS
7818gckOS_CreateNativeFence(
7819 IN gckOS Os,
7820 IN gctHANDLE Timeline,
7821 IN gctSYNC_POINT SyncPoint,
7822 OUT gctINT * FenceFD
7823 )
7824{
7825 int fd = -1;
7826 struct viv_sync_timeline *timeline;
7827 struct sync_pt * pt = gcvNULL;
7828 struct sync_fence * fence;
7829 char name[32];
7830 gcsSYNC_POINT_PTR syncPoint;
7831 gceSTATUS status;
7832
7833 gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d",
7834 Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint);
7835
7836 gcmkONERROR(
7837 _QueryIntegerId(&Os->syncPointDB,
7838 (gctUINT32)(gctUINTPTR_T)SyncPoint,
7839 (gctPOINTER)&syncPoint));
7840
7841 /* Cast timeline. */
7842 timeline = (struct viv_sync_timeline *) Timeline;
7843
7844 fd = get_unused_fd();
7845
7846 if (fd < 0)
7847 {
7848 /* Out of resources. */
7849 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
7850 }
7851
7852 /* Create viv_sync_pt. */
7853 pt = viv_sync_pt_create(timeline, SyncPoint);
7854
7855 if (pt == gcvNULL)
7856 {
7857 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7858 }
7859
7860 /* Reference sync_timeline. */
7861 syncPoint->timeline = &timeline->obj;
7862
7863 /* Build fence name. */
7864 snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint);
7865
7866 /* Create sync_fence. */
7867 fence = sync_fence_create(name, pt);
7868
7869 if (fence == NULL)
7870 {
7871 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7872 }
7873
7874 /* Install fence to fd. */
7875 sync_fence_install(fence, fd);
7876
7877 *FenceFD = fd;
7878 gcmkFOOTER_ARG("*FenceFD=%d", fd);
7879 return gcvSTATUS_OK;
7880
7881OnError:
7882 /* Error roll back. */
7883 if (pt)
7884 {
7885 sync_pt_free(pt);
7886 }
7887
7888 if (fd > 0)
7889 {
7890 put_unused_fd(fd);
7891 }
7892
7893 gcmkFOOTER();
7894 return status;
7895}
7896
7897gceSTATUS
7898gckOS_WaitNativeFence(
7899 IN gckOS Os,
7900 IN gctHANDLE Timeline,
7901 IN gctINT FenceFD,
7902 IN gctUINT32 Timeout
7903 )
7904{
7905 struct sync_timeline * timeline;
7906 struct list_head *pos;
7907 struct sync_fence * fence;
7908 gctBOOL wait = gcvFALSE;
7909 gceSTATUS status = gcvSTATUS_OK;
7910
7911 gcmkHEADER_ARG("Os=0x%X Timeline=0x%X FenceFD=%d Timeout=%u",
7912 Os, Timeline, FenceFD, Timeout);
7913
7914 /* Get shortcut. */
7915 timeline = (struct sync_timeline *) Timeline;
7916
7917 /* Get sync fence. */
7918 fence = sync_fence_fdget(FenceFD);
7919
7920 if (!fence)
7921 {
7922 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7923 }
7924
7925 list_for_each(pos, &fence->pt_list_head)
7926 {
7927 struct sync_pt * pt =
7928 container_of(pos, struct sync_pt, pt_list);
7929
7930 /* Do not need to wait on same timeline. */
7931 if (pt->parent != timeline)
7932 {
7933 wait = gcvTRUE;
7934 break;
7935 }
7936 }
7937
7938 if (wait)
7939 {
7940 int err;
7941 long timeout = (Timeout == gcvINFINITE) ? - 1 : (long) Timeout;
7942 err = sync_fence_wait(fence, timeout);
7943
7944 switch (err)
7945 {
7946 case 0:
7947 break;
7948 case -ETIME:
7949 status = gcvSTATUS_TIMEOUT;
7950 break;
7951 default:
7952 gcmkONERROR(gcvSTATUS_GENERIC_IO);
7953 }
7954 }
7955
7956 /* Put the fence. */
7957 sync_fence_put(fence);
7958
7959OnError:
7960 gcmkFOOTER();
7961 return status;
7962}
7963#endif
7964
7965
7966gceSTATUS
7967gckOS_CPUPhysicalToGPUPhysical(
7968 IN gckOS Os,
7969 IN gctPHYS_ADDR_T CPUPhysical,
7970 IN gctPHYS_ADDR_T * GPUPhysical
7971 )
7972{
7973 gcsPLATFORM * platform;
7974 gcmkHEADER_ARG("CPUPhysical=0x%X", CPUPhysical);
7975
7976 platform = Os->device->platform;
7977
7978 if (platform && platform->ops->getGPUPhysical)
7979 {
7980 gcmkVERIFY_OK(
7981 platform->ops->getGPUPhysical(platform, CPUPhysical, GPUPhysical));
7982 }
7983 else
7984 {
7985 *GPUPhysical = CPUPhysical;
7986 }
7987
7988 gcmkFOOTER_NO();
7989 return gcvSTATUS_OK;
7990}
7991
7992gceSTATUS
7993gckOS_GPUPhysicalToCPUPhysical(
7994 IN gckOS Os,
7995 IN gctUINT32 GPUPhysical,
7996 IN gctUINT32_PTR CPUPhysical
7997 )
7998{
7999 gcmkHEADER_ARG("GPUPhysical=0x%X", GPUPhysical);
8000
8001 *CPUPhysical = GPUPhysical;
8002
8003 gcmkFOOTER_NO();
8004 return gcvSTATUS_OK;
8005}
8006
8007gceSTATUS
8008gckOS_PhysicalToPhysicalAddress(
8009 IN gckOS Os,
8010 IN gctPOINTER Physical,
8011 OUT gctPHYS_ADDR_T * PhysicalAddress
8012 )
8013{
8014 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
8015 gckALLOCATOR allocator = mdl->allocator;
8016
8017 if (allocator)
8018 {
8019 return allocator->ops->Physical(allocator, mdl, 0, PhysicalAddress);
8020 }
8021
8022 return gcvSTATUS_NOT_SUPPORTED;
8023}
8024
8025gceSTATUS
8026gckOS_QueryOption(
8027 IN gckOS Os,
8028 IN gctCONST_STRING Option,
8029 OUT gctUINT32 * Value
8030 )
8031{
8032 gckGALDEVICE device = Os->device;
8033
8034 if (!strcmp(Option, "physBase"))
8035 {
8036 *Value = device->physBase;
8037 return gcvSTATUS_OK;
8038 }
8039 else if (!strcmp(Option, "physSize"))
8040 {
8041 *Value = device->physSize;
8042 return gcvSTATUS_OK;
8043 }
8044 else if (!strcmp(Option, "mmu"))
8045 {
8046 *Value = device->mmu;
8047 return gcvSTATUS_OK;
8048 }
8049 else if (!strcmp(Option, "contiguousSize"))
8050 {
8051 *Value = device->contiguousSize;
8052 return gcvSTATUS_OK;
8053 }
8054
8055 return gcvSTATUS_NOT_SUPPORTED;
8056}
8057
8058static int
8059fd_release(
8060 struct inode *inode,
8061 struct file *file
8062 )
8063{
8064 gcsFDPRIVATE_PTR private = (gcsFDPRIVATE_PTR)file->private_data;
8065
8066 if (private && private->release)
8067 {
8068 return private->release(private);
8069 }
8070
8071 return 0;
8072}
8073
8074static const struct file_operations fd_fops = {
8075 .release = fd_release,
8076};
8077
8078gceSTATUS
8079gckOS_GetFd(
8080 IN gctSTRING Name,
8081 IN gcsFDPRIVATE_PTR Private,
8082 OUT gctINT *Fd
8083 )
8084{
8085#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
8086 *Fd = anon_inode_getfd(Name, &fd_fops, Private, O_RDWR);
8087
8088 if (*Fd < 0)
8089 {
8090 return gcvSTATUS_OUT_OF_RESOURCES;
8091 }
8092
8093 return gcvSTATUS_OK;
8094#else
8095 return gcvSTATUS_NOT_SUPPORTED;
8096#endif
8097}
8098
8099/*******************************************************************************
8100**
8101** gckOS_WrapMemory
8102**
8103** Import a number of pages allocated by other allocator.
8104**
8105** INPUT:
8106**
8107** gckOS Os
8108** Pointer to an gckOS object.
8109**
8110** gctUINT32 Flag
8111** Memory type.
8112**
8113** OUTPUT:
8114**
8115** gctSIZE_T * Bytes
8116** Pointer to a variable that hold the number of bytes allocated.
8117**
8118** gctPHYS_ADDR * Physical
8119** Pointer to a variable that will hold the physical address of the
8120** allocation.
8121*/
8122gceSTATUS
8123gckOS_WrapMemory(
8124 IN gckOS Os,
8125 IN gcsUSER_MEMORY_DESC_PTR Desc,
8126 OUT gctSIZE_T *Bytes,
8127 OUT gctPHYS_ADDR * Physical
8128 )
8129{
8130 PLINUX_MDL mdl = gcvNULL;
8131 gceSTATUS status = gcvSTATUS_OUT_OF_MEMORY;
8132 gckALLOCATOR allocator;
8133 gcsATTACH_DESC desc;
8134 gctUINT32 flag;
8135
8136 gcmkHEADER_ARG("Os=0x%X ", Os);
8137
8138 /* Verify the arguments. */
8139 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8140 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
8141
8142 mdl = _CreateMdl();
8143 if (mdl == gcvNULL)
8144 {
8145 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8146 }
8147
8148 desc.handle = Desc->handle;
8149 desc.memory = gcmUINT64_TO_PTR(Desc->logical);
8150 desc.physical = Desc->physical;
8151 desc.size = Desc->size;
8152 flag = Desc->flag;
8153
8154 /* Walk all allocators. */
8155 list_for_each_entry(allocator, &Os->allocatorList, head)
8156 {
8157 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
8158 "%s(%d) Flag = %x allocator->capability = %x",
8159 __FUNCTION__, __LINE__, flag, allocator->capability);
8160
8161 if ((flag & allocator->capability) != flag)
8162 {
8163 status = gcvSTATUS_NOT_SUPPORTED;
8164 continue;
8165 }
8166
8167 status = allocator->ops->Attach(allocator, &desc, mdl);
8168
8169 if (gcmIS_SUCCESS(status))
8170 {
8171 mdl->allocator = allocator;
8172 break;
8173 }
8174 }
8175
8176 /* Check status. */
8177 gcmkONERROR(status);
8178
8179 mdl->dmaHandle = 0;
8180 mdl->addr = 0;
8181 mdl->pagedMem = 1;
8182
8183 *Bytes = mdl->numPages * PAGE_SIZE;
8184
8185 /* Return physical address. */
8186 *Physical = (gctPHYS_ADDR) mdl;
8187
8188 MEMORY_LOCK(Os);
8189
8190 /*
8191 * Add this to a global list.
8192 * Will be used by get physical address
8193 * and mapuser pointer functions.
8194 */
8195 if (!Os->mdlHead)
8196 {
8197 /* Initialize the queue. */
8198 Os->mdlHead = Os->mdlTail = mdl;
8199 }
8200 else
8201 {
8202 /* Add to tail. */
8203 mdl->prev = Os->mdlTail;
8204 Os->mdlTail->next = mdl;
8205 Os->mdlTail = mdl;
8206 }
8207
8208 MEMORY_UNLOCK(Os);
8209
8210 /* Success. */
8211 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
8212 return gcvSTATUS_OK;
8213
8214OnError:
8215 if (mdl != gcvNULL)
8216 {
8217 /* Free the memory. */
8218 _DestroyMdl(mdl);
8219 }
8220
8221 /* Return the status. */
8222 gcmkFOOTER();
8223 return status;
8224}
8225
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_os.h b/src/hal/os/linux/kernel/gc_hal_kernel_os.h
new file mode 100755
index 0000000..692a5a8
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_os.h
@@ -0,0 +1,124 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_os_h_
57#define __gc_hal_kernel_os_h_
58
59typedef struct _LINUX_MDL_MAP
60{
61 gctINT pid;
62 gctPOINTER vmaAddr;
63 gctUINT32 count;
64 struct vm_area_struct * vma;
65 struct _LINUX_MDL_MAP * next;
66}
67LINUX_MDL_MAP;
68
69typedef struct _LINUX_MDL_MAP * PLINUX_MDL_MAP;
70
71typedef struct _LINUX_MDL
72{
73 char * addr;
74
75 union _pages
76 {
77 /* Pointer to a array of pages. */
78 struct page * contiguousPages;
79 /* Pointer to a array of pointers to page. */
80 struct page ** nonContiguousPages;
81 }
82 u;
83
84#ifdef NO_DMA_COHERENT
85 gctPOINTER kaddr;
86#endif /* NO_DMA_COHERENT */
87
88 gctINT numPages;
89 gctINT pagedMem;
90 gctBOOL contiguous;
91#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
92 gctBOOL exact;
93#endif
94 dma_addr_t dmaHandle;
95 PLINUX_MDL_MAP maps;
96 struct _LINUX_MDL * prev;
97 struct _LINUX_MDL * next;
98
99 /* Pointer to allocator which allocates memory for this mdl. */
100 void * allocator;
101
102 /* Private data used by allocator. */
103 void * priv;
104
105 uint gid;
106}
107LINUX_MDL, *PLINUX_MDL;
108
109extern PLINUX_MDL_MAP
110FindMdlMap(
111 IN PLINUX_MDL Mdl,
112 IN gctINT PID
113 );
114
115typedef struct _DRIVER_ARGS
116{
117 gctUINT64 InputBuffer;
118 gctUINT64 InputBufferSize;
119 gctUINT64 OutputBuffer;
120 gctUINT64 OutputBufferSize;
121}
122DRIVER_ARGS;
123
124#endif /* __gc_hal_kernel_os_h_ */
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_platform.h b/src/hal/os/linux/kernel/gc_hal_kernel_platform.h
new file mode 100755
index 0000000..bf19409
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_platform.h
@@ -0,0 +1,342 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef _gc_hal_kernel_platform_h_
57#define _gc_hal_kernel_platform_h_
58#include <linux/mm.h>
59
60typedef struct _gcsMODULE_PARAMETERS
61{
62#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
63 gctINT irqLine3D0;
64 gctUINT registerMemBase3D0;
65 gctUINT registerMemSize3D0;
66 gctINT irqLine3D1;
67 gctUINT registerMemBase3D1;
68 gctUINT registerMemSize3D1;
69#else
70 gctINT irqLine;
71 gctUINT registerMemBase;
72 gctUINT registerMemSize;
73#endif
74 gctINT irqLine2D;
75 gctUINT registerMemBase2D;
76 gctUINT registerMemSize2D;
77 gctINT irqLineVG;
78 gctUINT registerMemBaseVG;
79 gctUINT registerMemSizeVG;
80 gctUINT contiguousSize;
81 gctUINT contiguousBase;
82 gctUINT contiguousRequested;
83 gctUINT bankSize;
84 gctINT fastClear;
85 gctINT compression;
86 gctINT powerManagement;
87 gctINT gpuProfiler;
88 gctINT signal;
89 gctUINT baseAddress;
90 gctUINT physSize;
91 gctUINT logFileSize;
92 gctUINT recovery;
93 gctUINT stuckDump;
94 gctUINT showArgs;
95 gctUINT gpu3DMinClock;
96 gctBOOL registerMemMapped;
97 gctPOINTER registerMemAddress;
98}
99gcsMODULE_PARAMETERS;
100
101typedef struct _gcsPLATFORM * gckPLATFORM;
102
103typedef struct _gcsPLATFORM_OPERATIONS
104{
105 /*******************************************************************************
106 **
107 ** needAddDevice
108 **
109 ** Determine whether platform_device is created by initialization code.
110 ** If platform_device is created by BSP, return gcvFLASE here.
111 */
112 gctBOOL
113 (*needAddDevice)(
114 IN gckPLATFORM Platform
115 );
116
117 /*******************************************************************************
118 **
119 ** adjustParam
120 **
121 ** Override content of arguments, if a argument is not changed here, it will
122 ** keep as default value or value set by insmod command line.
123 */
124 gceSTATUS
125 (*adjustParam)(
126 IN gckPLATFORM Platform,
127 OUT gcsMODULE_PARAMETERS *Args
128 );
129
130 /*******************************************************************************
131 **
132 ** adjustDriver
133 **
134 ** Override content of platform_driver which will be registered.
135 */
136 gceSTATUS
137 (*adjustDriver)(
138 IN gckPLATFORM Platform
139 );
140
141 /*******************************************************************************
142 **
143 ** getPower
144 **
145 ** Prepare power and clock operation.
146 */
147 gceSTATUS
148 (*getPower)(
149 IN gckPLATFORM Platform
150 );
151
152 /*******************************************************************************
153 **
154 ** putPower
155 **
156 ** Finish power and clock operation.
157 */
158 gceSTATUS
159 (*putPower)(
160 IN gckPLATFORM Platform
161 );
162
163 /*******************************************************************************
164 **
165 ** allocPriv
166 **
167 ** Construct platform private data.
168 */
169 gceSTATUS
170 (*allocPriv)(
171 IN gckPLATFORM Platform
172 );
173
174 /*******************************************************************************
175 **
176 ** freePriv
177 **
178 ** free platform private data.
179 */
180 gceSTATUS
181 (*freePriv)(
182 IN gckPLATFORM Platform
183 );
184
185 /*******************************************************************************
186 **
187 ** setPower
188 **
189 ** Set power state of specified GPU.
190 **
191 ** INPUT:
192 **
193 ** gceCORE GPU
194 ** GPU neeed to config.
195 **
196 ** gceBOOL Enable
197 ** Enable or disable power.
198 */
199 gceSTATUS
200 (*setPower)(
201 IN gckPLATFORM Platform,
202 IN gceCORE GPU,
203 IN gctBOOL Enable
204 );
205
206 /*******************************************************************************
207 **
208 ** setClock
209 **
210 ** Set clock state of specified GPU.
211 **
212 ** INPUT:
213 **
214 ** gceCORE GPU
215 ** GPU neeed to config.
216 **
217 ** gceBOOL Enable
218 ** Enable or disable clock.
219 */
220 gceSTATUS
221 (*setClock)(
222 IN gckPLATFORM Platform,
223 IN gceCORE GPU,
224 IN gctBOOL Enable
225 );
226
227 /*******************************************************************************
228 **
229 ** reset
230 **
231 ** Reset GPU outside.
232 **
233 ** INPUT:
234 **
235 ** gceCORE GPU
236 ** GPU neeed to reset.
237 */
238 gceSTATUS
239 (*reset)(
240 IN gckPLATFORM Platform,
241 IN gceCORE GPU
242 );
243
244 /*******************************************************************************
245 **
246 ** getGPUPhysical
247 **
248 ** Convert CPU physical address to GPU physical address if they are
249 ** different.
250 */
251 gceSTATUS
252 (*getGPUPhysical)(
253 IN gckPLATFORM Platform,
254 IN gctPHYS_ADDR_T CPUPhysical,
255 OUT gctPHYS_ADDR_T * GPUPhysical
256 );
257
258 /*******************************************************************************
259 **
260 ** adjustProt
261 **
262 ** Override Prot flag when mapping paged memory to userspace.
263 */
264 gceSTATUS
265 (*adjustProt)(
266 IN struct vm_area_struct * vma
267 );
268
269 /*******************************************************************************
270 **
271 ** shrinkMemory
272 **
273 ** Do something to collect memory, eg, act as oom killer.
274 */
275 gceSTATUS
276 (*shrinkMemory)(
277 IN gckPLATFORM Platform
278 );
279
280 /*******************************************************************************
281 **
282 ** cache
283 **
284 ** Cache operation.
285 */
286 gceSTATUS
287 (*cache)(
288 IN gckPLATFORM Platform,
289 IN gctUINT32 ProcessID,
290 IN gctPHYS_ADDR Handle,
291 IN gctUINT32 Physical,
292 IN gctPOINTER Logical,
293 IN gctSIZE_T Bytes,
294 IN gceCACHEOPERATION Operation
295 );
296
297 /*******************************************************************************
298 **
299 ** name
300 **
301 ** Get name of platform code.
302 **
303 ** There is a helper macro gcmkPLATFORM_Name which defines a default callback
304 ** function _Name() which uses code path as name.
305 */
306 gceSTATUS
307 (*name)(
308 IN gckPLATFORM Platform,
309 IN gctCONST_STRING * Name
310 );
311
312}
313gcsPLATFORM_OPERATIONS;
314
315typedef struct _gcsPLATFORM
316{
317 struct platform_device* device;
318 struct platform_driver* driver;
319
320 gcsPLATFORM_OPERATIONS* ops;
321
322 void* priv;
323}
324gcsPLATFORM;
325
326void
327gckPLATFORM_QueryOperations(
328 IN gcsPLATFORM_OPERATIONS ** Operations
329 );
330
331#define gcmkPLATFROM_Name \
332static gceSTATUS \
333_Name( \
334 IN gckPLATFORM Platform, \
335 IN gctCONST_STRING * Name \
336 ) \
337{ \
338 * Name = __FILE__; \
339 return gcvSTATUS_OK; \
340} \
341
342#endif
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_probe.c b/src/hal/os/linux/kernel/gc_hal_kernel_probe.c
new file mode 100755
index 0000000..473a266
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_probe.c
@@ -0,0 +1,1361 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include <linux/device.h>
57#include <linux/slab.h>
58
59#include "gc_hal_kernel_linux.h"
60#include "gc_hal_driver.h"
61
62#if USE_PLATFORM_DRIVER
63# include <linux/platform_device.h>
64#endif
65
66#ifdef CONFIG_PXA_DVFM
67# include <mach/dvfm.h>
68# include <mach/pxa3xx_dvfm.h>
69#endif
70
71
72/* Zone used for header/footer. */
73#define _GC_OBJ_ZONE gcvZONE_DRIVER
74
75MODULE_DESCRIPTION("Vivante Graphics Driver");
76MODULE_LICENSE("GPL");
77
78static struct class* gpuClass;
79
80static gcsPLATFORM platform;
81
82static gckGALDEVICE galDevice;
83
84static uint major = 199;
85module_param(major, uint, 0644);
86
87#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
88static int irqLine3D0 = -1;
89module_param(irqLine3D0, int, 0644);
90
91static ulong registerMemBase3D0 = 0;
92module_param(registerMemBase3D0, ulong, 0644);
93
94static ulong registerMemSize3D0 = 2 << 10;
95module_param(registerMemSize3D0, ulong, 0644);
96
97static int irqLine3D1 = -1;
98module_param(irqLine3D1, int, 0644);
99
100static ulong registerMemBase3D1 = 0;
101module_param(registerMemBase3D1, ulong, 0644);
102
103static ulong registerMemSize3D1 = 2 << 10;
104module_param(registerMemSize3D1, ulong, 0644);
105#else
106static int irqLine = -1;
107module_param(irqLine, int, 0644);
108
109static ulong registerMemBase = 0x80000000;
110module_param(registerMemBase, ulong, 0644);
111
112static ulong registerMemSize = 2 << 10;
113module_param(registerMemSize, ulong, 0644);
114#endif
115
116static int irqLine2D = -1;
117module_param(irqLine2D, int, 0644);
118
119static ulong registerMemBase2D = 0x00000000;
120module_param(registerMemBase2D, ulong, 0644);
121
122static ulong registerMemSize2D = 2 << 10;
123module_param(registerMemSize2D, ulong, 0644);
124
125static int irqLineVG = -1;
126module_param(irqLineVG, int, 0644);
127
128static ulong registerMemBaseVG = 0x00000000;
129module_param(registerMemBaseVG, ulong, 0644);
130
131static ulong registerMemSizeVG = 2 << 10;
132module_param(registerMemSizeVG, ulong, 0644);
133
134#if gcdENABLE_DEC_COMPRESSION
135static ulong registerMemBaseDEC300 = 0x00000000;
136module_param(registerMemBaseDEC300, ulong, 0644);
137
138static ulong registerMemSizeDEC300 = 2 << 10;
139module_param(registerMemSizeDEC300, ulong, 0644);
140#endif
141
142#ifndef gcdDEFAULT_CONTIGUOUS_SIZE
143#define gcdDEFAULT_CONTIGUOUS_SIZE (4 << 20)
144#endif
145static ulong contiguousSize = gcdDEFAULT_CONTIGUOUS_SIZE;
146module_param(contiguousSize, ulong, 0644);
147
148static ulong contiguousBase = 0;
149module_param(contiguousBase, ulong, 0644);
150
151static ulong bankSize = 0;
152module_param(bankSize, ulong, 0644);
153
154static int fastClear = -1;
155module_param(fastClear, int, 0644);
156
157static int compression = -1;
158module_param(compression, int, 0644);
159
160static int powerManagement = 1;
161module_param(powerManagement, int, 0644);
162
163static int gpuProfiler = 0;
164module_param(gpuProfiler, int, 0644);
165
166static int signal = 48;
167module_param(signal, int, 0644);
168
169static ulong baseAddress = 0;
170module_param(baseAddress, ulong, 0644);
171
172static ulong physSize = 0;
173module_param(physSize, ulong, 0644);
174
175static uint logFileSize = 0;
176module_param(logFileSize,uint, 0644);
177
178static uint recovery = 1;
179module_param(recovery, uint, 0644);
180MODULE_PARM_DESC(recovery, "Recover GPU from stuck (1: Enable, 0: Disable)");
181
182/* Middle needs about 40KB buffer, Maximal may need more than 200KB buffer. */
183static uint stuckDump = 0;
184module_param(stuckDump, uint, 0644);
185MODULE_PARM_DESC(stuckDump, "Level of stuck dump content (1: Minimal, 2: Middle, 3: Maximal)");
186
187static int showArgs = 0;
188module_param(showArgs, int, 0644);
189
190static int mmu = 1;
191module_param(mmu, int, 0644);
192
193static int gpu3DMinClock = 1;
194
195static int contiguousRequested = 0;
196
197
198static gctBOOL registerMemMapped = gcvFALSE;
199static gctPOINTER registerMemAddress = gcvNULL;
200
201static int drv_open(
202 struct inode* inode,
203 struct file* filp
204 );
205
206static int drv_release(
207 struct inode* inode,
208 struct file* filp
209 );
210
211static long drv_ioctl(
212 struct file* filp,
213 unsigned int ioctlCode,
214 unsigned long arg
215 );
216
217static int drv_mmap(
218 struct file* filp,
219 struct vm_area_struct* vma
220 );
221
222static struct file_operations driver_fops =
223{
224 .owner = THIS_MODULE,
225 .open = drv_open,
226 .release = drv_release,
227 .unlocked_ioctl = drv_ioctl,
228#ifdef HAVE_COMPAT_IOCTL
229 .compat_ioctl = drv_ioctl,
230#endif
231 .mmap = drv_mmap,
232};
233
234void
235_UpdateModuleParam(
236 gcsMODULE_PARAMETERS *Param
237 )
238{
239#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
240#else
241 irqLine = Param->irqLine ;
242 registerMemBase = Param->registerMemBase;
243 registerMemSize = Param->registerMemSize;
244#endif
245 irqLine2D = Param->irqLine2D ;
246 registerMemBase2D = Param->registerMemBase2D;
247 registerMemSize2D = Param->registerMemSize2D;
248 contiguousSize = Param->contiguousSize;
249 contiguousBase = Param->contiguousBase;
250 bankSize = Param->bankSize;
251 fastClear = Param->fastClear;
252 compression = Param->compression;
253 powerManagement = Param->powerManagement;
254 gpuProfiler = Param->gpuProfiler;
255 signal = Param->signal;
256 baseAddress = Param->baseAddress;
257 physSize = Param->physSize;
258 logFileSize = Param->logFileSize;
259 recovery = Param->recovery;
260 stuckDump = Param->stuckDump;
261 showArgs = Param->showArgs;
262 contiguousRequested = Param->contiguousRequested;
263 gpu3DMinClock = Param->gpu3DMinClock;
264 registerMemMapped = Param->registerMemMapped;
265 registerMemAddress = Param->registerMemAddress;
266}
267
268void
269gckOS_DumpParam(
270 void
271 )
272{
273 printk("Galcore options:\n");
274#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
275 printk(" irqLine3D0 = %d\n", irqLine3D0);
276 printk(" registerMemBase3D0 = 0x%08lX\n", registerMemBase3D0);
277 printk(" registerMemSize3D0 = 0x%08lX\n", registerMemSize3D0);
278
279 if (irqLine3D1 != -1)
280 {
281 printk(" irqLine3D1 = %d\n", irqLine3D1);
282 printk(" registerMemBase3D1 = 0x%08lX\n", registerMemBase3D1);
283 printk(" registerMemSize3D1 = 0x%08lX\n", registerMemSize3D1);
284 }
285#else
286 printk(" irqLine = %d\n", irqLine);
287 printk(" registerMemBase = 0x%08lX\n", registerMemBase);
288 printk(" registerMemSize = 0x%08lX\n", registerMemSize);
289#endif
290
291 if (irqLine2D != -1)
292 {
293 printk(" irqLine2D = %d\n", irqLine2D);
294 printk(" registerMemBase2D = 0x%08lX\n", registerMemBase2D);
295 printk(" registerMemSize2D = 0x%08lX\n", registerMemSize2D);
296 }
297
298 if (irqLineVG != -1)
299 {
300 printk(" irqLineVG = %d\n", irqLineVG);
301 printk(" registerMemBaseVG = 0x%08lX\n", registerMemBaseVG);
302 printk(" registerMemSizeVG = 0x%08lX\n", registerMemSizeVG);
303 }
304
305#if gcdENABLE_DEC_COMPRESSION
306 printk(" registerMemBaseDEC300 = 0x%08lX\n", registerMemBaseDEC300);
307 printk(" registerMemSizeDEC300 = 0x%08lX\n", registerMemSizeDEC300);
308#endif
309
310 printk(" contiguousSize = %ld\n", contiguousSize);
311 printk(" contiguousBase = 0x%08lX\n", contiguousBase);
312 printk(" bankSize = 0x%08lX\n", bankSize);
313 printk(" fastClear = %d\n", fastClear);
314 printk(" compression = %d\n", compression);
315 printk(" signal = %d\n", signal);
316 printk(" powerManagement = %d\n", powerManagement);
317 printk(" baseAddress = 0x%08lX\n", baseAddress);
318 printk(" physSize = 0x%08lX\n", physSize);
319 printk(" logFileSize = %d KB \n", logFileSize);
320 printk(" recovery = %d\n", recovery);
321 printk(" stuckDump = %d\n", stuckDump);
322 printk(" gpuProfiler = %d\n", gpuProfiler);
323}
324
325int drv_open(
326 struct inode* inode,
327 struct file* filp
328 )
329{
330 gceSTATUS status;
331 gctBOOL attached = gcvFALSE;
332 gcsHAL_PRIVATE_DATA_PTR data = gcvNULL;
333 gctINT i;
334
335 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
336
337 if (filp == gcvNULL)
338 {
339 gcmkTRACE_ZONE(
340 gcvLEVEL_ERROR, gcvZONE_DRIVER,
341 "%s(%d): filp is NULL\n",
342 __FUNCTION__, __LINE__
343 );
344
345 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
346 }
347
348 data = kmalloc(sizeof(gcsHAL_PRIVATE_DATA), GFP_KERNEL | __GFP_NOWARN);
349
350 if (data == gcvNULL)
351 {
352 gcmkTRACE_ZONE(
353 gcvLEVEL_ERROR, gcvZONE_DRIVER,
354 "%s(%d): private_data is NULL\n",
355 __FUNCTION__, __LINE__
356 );
357
358 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
359 }
360
361 data->device = galDevice;
362 data->mappedMemory = gcvNULL;
363 data->contiguousLogical = gcvNULL;
364 gcmkONERROR(gckOS_GetProcessID(&data->pidOpen));
365
366 /* Attached the process. */
367 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
368 {
369 if (galDevice->kernels[i] != gcvNULL)
370 {
371 gcmkONERROR(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvTRUE));
372 }
373 }
374 attached = gcvTRUE;
375
376 if (!galDevice->contiguousMapped)
377 {
378 if (galDevice->contiguousPhysical != gcvNULL)
379 {
380 gcmkONERROR(gckOS_MapMemory(
381 galDevice->os,
382 galDevice->contiguousPhysical,
383 galDevice->contiguousSize,
384 &data->contiguousLogical
385 ));
386 }
387 }
388
389 filp->private_data = data;
390
391 /* Success. */
392 gcmkFOOTER_NO();
393 return 0;
394
395OnError:
396 if (data != gcvNULL)
397 {
398 if (data->contiguousLogical != gcvNULL)
399 {
400 gcmkVERIFY_OK(gckOS_UnmapMemory(
401 galDevice->os,
402 galDevice->contiguousPhysical,
403 galDevice->contiguousSize,
404 data->contiguousLogical
405 ));
406 }
407
408 kfree(data);
409 }
410
411 if (attached)
412 {
413 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
414 {
415 if (galDevice->kernels[i] != gcvNULL)
416 {
417 gcmkVERIFY_OK(gckKERNEL_AttachProcess(galDevice->kernels[i], gcvFALSE));
418 }
419 }
420 }
421
422 gcmkFOOTER();
423 return -ENOTTY;
424}
425
426int drv_release(
427 struct inode* inode,
428 struct file* filp
429 )
430{
431 gceSTATUS status;
432 gcsHAL_PRIVATE_DATA_PTR data;
433 gckGALDEVICE device;
434 gctINT i;
435
436 gcmkHEADER_ARG("inode=0x%08X filp=0x%08X", inode, filp);
437
438 if (filp == gcvNULL)
439 {
440 gcmkTRACE_ZONE(
441 gcvLEVEL_ERROR, gcvZONE_DRIVER,
442 "%s(%d): filp is NULL\n",
443 __FUNCTION__, __LINE__
444 );
445
446 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
447 }
448
449 data = filp->private_data;
450
451 if (data == gcvNULL)
452 {
453 gcmkTRACE_ZONE(
454 gcvLEVEL_ERROR, gcvZONE_DRIVER,
455 "%s(%d): private_data is NULL\n",
456 __FUNCTION__, __LINE__
457 );
458
459 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
460 }
461
462 device = data->device;
463
464 if (device == gcvNULL)
465 {
466 gcmkTRACE_ZONE(
467 gcvLEVEL_ERROR, gcvZONE_DRIVER,
468 "%s(%d): device is NULL\n",
469 __FUNCTION__, __LINE__
470 );
471
472 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
473 }
474
475 if (!device->contiguousMapped)
476 {
477 if (data->contiguousLogical != gcvNULL)
478 {
479 gcmkONERROR(gckOS_UnmapMemoryEx(
480 galDevice->os,
481 galDevice->contiguousPhysical,
482 galDevice->contiguousSize,
483 data->contiguousLogical,
484 data->pidOpen
485 ));
486
487 data->contiguousLogical = gcvNULL;
488 }
489 }
490
491 /* A process gets detached. */
492 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
493 {
494 if (galDevice->kernels[i] != gcvNULL)
495 {
496 gcmkONERROR(gckKERNEL_AttachProcessEx(galDevice->kernels[i], gcvFALSE, data->pidOpen));
497 }
498 }
499
500 kfree(data);
501 filp->private_data = NULL;
502
503 /* Success. */
504 gcmkFOOTER_NO();
505 return 0;
506
507OnError:
508 gcmkFOOTER();
509 return -ENOTTY;
510}
511
512long drv_ioctl(
513 struct file* filp,
514 unsigned int ioctlCode,
515 unsigned long arg
516 )
517{
518 gceSTATUS status;
519 gcsHAL_INTERFACE iface;
520 gctUINT32 copyLen;
521 DRIVER_ARGS drvArgs;
522 gckGALDEVICE device;
523 gcsHAL_PRIVATE_DATA_PTR data;
524 gctINT32 i, count;
525 gckVIDMEM_NODE nodeObject;
526
527 gcmkHEADER_ARG(
528 "filp=0x%08X ioctlCode=0x%08X arg=0x%08X",
529 filp, ioctlCode, arg
530 );
531
532 if (filp == gcvNULL)
533 {
534 gcmkTRACE_ZONE(
535 gcvLEVEL_ERROR, gcvZONE_DRIVER,
536 "%s(%d): filp is NULL\n",
537 __FUNCTION__, __LINE__
538 );
539
540 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
541 }
542
543 data = filp->private_data;
544
545 if (data == gcvNULL)
546 {
547 gcmkTRACE_ZONE(
548 gcvLEVEL_ERROR, gcvZONE_DRIVER,
549 "%s(%d): private_data is NULL\n",
550 __FUNCTION__, __LINE__
551 );
552
553 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
554 }
555
556 device = data->device;
557
558 if (device == gcvNULL)
559 {
560 gcmkTRACE_ZONE(
561 gcvLEVEL_ERROR, gcvZONE_DRIVER,
562 "%s(%d): device is NULL\n",
563 __FUNCTION__, __LINE__
564 );
565
566 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
567 }
568
569 if ((ioctlCode != IOCTL_GCHAL_INTERFACE)
570 && (ioctlCode != IOCTL_GCHAL_KERNEL_INTERFACE)
571 )
572 {
573 gcmkTRACE_ZONE(
574 gcvLEVEL_ERROR, gcvZONE_DRIVER,
575 "%s(%d): unknown command %d\n",
576 __FUNCTION__, __LINE__,
577 ioctlCode
578 );
579
580 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
581 }
582
583 /* Get the drvArgs. */
584 copyLen = copy_from_user(
585 &drvArgs, (void *) arg, sizeof(DRIVER_ARGS)
586 );
587
588 if (copyLen != 0)
589 {
590 gcmkTRACE_ZONE(
591 gcvLEVEL_ERROR, gcvZONE_DRIVER,
592 "%s(%d): error copying of the input arguments.\n",
593 __FUNCTION__, __LINE__
594 );
595
596 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
597 }
598
599 /* Now bring in the gcsHAL_INTERFACE structure. */
600 if ((drvArgs.InputBufferSize != sizeof(gcsHAL_INTERFACE))
601 || (drvArgs.OutputBufferSize != sizeof(gcsHAL_INTERFACE))
602 )
603 {
604 gcmkTRACE_ZONE(
605 gcvLEVEL_ERROR, gcvZONE_DRIVER,
606 "%s(%d): input or/and output structures are invalid.\n",
607 __FUNCTION__, __LINE__
608 );
609
610 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
611 }
612
613 copyLen = copy_from_user(
614 &iface, gcmUINT64_TO_PTR(drvArgs.InputBuffer), sizeof(gcsHAL_INTERFACE)
615 );
616
617 if (copyLen != 0)
618 {
619 gcmkTRACE_ZONE(
620 gcvLEVEL_ERROR, gcvZONE_DRIVER,
621 "%s(%d): error copying of input HAL interface.\n",
622 __FUNCTION__, __LINE__
623 );
624
625 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
626 }
627
628 if (iface.command == gcvHAL_CHIP_INFO)
629 {
630 count = 0;
631 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
632 {
633 if (device->kernels[i] != gcvNULL)
634 {
635 {
636 gcmkVERIFY_OK(gckHARDWARE_GetType(device->kernels[i]->hardware,
637 &iface.u.ChipInfo.types[count]));
638 }
639 count++;
640 }
641 }
642
643 iface.u.ChipInfo.count = count;
644 iface.status = status = gcvSTATUS_OK;
645 }
646 else
647 {
648 if (iface.hardwareType > 7)
649 {
650 gcmkTRACE_ZONE(
651 gcvLEVEL_ERROR, gcvZONE_DRIVER,
652 "%s(%d): unknown hardwareType %d\n",
653 __FUNCTION__, __LINE__,
654 iface.hardwareType
655 );
656
657 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
658 }
659
660 {
661 status = gckKERNEL_Dispatch(device->kernels[device->coreMapping[iface.hardwareType]],
662 (ioctlCode == IOCTL_GCHAL_INTERFACE),
663 &iface);
664 }
665 }
666
667 /* Redo system call after pending signal is handled. */
668 if (status == gcvSTATUS_INTERRUPTED)
669 {
670 gcmkFOOTER();
671 return -ERESTARTSYS;
672 }
673
674 if (gcmIS_SUCCESS(status) && (iface.command == gcvHAL_LOCK_VIDEO_MEMORY))
675 {
676 gcuVIDMEM_NODE_PTR node;
677 gctUINT32 processID;
678
679 gckOS_GetProcessID(&processID);
680
681 gcmkONERROR(gckVIDMEM_HANDLE_Lookup(device->kernels[device->coreMapping[iface.hardwareType]],
682 processID,
683 (gctUINT32)iface.u.LockVideoMemory.node,
684 &nodeObject));
685 node = nodeObject->node;
686
687 /* Special case for mapped memory. */
688 if ((data->mappedMemory != gcvNULL)
689 && (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
690 )
691 {
692 /* Compute offset into mapped memory. */
693 gctUINT32 offset
694 = (gctUINT8 *) gcmUINT64_TO_PTR(iface.u.LockVideoMemory.memory)
695 - (gctUINT8 *) device->contiguousBase;
696
697 /* Compute offset into user-mapped region. */
698 iface.u.LockVideoMemory.memory =
699 gcmPTR_TO_UINT64((gctUINT8 *) data->mappedMemory + offset);
700 }
701 }
702
703 /* Copy data back to the user. */
704 copyLen = copy_to_user(
705 gcmUINT64_TO_PTR(drvArgs.OutputBuffer), &iface, sizeof(gcsHAL_INTERFACE)
706 );
707
708 if (copyLen != 0)
709 {
710 gcmkTRACE_ZONE(
711 gcvLEVEL_ERROR, gcvZONE_DRIVER,
712 "%s(%d): error copying of output HAL interface.\n",
713 __FUNCTION__, __LINE__
714 );
715
716 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
717 }
718
719 /* Success. */
720 gcmkFOOTER_NO();
721 return 0;
722
723OnError:
724 gcmkFOOTER();
725 return -ENOTTY;
726}
727
728static int drv_mmap(
729 struct file* filp,
730 struct vm_area_struct* vma
731 )
732{
733 gceSTATUS status = gcvSTATUS_OK;
734 gcsHAL_PRIVATE_DATA_PTR data;
735 gckGALDEVICE device;
736
737 gcmkHEADER_ARG("filp=0x%08X vma=0x%08X", filp, vma);
738
739 if (filp == gcvNULL)
740 {
741 gcmkTRACE_ZONE(
742 gcvLEVEL_ERROR, gcvZONE_DRIVER,
743 "%s(%d): filp is NULL\n",
744 __FUNCTION__, __LINE__
745 );
746
747 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
748 }
749
750 data = filp->private_data;
751
752 if (data == gcvNULL)
753 {
754 gcmkTRACE_ZONE(
755 gcvLEVEL_ERROR, gcvZONE_DRIVER,
756 "%s(%d): private_data is NULL\n",
757 __FUNCTION__, __LINE__
758 );
759
760 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
761 }
762
763 device = data->device;
764
765 if (device == gcvNULL)
766 {
767 gcmkTRACE_ZONE(
768 gcvLEVEL_ERROR, gcvZONE_DRIVER,
769 "%s(%d): device is NULL\n",
770 __FUNCTION__, __LINE__
771 );
772
773 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
774 }
775
776#if !gcdPAGED_MEMORY_CACHEABLE
777 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
778 vma->vm_flags |= gcdVM_FLAGS;
779#endif
780 vma->vm_pgoff = 0;
781
782 if (device->contiguousMapped)
783 {
784 unsigned long size = vma->vm_end - vma->vm_start;
785 int ret = 0;
786
787 if (size > device->contiguousSize)
788 {
789 gcmkTRACE_ZONE(
790 gcvLEVEL_ERROR, gcvZONE_DRIVER,
791 "%s(%d): Invalid mapping size.\n",
792 __FUNCTION__, __LINE__
793 );
794
795 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
796 }
797
798 ret = io_remap_pfn_range(
799 vma,
800 vma->vm_start,
801 device->requestedContiguousBase >> PAGE_SHIFT,
802 size,
803 vma->vm_page_prot
804 );
805
806 if (ret != 0)
807 {
808 gcmkTRACE_ZONE(
809 gcvLEVEL_ERROR, gcvZONE_DRIVER,
810 "%s(%d): io_remap_pfn_range failed %d\n",
811 __FUNCTION__, __LINE__,
812 ret
813 );
814
815 data->mappedMemory = gcvNULL;
816
817 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
818 }
819
820 data->mappedMemory = (gctPOINTER) vma->vm_start;
821
822 /* Success. */
823 gcmkFOOTER_NO();
824 return 0;
825 }
826
827OnError:
828 gcmkFOOTER();
829 return -ENOTTY;
830}
831
832
833#if !USE_PLATFORM_DRIVER
834static int __init drv_init(void)
835#else
836static int drv_init(void)
837#endif
838{
839 int ret;
840 int result = -EINVAL;
841 gceSTATUS status;
842 gckGALDEVICE device = gcvNULL;
843 struct class* device_class = gcvNULL;
844
845 gcsDEVICE_CONSTRUCT_ARGS args = {
846 .recovery = recovery,
847 .stuckDump = stuckDump,
848 .gpu3DMinClock = gpu3DMinClock,
849 .contiguousRequested = contiguousRequested,
850 .platform = &platform,
851 .mmu = mmu,
852 .registerMemMapped = registerMemMapped,
853 .registerMemAddress = registerMemAddress,
854#if gcdENABLE_DEC_COMPRESSION
855 .registerMemBaseDEC300 = registerMemBaseDEC300,
856 .registerMemSizeDEC300 = registerMemSizeDEC300,
857#endif
858 };
859
860 gcmkHEADER();
861
862 printk(KERN_INFO "Galcore version %d.%d.%d.%d\n",
863 gcvVERSION_MAJOR, gcvVERSION_MINOR, gcvVERSION_PATCH, gcvVERSION_BUILD);
864
865#if !VIVANTE_PROFILER_PM
866 /* when enable gpu profiler, we need to turn off gpu powerMangement */
867 if (gpuProfiler)
868 {
869 powerManagement = 0;
870 }
871#endif
872
873 if (showArgs)
874 {
875 gckOS_DumpParam();
876 }
877
878 if (logFileSize != 0)
879 {
880 gckDEBUGFS_Initialize();
881 }
882
883 /* Create the GAL device. */
884 status = gckGALDEVICE_Construct(
885#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
886 irqLine3D0,
887 registerMemBase3D0, registerMemSize3D0,
888 irqLine3D1,
889 registerMemBase3D1, registerMemSize3D1,
890#else
891 irqLine,
892 registerMemBase, registerMemSize,
893#endif
894 irqLine2D,
895 registerMemBase2D, registerMemSize2D,
896 irqLineVG,
897 registerMemBaseVG, registerMemSizeVG,
898 contiguousBase, contiguousSize,
899 bankSize, fastClear, compression, baseAddress, physSize, signal,
900 logFileSize,
901 powerManagement,
902 gpuProfiler,
903 &args,
904 &device
905 );
906
907 if (gcmIS_ERROR(status))
908 {
909 gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DRIVER,
910 "%s(%d): Failed to create the GAL device: status=%d\n",
911 __FUNCTION__, __LINE__, status);
912
913 goto OnError;
914 }
915
916 /* Start the GAL device. */
917 gcmkONERROR(gckGALDEVICE_Start(device));
918
919 if ((physSize != 0)
920 && (device->kernels[gcvCORE_MAJOR] != gcvNULL)
921 && (device->kernels[gcvCORE_MAJOR]->hardware->mmuVersion != 0))
922 {
923 /* Reset the base address */
924 device->baseAddress = 0;
925 }
926
927 /* Register the character device. */
928 ret = register_chrdev(major, DEVICE_NAME, &driver_fops);
929
930 if (ret < 0)
931 {
932 gcmkTRACE_ZONE(
933 gcvLEVEL_ERROR, gcvZONE_DRIVER,
934 "%s(%d): Could not allocate major number for mmap.\n",
935 __FUNCTION__, __LINE__
936 );
937
938 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
939 }
940
941 if (major == 0)
942 {
943 major = ret;
944 }
945
946 /* Create the device class. */
947 device_class = class_create(THIS_MODULE, CLASS_NAME);
948
949 if (IS_ERR(device_class))
950 {
951 gcmkTRACE_ZONE(
952 gcvLEVEL_ERROR, gcvZONE_DRIVER,
953 "%s(%d): Failed to create the class.\n",
954 __FUNCTION__, __LINE__
955 );
956
957 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
958 }
959
960#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
961 device_create(device_class, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);
962#else
963 device_create(device_class, NULL, MKDEV(major, 0), DEVICE_NAME);
964#endif
965
966 galDevice = device;
967 gpuClass = device_class;
968
969#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
970 gcmkTRACE_ZONE(
971 gcvLEVEL_INFO, gcvZONE_DRIVER,
972 "%s(%d): irqLine3D0=%d, contiguousSize=%lu, memBase3D0=0x%lX\n",
973 __FUNCTION__, __LINE__,
974 irqLine3D0, contiguousSize, registerMemBase3D0
975 );
976#else
977 gcmkTRACE_ZONE(
978 gcvLEVEL_INFO, gcvZONE_DRIVER,
979 "%s(%d): irqLine=%d, contiguousSize=%lu, memBase=0x%lX\n",
980 __FUNCTION__, __LINE__,
981 irqLine, contiguousSize, registerMemBase
982 );
983#endif
984
985 /* Success. */
986 gcmkFOOTER_NO();
987 return 0;
988
989OnError:
990 /* Roll back. */
991 if (device_class != gcvNULL)
992 {
993 device_destroy(device_class, MKDEV(major, 0));
994 class_destroy(device_class);
995 }
996
997 if (device != gcvNULL)
998 {
999 gcmkVERIFY_OK(gckGALDEVICE_Stop(device));
1000 gcmkVERIFY_OK(gckGALDEVICE_Destroy(device));
1001 }
1002
1003 gcmkFOOTER();
1004 return result;
1005}
1006
1007#if !USE_PLATFORM_DRIVER
1008static void __exit drv_exit(void)
1009#else
1010static void drv_exit(void)
1011#endif
1012{
1013 gcmkHEADER();
1014
1015 gcmkASSERT(gpuClass != gcvNULL);
1016 device_destroy(gpuClass, MKDEV(major, 0));
1017 class_destroy(gpuClass);
1018
1019 unregister_chrdev(major, DEVICE_NAME);
1020
1021 gcmkVERIFY_OK(gckGALDEVICE_Stop(galDevice));
1022 gcmkVERIFY_OK(gckGALDEVICE_Destroy(galDevice));
1023
1024 if(gckDEBUGFS_IsEnabled())
1025 {
1026 gckDEBUGFS_Terminate();
1027 }
1028
1029 gcmkFOOTER_NO();
1030}
1031
1032#if !USE_PLATFORM_DRIVER
1033 module_init(drv_init);
1034 module_exit(drv_exit);
1035#else
1036
1037#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1038static int gpu_probe(struct platform_device *pdev)
1039#else
1040static int __devinit gpu_probe(struct platform_device *pdev)
1041#endif
1042{
1043 int ret = -ENODEV;
1044 gcsMODULE_PARAMETERS moduleParam = {
1045#if gcdMULTI_GPU || gcdMULTI_GPU_AFFINITY
1046#else
1047 .irqLine = irqLine,
1048 .registerMemBase = registerMemBase,
1049 .registerMemSize = registerMemSize,
1050#endif
1051 .irqLine2D = irqLine2D,
1052 .registerMemBase2D = registerMemBase2D,
1053 .registerMemSize2D = registerMemSize2D,
1054 .irqLineVG = irqLineVG,
1055 .registerMemBaseVG = registerMemBaseVG,
1056 .registerMemSizeVG = registerMemSizeVG,
1057 .contiguousSize = contiguousSize,
1058 .contiguousBase = contiguousBase,
1059 .bankSize = bankSize,
1060 .fastClear = fastClear,
1061 .compression = compression,
1062 .powerManagement = powerManagement,
1063 .gpuProfiler = gpuProfiler,
1064 .signal = signal,
1065 .baseAddress = baseAddress,
1066 .physSize = physSize,
1067 .logFileSize = logFileSize,
1068 .recovery = recovery,
1069 .stuckDump = stuckDump,
1070 .showArgs = showArgs,
1071 .gpu3DMinClock = gpu3DMinClock,
1072 .registerMemMapped = registerMemMapped,
1073 };
1074
1075 gcmkHEADER();
1076
1077 platform.device = pdev;
1078
1079 if (platform.ops->getPower)
1080 {
1081 if (gcmIS_ERROR(platform.ops->getPower(&platform)))
1082 {
1083 gcmkFOOTER_NO();
1084 return ret;
1085 }
1086 }
1087
1088 if (platform.ops->adjustParam)
1089 {
1090 /* Override default module param. */
1091 platform.ops->adjustParam(&platform, &moduleParam);
1092
1093 /* Update module param because drv_init() uses them directly. */
1094 _UpdateModuleParam(&moduleParam);
1095 }
1096
1097 ret = drv_init();
1098
1099 if (!ret)
1100 {
1101 platform_set_drvdata(pdev, galDevice);
1102
1103 gcmkFOOTER_NO();
1104 return ret;
1105 }
1106
1107 gcmkFOOTER_ARG(KERN_INFO "Failed to register gpu driver: %d\n", ret);
1108 return ret;
1109}
1110
1111#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1112static int gpu_remove(struct platform_device *pdev)
1113#else
1114static int __devexit gpu_remove(struct platform_device *pdev)
1115#endif
1116{
1117 gcmkHEADER();
1118
1119 drv_exit();
1120
1121 if (platform.ops->putPower)
1122 {
1123 platform.ops->putPower(&platform);
1124 }
1125
1126 gcmkFOOTER_NO();
1127 return 0;
1128}
1129
1130static int gpu_suspend(struct platform_device *dev, pm_message_t state)
1131{
1132 gceSTATUS status;
1133 gckGALDEVICE device;
1134 gctINT i;
1135
1136 device = platform_get_drvdata(dev);
1137
1138 if (!device)
1139 {
1140 return -1;
1141 }
1142
1143 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1144 {
1145 if (device->kernels[i] != gcvNULL)
1146 {
1147 /* Store states. */
1148 {
1149 status = gckHARDWARE_QueryPowerManagementState(device->kernels[i]->hardware, &device->statesStored[i]);
1150 }
1151
1152 if (gcmIS_ERROR(status))
1153 {
1154 return -1;
1155 }
1156
1157 {
1158 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_OFF);
1159 }
1160
1161 if (gcmIS_ERROR(status))
1162 {
1163 return -1;
1164 }
1165
1166 }
1167 }
1168
1169 return 0;
1170}
1171
1172static int gpu_resume(struct platform_device *dev)
1173{
1174 gceSTATUS status;
1175 gckGALDEVICE device;
1176 gctINT i;
1177 gceCHIPPOWERSTATE statesStored;
1178
1179 device = platform_get_drvdata(dev);
1180
1181 if (!device)
1182 {
1183 return -1;
1184 }
1185
1186 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
1187 {
1188 if (device->kernels[i] != gcvNULL)
1189 {
1190 {
1191 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, gcvPOWER_ON);
1192 }
1193
1194 if (gcmIS_ERROR(status))
1195 {
1196 return -1;
1197 }
1198
1199 /* Convert global state to crossponding internal state. */
1200 switch(device->statesStored[i])
1201 {
1202 case gcvPOWER_OFF:
1203 statesStored = gcvPOWER_OFF_BROADCAST;
1204 break;
1205 case gcvPOWER_IDLE:
1206 statesStored = gcvPOWER_IDLE_BROADCAST;
1207 break;
1208 case gcvPOWER_SUSPEND:
1209 statesStored = gcvPOWER_SUSPEND_BROADCAST;
1210 break;
1211 case gcvPOWER_ON:
1212 statesStored = gcvPOWER_ON_AUTO;
1213 break;
1214 default:
1215 statesStored = device->statesStored[i];
1216 break;
1217 }
1218
1219 /* Restore states. */
1220 {
1221 status = gckHARDWARE_SetPowerManagementState(device->kernels[i]->hardware, statesStored);
1222 }
1223
1224 if (gcmIS_ERROR(status))
1225 {
1226 return -1;
1227 }
1228 }
1229 }
1230
1231 return 0;
1232}
1233
1234#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
1235#ifdef CONFIG_PM_SLEEP
1236static int gpu_system_suspend(struct device *dev)
1237{
1238 pm_message_t state={0};
1239 return gpu_suspend(to_platform_device(dev), state);
1240}
1241
1242static int gpu_system_resume(struct device *dev)
1243{
1244 return gpu_resume(to_platform_device(dev));
1245}
1246#endif
1247
1248static const struct dev_pm_ops gpu_pm_ops = {
1249 SET_SYSTEM_SLEEP_PM_OPS(gpu_system_suspend, gpu_system_resume)
1250};
1251#endif
1252
1253static struct platform_driver gpu_driver = {
1254 .probe = gpu_probe,
1255#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1256 .remove = gpu_remove,
1257#else
1258 .remove = __devexit_p(gpu_remove),
1259#endif
1260
1261 .suspend = gpu_suspend,
1262 .resume = gpu_resume,
1263
1264 .driver = {
1265 .owner = THIS_MODULE,
1266 .name = DEVICE_NAME,
1267#if defined(CONFIG_PM) && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
1268 .pm = &gpu_pm_ops,
1269#endif
1270 }
1271};
1272
1273static int __init gpu_init(void)
1274{
1275 int ret = 0;
1276
1277 memset(&platform, 0, sizeof(gcsPLATFORM));
1278
1279 gckPLATFORM_QueryOperations(&platform.ops);
1280
1281 if (platform.ops == gcvNULL)
1282 {
1283 printk(KERN_ERR "galcore: No platform specific operations.\n");
1284 ret = -ENODEV;
1285 goto out;
1286 }
1287
1288 if (platform.ops->allocPriv)
1289 {
1290 /* Allocate platform private data. */
1291 if (gcmIS_ERROR(platform.ops->allocPriv(&platform)))
1292 {
1293 ret = -ENOMEM;
1294 goto out;
1295 }
1296 }
1297
1298 if (platform.ops->needAddDevice
1299 && platform.ops->needAddDevice(&platform))
1300 {
1301 /* Allocate device */
1302 platform.device = platform_device_alloc(DEVICE_NAME, -1);
1303 if (!platform.device)
1304 {
1305 printk(KERN_ERR "galcore: platform_device_alloc failed.\n");
1306 ret = -ENOMEM;
1307 goto out;
1308 }
1309
1310 /* Add device */
1311 ret = platform_device_add(platform.device);
1312 if (ret)
1313 {
1314 printk(KERN_ERR "galcore: platform_device_add failed.\n");
1315 goto put_dev;
1316 }
1317 }
1318
1319 platform.driver = &gpu_driver;
1320
1321 if (platform.ops->adjustDriver)
1322 {
1323 /* Override default platform_driver struct. */
1324 platform.ops->adjustDriver(&platform);
1325 }
1326
1327 ret = platform_driver_register(&gpu_driver);
1328 if (!ret)
1329 {
1330 goto out;
1331 }
1332
1333 platform_device_del(platform.device);
1334put_dev:
1335 platform_device_put(platform.device);
1336
1337out:
1338 return ret;
1339}
1340
1341static void __exit gpu_exit(void)
1342{
1343 platform_driver_unregister(&gpu_driver);
1344
1345 if (platform.ops->needAddDevice
1346 && platform.ops->needAddDevice(&platform))
1347 {
1348 platform_device_unregister(platform.device);
1349 }
1350
1351 if (platform.priv)
1352 {
1353 /* Free platform private data. */
1354 platform.ops->freePriv(&platform);
1355 }
1356}
1357
1358module_init(gpu_init);
1359module_exit(gpu_exit);
1360
1361#endif
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_security_channel.c b/src/hal/os/linux/kernel/gc_hal_kernel_security_channel.c
new file mode 100755
index 0000000..9dfb755
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_security_channel.c
@@ -0,0 +1,423 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include <linux/slab.h>
58
59#include "tee_client_api.h"
60
61#define _GC_OBJ_ZONE gcvZONE_OS
62
63#define GPU3D_UUID { 0xcc9f80ea, 0xa836, 0x11e3, { 0x9b, 0x07, 0x78, 0x2b, 0xcb, 0x5c, 0xf3, 0xe3 } }
64
65static const TEEC_UUID gpu3d_uuid = GPU3D_UUID;
66TEEC_Context teecContext;
67
68typedef struct _gcsSecurityChannel {
69 gckOS os;
70 TEEC_Session session;
71 int * virtual;
72 TEEC_SharedMemory inputBuffer;
73 gctUINT32 bytes;
74 gctPOINTER mutex;
75} gcsSecurityChannel;
76
77TEEC_SharedMemory *
78gpu3d_allocate_secure_mem(
79 gckOS Os,
80 unsigned int size
81 )
82{
83 TEEC_Result result;
84 TEEC_Context *context = &teecContext;
85 TEEC_SharedMemory *shm = NULL;
86 void *handle = NULL;
87 gctPHYS_ADDR_T phyAddr;
88 gceSTATUS status;
89 gctSIZE_T bytes = size;
90
91 shm = kmalloc(sizeof(TEEC_SharedMemory), GFP_KERNEL);
92
93 if (NULL == shm)
94 {
95 return NULL;
96 }
97
98 memset(shm, 0, sizeof(TEEC_SharedMemory));
99
100 status = gckOS_AllocatePagedMemoryEx(
101 Os,
102 gcvALLOC_FLAG_SECURITY,
103 bytes,
104 gcvNULL,
105 (gctPHYS_ADDR *)&handle);
106
107 if (gcmIS_ERROR(status))
108 {
109 kfree(shm);
110 return NULL;
111 }
112
113 status = gckOS_PhysicalToPhysicalAddress(
114 Os,
115 handle,
116 &phyAddr);
117
118 if (gcmIS_ERROR(status))
119 {
120 kfree(shm);
121 return NULL;
122 }
123
124 /* record the handle into shm->user_data */
125 shm->userdata = handle;
126
127 /* [b] Bulk input buffer. */
128 shm->size = size;
129 shm->flags = TEEC_MEM_INPUT;
130
131 /* Use TEE Client API to register the underlying memory buffer. */
132 shm->phyAddr = (void *)(gctUINT32)phyAddr;
133
134 result = TEEC_RegisterSharedMemory(
135 context,
136 shm);
137
138 if (result != TEEC_SUCCESS)
139 {
140 gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
141 kfree(shm);
142 return NULL;
143 }
144
145 return shm;
146}
147
148void gpu3d_release_secure_mem(
149 gckOS Os,
150 void *shm_handle
151 )
152{
153 TEEC_SharedMemory *shm = shm_handle;
154 void * handle;
155
156 if (!shm)
157 {
158 return;
159 }
160
161 handle = shm->userdata;
162
163 TEEC_ReleaseSharedMemory(shm);
164 gckOS_FreePagedMemory(Os, (gctPHYS_ADDR)handle, shm->size);
165
166 kfree(shm);
167
168 return;
169}
170
171static TEEC_Result gpu3d_session_callback(
172 TEEC_Session* session,
173 uint32_t commandID,
174 TEEC_Operation* operation,
175 void* userdata
176 )
177{
178 gcsSecurityChannel *channel = userdata;
179
180 if (channel == gcvNULL)
181 {
182 return TEEC_ERROR_BAD_PARAMETERS;
183 }
184
185 switch(commandID)
186 {
187 case gcvTA_CALLBACK_ALLOC_SECURE_MEM:
188 {
189 uint32_t size = operation->params[0].value.a;
190 TEEC_SharedMemory *shm = NULL;
191
192 shm = gpu3d_allocate_secure_mem(channel->os, size);
193 if (shm == NULL)
194 {
195 return TEEC_ERROR_OUT_OF_MEMORY;
196 }
197
198 /* use the value to save the pointer in client side */
199 operation->params[0].value.a = (uint32_t)shm;
200 operation->params[0].value.b = (uint32_t)shm->phyAddr;
201
202 break;
203 }
204 case gcvTA_CALLBACK_FREE_SECURE_MEM:
205 {
206 TEEC_SharedMemory *shm = (TEEC_SharedMemory *)operation->params[0].value.a;
207
208 gpu3d_release_secure_mem(channel->os, shm);
209 break;
210 }
211 default:
212 break;
213 }
214
215 return TEEC_SUCCESS;
216}
217
218gceSTATUS
219gckOS_OpenSecurityChannel(
220 IN gckOS Os,
221 IN gceCORE GPU,
222 OUT gctUINT32 *Channel
223 )
224{
225 gceSTATUS status;
226 TEEC_Result result;
227 static bool initialized = gcvFALSE;
228 gcsSecurityChannel *channel = gcvNULL;
229
230 TEEC_Operation operation = {0};
231
232 /* Connect to TEE. */
233 if (initialized == gcvFALSE)
234 {
235 result = TEEC_InitializeContext(NULL, &teecContext);
236
237 if (result != TEEC_SUCCESS) {
238 gcmkONERROR(gcvSTATUS_CHIP_NOT_READY);
239 }
240
241 initialized = gcvTRUE;
242 }
243
244 /* Construct channel. */
245 gcmkONERROR(
246 gckOS_Allocate(Os, gcmSIZEOF(*channel), (gctPOINTER *)&channel));
247
248 gckOS_ZeroMemory(channel, gcmSIZEOF(gcsSecurityChannel));
249
250 channel->os = Os;
251
252 gcmkONERROR(gckOS_CreateMutex(Os, &channel->mutex));
253
254 /* Allocate shared memory for passing gcTA_INTERFACE. */
255 channel->bytes = gcmSIZEOF(gcsTA_INTERFACE);
256 channel->virtual = kmalloc(channel->bytes, GFP_KERNEL | __GFP_NOWARN);
257
258 if (!channel->virtual)
259 {
260 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
261 }
262
263 channel->inputBuffer.size = channel->bytes;
264 channel->inputBuffer.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
265 channel->inputBuffer.phyAddr = (void *)virt_to_phys(channel->virtual);
266
267 result = TEEC_RegisterSharedMemory(&teecContext, &channel->inputBuffer);
268
269 if (result != TEEC_SUCCESS)
270 {
271 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
272 }
273
274 operation.paramTypes = TEEC_PARAM_TYPES(
275 TEEC_VALUE_INPUT,
276 TEEC_NONE,
277 TEEC_NONE,
278 TEEC_NONE);
279
280 operation.params[0].value.a = GPU;
281
282 /* Open session with TEE application. */
283 result = TEEC_OpenSession(
284 &teecContext,
285 &channel->session,
286 &gpu3d_uuid,
287 TEEC_LOGIN_USER,
288 NULL,
289 &operation,
290 NULL);
291
292 /* Prepare callback. */
293 TEEC_RegisterCallback(&channel->session, gpu3d_session_callback, channel);
294
295 *Channel = (gctUINT32)channel;
296
297 return gcvSTATUS_OK;
298
299OnError:
300 if (channel)
301 {
302 if (channel->virtual)
303 {
304 }
305
306 if (channel->mutex)
307 {
308 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, channel->mutex));
309 }
310
311 gcmkVERIFY_OK(gckOS_Free(Os, channel));
312 }
313
314 return status;
315}
316
317gceSTATUS
318gckOS_CloseSecurityChannel(
319 IN gctUINT32 Channel
320 )
321{
322 /* TODO . */
323 return gcvSTATUS_OK;
324}
325
326gceSTATUS
327gckOS_CallSecurityService(
328 IN gctUINT32 Channel,
329 IN gcsTA_INTERFACE *Interface
330 )
331{
332 gceSTATUS status;
333 TEEC_Result result;
334 gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
335 TEEC_Operation operation = {0};
336
337 gcmkHEADER();
338 gcmkVERIFY_ARGUMENT(Channel != 0);
339
340 gckOS_AcquireMutex(channel->os, channel->mutex, gcvINFINITE);
341
342 gckOS_MemCopy(channel->virtual, Interface, channel->bytes);
343
344 operation.paramTypes = TEEC_PARAM_TYPES(
345 TEEC_MEMREF_PARTIAL_INPUT,
346 TEEC_NONE,
347 TEEC_NONE,
348 TEEC_NONE);
349
350 /* Note: we use the updated size in the MemRef output by the encryption. */
351 operation.params[0].memref.parent = &channel->inputBuffer;
352 operation.params[0].memref.offset = 0;
353 operation.params[0].memref.size = sizeof(gcsTA_INTERFACE);
354 operation.started = true;
355
356 /* Start the commit command within the TEE application. */
357 result = TEEC_InvokeCommand(
358 &channel->session,
359 gcvTA_COMMAND_DISPATCH,
360 &operation,
361 NULL);
362
363 gckOS_MemCopy(Interface, channel->virtual, channel->bytes);
364
365 gckOS_ReleaseMutex(channel->os, channel->mutex);
366
367 if (result != TEEC_SUCCESS)
368 {
369 gcmkONERROR(gcvSTATUS_GENERIC_IO);
370 }
371
372 gcmkFOOTER_NO();
373 return gcvSTATUS_OK;
374
375OnError:
376 gcmkFOOTER();
377 return status;
378}
379
380gceSTATUS
381gckOS_InitSecurityChannel(
382 IN gctUINT32 Channel
383 )
384{
385 gceSTATUS status;
386 TEEC_Result result;
387 gcsSecurityChannel *channel = (gcsSecurityChannel *)Channel;
388 TEEC_Operation operation = {0};
389
390 gcmkHEADER();
391 gcmkVERIFY_ARGUMENT(Channel != 0);
392
393 operation.paramTypes = TEEC_PARAM_TYPES(
394 TEEC_MEMREF_PARTIAL_INPUT,
395 TEEC_NONE,
396 TEEC_NONE,
397 TEEC_NONE);
398
399 /* Note: we use the updated size in the MemRef output by the encryption. */
400 operation.params[0].memref.parent = &channel->inputBuffer;
401 operation.params[0].memref.offset = 0;
402 operation.params[0].memref.size = gcmSIZEOF(gcsTA_INTERFACE);
403 operation.started = true;
404
405 /* Start the commit command within the TEE application. */
406 result = TEEC_InvokeCommand(
407 &channel->session,
408 gcvTA_COMMAND_INIT,
409 &operation,
410 NULL);
411
412 if (result != TEEC_SUCCESS)
413 {
414 gcmkONERROR(gcvSTATUS_GENERIC_IO);
415 }
416
417 gcmkFOOTER_NO();
418 return gcvSTATUS_OK;
419
420OnError:
421 gcmkFOOTER();
422 return status;
423}
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_sync.c b/src/hal/os/linux/kernel/gc_hal_kernel_sync.c
new file mode 100755
index 0000000..3a0feac
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_sync.c
@@ -0,0 +1,211 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include <gc_hal.h>
57#include <gc_hal_base.h>
58
59#if gcdANDROID_NATIVE_FENCE_SYNC
60
61#include <linux/kernel.h>
62#include <linux/file.h>
63#include <linux/fs.h>
64#include <linux/miscdevice.h>
65#include <linux/module.h>
66#include <linux/syscalls.h>
67#include <linux/uaccess.h>
68
69#include "gc_hal_kernel_sync.h"
70
71static struct sync_pt *
72viv_sync_pt_dup(
73 struct sync_pt * sync_pt
74 )
75{
76 gceSTATUS status;
77 struct viv_sync_pt *pt;
78 struct viv_sync_pt *src;
79 struct viv_sync_timeline *obj;
80
81 src = (struct viv_sync_pt *) sync_pt;
82 obj = (struct viv_sync_timeline *) sync_pt->parent;
83
84 /* Create the new sync_pt. */
85 pt = (struct viv_sync_pt *)
86 sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
87
88 pt->stamp = src->stamp;
89 pt->sync = src->sync;
90
91 /* Reference sync point. */
92 status = gckOS_ReferenceSyncPoint(obj->os, pt->sync);
93
94 if (gcmIS_ERROR(status))
95 {
96 sync_pt_free((struct sync_pt *)pt);
97 return NULL;
98 }
99
100 return (struct sync_pt *)pt;
101}
102
103static int
104viv_sync_pt_has_signaled(
105 struct sync_pt * sync_pt
106 )
107{
108 gceSTATUS status;
109 gctBOOL state;
110 struct viv_sync_pt * pt;
111 struct viv_sync_timeline * obj;
112
113 pt = (struct viv_sync_pt *)sync_pt;
114 obj = (struct viv_sync_timeline *)sync_pt->parent;
115
116 status = gckOS_QuerySyncPoint(obj->os, pt->sync, &state);
117
118 if (gcmIS_ERROR(status))
119 {
120 /* Error. */
121 return -1;
122 }
123
124 return state;
125}
126
127static int
128viv_sync_pt_compare(
129 struct sync_pt * a,
130 struct sync_pt * b
131 )
132{
133 int ret;
134 struct viv_sync_pt * pt1 = (struct viv_sync_pt *) a;
135 struct viv_sync_pt * pt2 = (struct viv_sync_pt *) b;
136
137 ret = (pt1->stamp < pt2->stamp) ? -1
138 : (pt1->stamp == pt2->stamp) ? 0
139 : 1;
140
141 return ret;
142}
143
144static void
145viv_sync_pt_free(
146 struct sync_pt * sync_pt
147 )
148{
149 struct viv_sync_pt * pt;
150 struct viv_sync_timeline * obj;
151
152 pt = (struct viv_sync_pt *) sync_pt;
153 obj = (struct viv_sync_timeline *) sync_pt->parent;
154
155 gckOS_DestroySyncPoint(obj->os, pt->sync);
156}
157
158static struct sync_timeline_ops viv_timeline_ops =
159{
160 .driver_name = "viv_sync",
161 .dup = viv_sync_pt_dup,
162 .has_signaled = viv_sync_pt_has_signaled,
163 .compare = viv_sync_pt_compare,
164 .free_pt = viv_sync_pt_free,
165};
166
167struct viv_sync_timeline *
168viv_sync_timeline_create(
169 const char * name,
170 gckOS os
171 )
172{
173 struct viv_sync_timeline * obj;
174
175 obj = (struct viv_sync_timeline *)
176 sync_timeline_create(&viv_timeline_ops, sizeof(struct viv_sync_timeline), name);
177
178 obj->os = os;
179 obj->stamp = 0;
180
181 return obj;
182}
183
184struct sync_pt *
185viv_sync_pt_create(
186 struct viv_sync_timeline * obj,
187 gctSYNC_POINT SyncPoint
188 )
189{
190 gceSTATUS status;
191 struct viv_sync_pt * pt;
192
193 pt = (struct viv_sync_pt *)
194 sync_pt_create(&obj->obj, sizeof(struct viv_sync_pt));
195
196 pt->stamp = obj->stamp++;
197 pt->sync = SyncPoint;
198
199 /* Dup signal. */
200 status = gckOS_ReferenceSyncPoint(obj->os, SyncPoint);
201
202 if (gcmIS_ERROR(status))
203 {
204 sync_pt_free((struct sync_pt *)pt);
205 return NULL;
206 }
207
208 return (struct sync_pt *) pt;
209}
210
211#endif
diff --git a/src/hal/os/linux/kernel/gc_hal_kernel_sync.h b/src/hal/os/linux/kernel/gc_hal_kernel_sync.h
new file mode 100755
index 0000000..658b205
--- /dev/null
+++ b/src/hal/os/linux/kernel/gc_hal_kernel_sync.h
@@ -0,0 +1,106 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#ifndef __gc_hal_kernel_sync_h_
57#define __gc_hal_kernel_sync_h_
58
59#include <linux/types.h>
60
61/* sync.h is in drivers/staging/android/ for now. */
62#include <sync.h>
63
64#include <gc_hal.h>
65#include <gc_hal_base.h>
66
67struct viv_sync_timeline
68{
69 /* Parent object. */
70 struct sync_timeline obj;
71
72 /* Timestamp when sync_pt is created. */
73 gctUINT stamp;
74
75 /* Pointer to os struct. */
76 gckOS os;
77};
78
79
80struct viv_sync_pt
81{
82 /* Parent object. */
83 struct sync_pt pt;
84
85 /* Reference sync point*/
86 gctSYNC_POINT sync;
87
88 /* Timestamp when sync_pt is created. */
89 gctUINT stamp;
90};
91
92/* Create viv_sync_timeline object. */
93struct viv_sync_timeline *
94viv_sync_timeline_create(
95 const char * Name,
96 gckOS Os
97 );
98
99/* Create viv_sync_pt object. */
100struct sync_pt *
101viv_sync_pt_create(
102 struct viv_sync_timeline * Obj,
103 gctSYNC_POINT SyncPoint
104 );
105
106#endif /* __gc_hal_kernel_sync_h_ */
diff --git a/src/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c b/src/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c
new file mode 100755
index 0000000..599855a
--- /dev/null
+++ b/src/hal/os/linux/kernel/platform/default/gc_hal_kernel_platform_default.c
@@ -0,0 +1,81 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include "gc_hal_kernel_platform.h"
58
59gctBOOL
60_NeedAddDevice(
61 IN gckPLATFORM Platform
62 )
63{
64 return gcvTRUE;
65}
66
67gcmkPLATFROM_Name
68
69gcsPLATFORM_OPERATIONS platformOperations =
70{
71 .needAddDevice = _NeedAddDevice,
72 .name = _Name,
73};
74
75void
76gckPLATFORM_QueryOperations(
77 IN gcsPLATFORM_OPERATIONS ** Operations
78 )
79{
80 *Operations = &platformOperations;
81}
diff --git a/src/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_j6.c b/src/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_j6.c
new file mode 100755
index 0000000..e760bb6
--- /dev/null
+++ b/src/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_j6.c
@@ -0,0 +1,253 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include "gc_hal_kernel_platform.h"
58
59#include <linux/pm_runtime.h>
60#include <linux/delay.h>
61#include <linux/io.h>
62#include <linux/of.h>
63#include <linux/of_device.h>
64
65/*
66 * GC320 platform data struct, using the definition as in
67 * `linux/platform_data/omap_gcx.h` in k3.8
68 *
69 * TODO: revisit this and tune it as per latest requirements
70 */
71struct omap_gcx_platform_data {
72 bool is_hw_present;
73 void *regbase;
74 /*bool (*was_context_lost)(struct device *dev);*/
75 int (*get_context_loss_count)(struct device *dev);
76 /* device scale */
77 int (*scale_dev)(struct device *dev, unsigned long freq);
78 /* bandwidth */
79 int (*set_bw)(struct device *dev, unsigned long v);
80};
81
82static int gcxxx_get_context_loss_count(struct device *dev)
83{
84 /*
85 omap_pm_get_context_loss_count not supported:
86 returning with default 1
87 */
88 return 1;
89}
90static int gcxxx_scale_dev(struct device *dev, unsigned long val)
91{
92 /*omap_device_scale(dev, val) is not supported, returning with no-op
93 * for now. */
94 return 0;
95}
96
97static int gcxxx_set_l3_bw(struct device *dev, unsigned long val)
98{
99 return 0; /*omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, val);*/
100}
101static struct omap_gcx_platform_data omap_gcxxx = {
102 .get_context_loss_count = gcxxx_get_context_loss_count,
103 .scale_dev = gcxxx_scale_dev,
104 .set_bw = gcxxx_set_l3_bw,
105};
106
107
108
109static const struct of_device_id bb2d_of_match[] = {
110 {
111 .compatible = "ti,dra7-bb2d",
112 .data = &omap_gcxxx,
113 },
114 {},
115};
116
117
118static gctBOOL
119_NeedAddDevice(
120 IN gckPLATFORM Platform
121 )
122{
123 /*
124 * platform_device is registered through DTS framework, we dont need to
125 * register explicitly, return false here.
126 */
127 return gcvFALSE;
128}
129
130/* override J6 specific fields of `platform_driver` */
131static gceSTATUS
132_AdjustDriver(
133 IN gckPLATFORM Platform
134 )
135{
136 struct platform_driver * driver = Platform->driver;
137
138 /* return DTS match entry */
139 driver->driver.of_match_table = bb2d_of_match;
140
141 return gcvSTATUS_TRUE;
142}
143
144/* prepare clock and power operations */
145static gceSTATUS
146_GetPower(
147 IN gckPLATFORM Platform
148 )
149{
150 struct platform_device *pdev;
151 pdev = Platform->device;
152
153 pm_runtime_enable(&pdev->dev);
154 pm_runtime_get_sync(&pdev->dev);
155
156 return gcvSTATUS_TRUE;
157}
158
159/* finish clock and power operations */
160static gceSTATUS
161_PutPower(
162 IN gckPLATFORM Platform
163 )
164{
165 struct platform_device *pdev;
166 pdev = Platform->device;
167
168 pm_runtime_put_sync(&pdev->dev);
169 pm_runtime_disable(&pdev->dev);
170
171 return gcvSTATUS_TRUE;
172}
173
174/*
175 * AdjustParam - override default/passed in module arguments.
176 *
177 * Here we modify/update IRQ and register address entries by querying through
178 * DTS framework.
179 */
180static gceSTATUS
181_AdjustParam(
182 IN gckPLATFORM Platform,
183 OUT gcsMODULE_PARAMETERS *Args
184 )
185{
186 struct resource *res_ptr = NULL;
187
188 struct omap_gcx_platform_data *plat;
189 struct of_device_id *match;
190 struct platform_device *pdev;
191 int dev_irq;
192
193 if (Args->registerMemMapped)
194 return gcvSTATUS_TRUE;
195
196 pdev = Platform->device;
197
198 match = (struct of_device_id *)of_match_device(of_match_ptr(bb2d_of_match), &pdev->dev);
199
200 if (match) {
201 plat = (struct omap_gcx_platform_data *) match->data;
202 plat->is_hw_present = (of_machine_is_compatible("ti, omap54xx") || of_machine_is_compatible("ti,dra7"));
203 } else {
204 /* platform_device registration */
205 plat = (struct omap_gcx_platform_data *)dev_get_platdata(&pdev->dev);
206 }
207
208 if ( !plat->is_hw_present )
209 return gcvSTATUS_FALSE;
210
211 res_ptr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
212 if (!res_ptr) {
213 return gcvSTATUS_FALSE;
214 }
215 /* map the address space */
216 Args->registerMemAddress = (gctPOINTER)devm_ioremap_resource(&pdev->dev, res_ptr);
217 Args->registerMemMapped = gcvTRUE;
218
219 /*
220 * IRQ line is acquired through commandline argument with unified driver.
221 * With k3.14, the MPU IRQ line in J6 is configured dynamically at runtime
222 * per dtb configuration and has to be queried through `platform_get_irq()`
223 * API.
224 */
225 dev_irq = platform_get_irq(pdev, 0);
226 if (dev_irq < 0) {
227 /* TODO: use Vivante debug prints */
228 printk(KERN_ERR "%s: platform_get_irq failed (%d)\n",
229 __FUNCTION__, -dev_irq);
230 return -EINVAL;
231 }
232 printk(KERN_INFO "GC320 IRQ: %d\n", dev_irq);
233 Args->irqLine = dev_irq;
234
235 return gcvSTATUS_TRUE;
236}
237
238gcsPLATFORM_OPERATIONS platformOperations =
239{
240 .adjustParam = _AdjustParam,
241 .adjustDriver = _AdjustDriver,
242 .needAddDevice = _NeedAddDevice,
243 .getPower = _GetPower,
244 .putPower = _PutPower,
245};
246
247void
248gckPLATFORM_QueryOperations(
249 IN gcsPLATFORM_OPERATIONS ** Operations
250 )
251{
252 *Operations = &platformOperations;
253}
diff --git a/src/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_ti.c b/src/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_ti.c
new file mode 100755
index 0000000..32ea3b6
--- /dev/null
+++ b/src/hal/os/linux/kernel/platform/ti/gc_hal_kernel_platform_ti.c
@@ -0,0 +1,188 @@
1/****************************************************************************
2*
3* The MIT License (MIT)
4*
5* Copyright (c) 2014 Vivante Corporation
6*
7* Permission is hereby granted, free of charge, to any person obtaining a
8* copy of this software and associated documentation files (the "Software"),
9* to deal in the Software without restriction, including without limitation
10* the rights to use, copy, modify, merge, publish, distribute, sublicense,
11* and/or sell copies of the Software, and to permit persons to whom the
12* Software is furnished to do so, subject to the following conditions:
13*
14* The above copyright notice and this permission notice shall be included in
15* all copies or substantial portions of the Software.
16*
17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23* DEALINGS IN THE SOFTWARE.
24*
25*****************************************************************************
26*
27* The GPL License (GPL)
28*
29* Copyright (C) 2014 Vivante Corporation
30*
31* This program is free software; you can redistribute it and/or
32* modify it under the terms of the GNU General Public License
33* as published by the Free Software Foundation; either version 2
34* of the License, or (at your option) any later version.
35*
36* This program is distributed in the hope that it will be useful,
37* but WITHOUT ANY WARRANTY; without even the implied warranty of
38* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39* GNU General Public License for more details.
40*
41* You should have received a copy of the GNU General Public License
42* along with this program; if not, write to the Free Software Foundation,
43* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
44*
45*****************************************************************************
46*
47* Note: This software is released under dual MIT and GPL licenses. A
48* recipient may use this file under the terms of either the MIT license or
49* GPL License. If you wish to use only one license not the other, you can
50* indicate your decision by deleting one of the above license notices in your
51* version of this file.
52*
53*****************************************************************************/
54
55
56#include "gc_hal_kernel_linux.h"
57#include "gc_hal_kernel_platform.h"
58
59#include <linux/pm_runtime.h>
60#include <linux/delay.h>
61#include <linux/opp.h>
62#include <linux/io.h>
63#include <linux/of.h>
64#include <linux/of_device.h>
65#include <linux/platform_data/omap_gcx.h>
66
67static int gcxxx_get_context_loss_count(struct device *dev)
68{
69 /*
70 omap_pm_get_context_loss_count not supported:
71 returning with default 1
72 */
73 return 1;
74}
75static int gcxxx_scale_dev(struct device *dev, unsigned long val)
76{
77 /*omap_device_scale(dev, val) is not supported, returning with no-op
78 * for now. */
79 return 0;
80}
81
82static int gcxxx_set_l3_bw(struct device *dev, unsigned long val)
83{
84 return 0; /*omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, val);*/
85}
86static struct omap_gcx_platform_data omap_gcxxx = {
87 .get_context_loss_count = gcxxx_get_context_loss_count,
88 .scale_dev = gcxxx_scale_dev,
89 .set_bw = gcxxx_set_l3_bw,
90};
91
92
93
94static const struct of_device_id bb2d_of_match[] = {
95 {
96 .compatible = "ti,bb2d",
97 .data = &omap_gcxxx,
98 },
99 {},
100};
101
102
103static gctBOOL
104_NeedAddDevice(
105 IN gckPLATFORM Platform
106 )
107{
108 return gcvTRUE;
109}
110
111static gceSTATUS
112_AdjustDriver(
113 IN gckPLATFORM Platform
114 )
115{
116 struct platform_driver * driver = Platform->driver;
117 driver->driver.of_match_table = bb2d_of_match;
118 return gcvSTATUS_TRUE;
119}
120
121static gceSTATUS
122_GetPower(
123 IN gckPLATFORM Platform
124 )
125{
126 struct platform_device *pdev;
127 pdev = Platform->device;
128
129 pm_runtime_enable(&pdev->dev);
130 pm_runtime_get_sync(&pdev->dev);
131
132 return gcvSTATUS_TRUE;
133}
134
135static gceSTATUS
136_AdjustParam(
137 IN gckPLATFORM Platform,
138 OUT gcsMODULE_PARAMETERS *Args
139 )
140{
141 struct resource *res_ptr = NULL;
142
143 struct omap_gcx_platform_data *plat;
144 struct of_device_id *match;
145 struct platform_device *pdev;
146
147 if (Args->registerMemMapped)
148 return gcvSTATUS_TRUE;
149
150 pdev = Platform->device;
151
152
153 plat = (struct omap_gcx_platform_data *)dev_get_platdata(&pdev->dev);
154
155 match = (struct of_device_id *)of_match_device(of_match_ptr(bb2d_of_match), &pdev->dev);
156
157 if (match) {
158 plat = (struct omap_gcx_platform_data *) match->data;
159 plat->is_hw_present = (of_machine_is_compatible("ti, omap54xx") || of_machine_is_compatible("ti,dra7"));
160 }
161
162 if ( !plat->is_hw_present )
163 return gcvSTATUS_FALSE;
164
165 res_ptr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
166 if (!res_ptr) {
167 return gcvSTATUS_FALSE;
168 }
169 Args->registerMemAddress = (gctPOINTER)devm_ioremap_resource(&pdev->dev, res_ptr);
170 Args->registerMemMapped = gcvTRUE;
171 return gcvSTATUS_TRUE;
172}
173
174gcsPLATFORM_OPERATIONS platformOperations =
175{
176 .adjustParam = _AdjustParam,
177 .adjustDriver = _AdjustDriver,
178 .needAddDevice = _NeedAddDevice,
179 .getPower = _GetPower,
180};
181
182void
183gckPLATFORM_QueryOperations(
184 IN gcsPLATFORM_OPERATIONS ** Operations
185 )
186{
187 *Operations = &platformOperations;
188}