aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/ice4100/sgx535
diff options
context:
space:
mode:
authorMichael Demeter <michael.demeter@intel.com>2010-12-09 10:37:30 +0000
committerAlan Cox <alan@linux.intel.com>2010-12-09 10:37:30 +0000
commit0ea0a682c607bd71cc750c595c276c8eb2830470 (patch)
tree3bdf430695b91eeaff8a1659b0b1c5ed845f3740 /drivers/staging/ice4100/sgx535
parent3b2a22549568fb5f6f63872352ac276e8dc835ac (diff)
downloadmrst-s0i3-test-0ea0a682c607bd71cc750c595c276c8eb2830470.tar.gz
mrst-s0i3-test-0ea0a682c607bd71cc750c595c276c8eb2830470.tar.xz
mrst-s0i3-test-0ea0a682c607bd71cc750c595c276c8eb2830470.zip
Initial add of the sgx535 to the staging tree
Signed-off-by: Michael Demeter <michael.demeter@intel.com>
Diffstat (limited to 'drivers/staging/ice4100/sgx535')
-rw-r--r--drivers/staging/ice4100/sgx535/Makefile267
-rwxr-xr-xdrivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.c3419
-rwxr-xr-xdrivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.h218
-rwxr-xr-xdrivers/staging/ice4100/sgx535/bridged/bridged_support.c84
-rwxr-xr-xdrivers/staging/ice4100/sgx535/bridged/bridged_support.h43
-rwxr-xr-xdrivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.c2497
-rwxr-xr-xdrivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.h42
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/buffer_manager.c1803
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/deviceclass.c1732
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/devicemem.c1253
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/handle.c1521
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/hash.c434
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/lists.c92
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/mem.c131
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/mem_debug.c228
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/metrics.c149
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/pdump_common.c1558
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/perproc.c276
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/power.c686
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/pvrsrv.c1108
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/queue.c1046
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/ra.c1889
-rwxr-xr-xdrivers/staging/ice4100/sgx535/common/resman.c629
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/mmu.c2500
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/mmu.h139
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/pb.c420
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgx_bridge_km.h147
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxconfig.h158
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxinfokm.h346
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxinit.c2136
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxkick.c901
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxpower.c422
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxreset.c474
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxtransfer.c598
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxutils.c845
-rwxr-xr-xdrivers/staging/ice4100/sgx535/devices/sgx/sgxutils.h107
-rwxr-xr-xdrivers/staging/ice4100/sgx535/env_data.h66
-rwxr-xr-xdrivers/staging/ice4100/sgx535/env_perproc.h56
-rwxr-xr-xdrivers/staging/ice4100/sgx535/event.c278
-rwxr-xr-xdrivers/staging/ice4100/sgx535/event.h32
-rwxr-xr-xdrivers/staging/ice4100/sgx535/hwdefs/sgx535defs.h637
-rwxr-xr-xdrivers/staging/ice4100/sgx535/hwdefs/sgxdefs.h82
-rwxr-xr-xdrivers/staging/ice4100/sgx535/hwdefs/sgxerrata.h306
-rwxr-xr-xdrivers/staging/ice4100/sgx535/hwdefs/sgxfeaturedefs.h166
-rwxr-xr-xdrivers/staging/ice4100/sgx535/hwdefs/sgxmmu.h79
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/buffer_manager.h213
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/dbgdrvif.h267
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/device.h271
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/env/linux/pvr_drm_shared.h63
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/handle.h272
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/hash.h73
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/img_defs.h63
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/img_types.h86
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/ioctldef.h98
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/kernelbuffer.h60
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/kerneldisplay.h153
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/lists.h176
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/metrics.h130
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/osfunc.h324
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/osperproc.h37
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pdump_km.h439
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pdump_osfunc.h137
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pdumpdefs.h99
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/perproc.h91
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/power.h120
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pvr_bridge.h1405
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pvr_bridge_km.h295
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pvr_debug.h119
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pvrmmap.h36
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pvrmodule.h31
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/pvrversion.h38
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/queue.h119
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/ra.h155
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/regpaths.h43
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/resman.h113
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/services.h864
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/services_headers.h49
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/servicesext.h659
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/servicesint.h254
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/sgx_bridge.h477
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/sgx_mkif_km.h388
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/sgx_options.h224
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/sgxapi_km.h329
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/sgxinfo.h288
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/sgxscript.h81
-rwxr-xr-xdrivers/staging/ice4100/sgx535/include/srvkm.h69
-rwxr-xr-xdrivers/staging/ice4100/sgx535/linkage.h61
-rwxr-xr-xdrivers/staging/ice4100/sgx535/lock.h32
-rwxr-xr-xdrivers/staging/ice4100/sgx535/mm.c2150
-rwxr-xr-xdrivers/staging/ice4100/sgx535/mm.h331
-rwxr-xr-xdrivers/staging/ice4100/sgx535/mmap.c1104
-rwxr-xr-xdrivers/staging/ice4100/sgx535/mmap.h107
-rwxr-xr-xdrivers/staging/ice4100/sgx535/module.c734
-rwxr-xr-xdrivers/staging/ice4100/sgx535/mutils.c129
-rwxr-xr-xdrivers/staging/ice4100/sgx535/mutils.h101
-rwxr-xr-xdrivers/staging/ice4100/sgx535/osfunc.c2369
-rwxr-xr-xdrivers/staging/ice4100/sgx535/osperproc.c106
-rwxr-xr-xdrivers/staging/ice4100/sgx535/pdump.c610
-rwxr-xr-xdrivers/staging/ice4100/sgx535/private_data.h67
-rwxr-xr-xdrivers/staging/ice4100/sgx535/proc.c933
-rwxr-xr-xdrivers/staging/ice4100/sgx535/proc.h115
-rwxr-xr-xdrivers/staging/ice4100/sgx535/pvr_bridge_k.c667
-rwxr-xr-xdrivers/staging/ice4100/sgx535/pvr_debug.c413
-rwxr-xr-xdrivers/staging/ice4100/sgx535/pvr_drm.c300
-rwxr-xr-xdrivers/staging/ice4100/sgx535/pvr_drm.h87
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/include/syscommon.h201
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/graphics_pm.c262
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/graphics_pm.h51
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/oemfuncs.h79
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/sysconfig.c884
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/sysconfig.h88
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/sysinfo.h65
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/syslocal.h85
-rwxr-xr-xdrivers/staging/ice4100/sgx535/system/sgx_intel_ce/sysutils.c118
114 files changed, 53457 insertions, 0 deletions
diff --git a/drivers/staging/ice4100/sgx535/Makefile b/drivers/staging/ice4100/sgx535/Makefile
new file mode 100644
index 00000000000..9d28cf5fa21
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/Makefile
@@ -0,0 +1,267 @@
+#
+# Makefile for the graphics hardware. This driver provides support for the
+# Power VR accelerated 2D and 3D cores
+
+BUILD ?= release
+
+
+DATE ?= $(shell date "+%a %B %d %Z %Y")
+PVRVERSION_H = drivers/staging/ice4100/sgx535/include/pvrversion.h
+PVRVERSION = $(shell grep "PVRVERSION_STRING" < $(PVRVERSION_H) | \
+ sed "s,.*\"\([0-9.]*\)\".*,\1,";)
+
+PVRVERSION_MAJ = $(shell echo $(PVRVERSION) | cut -d '.' -f1)
+PVRVERSION_MIN = $(shell echo $(PVRVERSION) | cut -d '.' -f2)
+PVRVERSION_BRANCH = $(shell echo $(PVRVERSION) | cut -d '.' -f3)
+PVRVERSION_BUILD = $(shell echo $(PVRVERSION) | cut -d '.' -f4,5,6)
+
+PVR_BUILD_DIR ?= $(PWD)
+
+# Defaults for useful things.
+#
+INTEL_D3_CHANGES ?= 1
+INTEL_D3_PAD ?= 1
+INTEL_D3_FLUSH ?= 1
+INTEL_D3_DISABLE_TEXTURE_STREAM ?= 1
+INTEL_D3_GDL ?= 0
+INTEL_D3_NO_PCI_ENUM ?= 0
+INTEL_D3_P_CHANGES ?= 1
+INTEL_D3_CACHED_CBUF ?= 1
+INTEL_D3_MEEGO ?= 1
+
+SUPPORT_SECURE_FD_EXPORT ?= 0
+TRANSFER_QUEUE ?= 1
+SUPPORT_SGX_EVENT_OBJECT ?=1
+SUPPORT_SECURE_HANDLES ?= 1
+SUPPORT_SRVINIT = 1
+SUPPORT_PERCONTEXT_PB = 1
+DC_NOHW_WIDTH ?= 640
+DC_NOHW_HEIGHT ?= 480
+
+#OPTIM contains the optimisation level in timing and release builds
+OPTIM = -O2
+
+PDUMP ?= 0
+SUPPORT_SGX ?= 1
+SUPPORT_HW_RECOVERY ?= 1
+
+SYS_USING_INTERRUPTS ?= 1
+
+# CE4100 device information
+SGXCORE = 535
+CORE = -DSGX535 -DSGX_CORE_REV=121 -DSUPPORT_SGX535
+SUPPORT_DRI_DRM ?= 1
+SUPPORT_LINUX_X86_WRITECOMBINE ?= 1
+SUPPORT_SGX_LOW_LATENCY_SCHEDULING ?=1
+SUPPORT_LINUX_X86_PAT ?= 1
+PVR_PROC_USE_SEQ_FILE ?= 1
+
+SUPPORT_SECURE_DRM_AUTH_EXPORT ?= 0
+SUPPORT_LIBDRM_LITE ?= 0
+SUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION = 0
+SUPPORT_LINUX_USING_WORKQUEUES ?= 0
+
+# Thread support
+USE_PTHREADS ?= 1
+USE_GCC__thread_KEYWORD ?= 0
+OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP ?= 0
+DISABLE_THREADS ?= 0
+
+# Don't support HW recovery on debug builds
+ifeq ("$(BUILD)", "debug")
+DEBUG_LINUX_MEMORY_ALLOCATIONS ?= 1
+DEBUG_LINUX_MEM_AREAS ?= 1
+DEBUG_LINUX_MMAP_AREAS ?= 1
+DEBUG_LINUX_XML_PROC_FILES ?= 0
+DEBUG_LINUX_SLAB_ALLOCATIONS ?= 0
+DEBUG_BRIDGE_KM ?= 1
+DEBUG_TRACE_BRIDGE_KM ?= 0
+DEBUG_BRIDGE_KM_DISPATCH_TABLE ?= 0
+SUPPORT_HW_RECOVERY = 0
+PVRSRV_LOG_MEMORY_ALLOCS ?= 0
+PVRSRV_DEBUG_OS_MEMORY ?= 0
+endif
+
+# The standard CFLAGS macro can be overridden on the 'make' command line. We
+# put CBUILD in a separate macro so its setting doesn't get lost when a user
+# *does* override CFLAGS.
+#
+
+CBUILD = -DPVR_BUILD_DIR="\"$(PVR_BUILD_DIR)\"" \
+ -DPVR_BUILD_DATE="\"$(DATE)\"" \
+ -DPVR_BUILD_TYPE="\"$(BUILD)\""
+
+CBUILD.debug = -DDEBUG
+CBUILD.timing = -DTIMING
+CBUILD.release = -DRELEASE
+CFLAGS.debug = -g -O0 -DDLL_METRIC=1
+CFLAGS.timing = $(OPTIM) -g -DDLL_METRIC=1 -DTIMING
+CFLAGS.release = $(OPTIM) -g
+EXTRA_CFLAGS = $(CFLAGS.$(BUILD))
+
+SYS_CFLAGS += -DSERVICES4 -D_XOPEN_SOURCE=600 -DPVR2D_VALIDATE_INPUT_PARAMS
+
+# Services module name
+PVRSRV_MODNAME = pvrsrvkm
+SYS_CFLAGS += -DPVRSRV_MODNAME="\"$(PVRSRV_MODNAME)"\"
+
+# Automatically define C compiler macros for features possible (or not) in use.
+
+SYS_CFLAGS.$(SUPPORT_SRVINIT) += -DSUPPORT_SRVINIT
+SYS_CFLAGS.$(SUPPORT_LINUX_X86_PAT) += -DSUPPORT_LINUX_X86_PAT
+
+SYS_CFLAGS.$(SUPPORT_SGX) += -DSUPPORT_SGX
+SYS_CFLAGS.$(SUPPORT_XWS) += -DSUPPORT_XWS
+SYS_CFLAGS.$(PDUMP) += -DPDUMP
+SYS_CFLAGS.$(SUPPORT_POWER_MANAGEMENT) += -DSUPPORT_POWER_MANAGEMENT
+SYS_CFLAGS.$(SUPPORT_BUFFER_CLASS) += -DSUPPORT_BUFFER_CLASS
+
+SYS_CFLAGS.$(SUPPORT_PERCONTEXT_PB) += -DSUPPORT_PERCONTEXT_PB
+SYS_CFLAGS.$(SUPPORT_DYNAMIC_PBRESIZE) += -DSUPPORT_DYNAMIC_PBRESIZE
+
+SYS_CFLAGS.$(USE_FBDEV) += -DUSE_FBDEV
+SYS_CFLAGS.$(USE_FBDEV) += -DFBDEV_NAME="\"$(FBDEV_NAME)\""
+SYS_CFLAGS.$(SUPPORT_DYNAMIC_3DCLOCKGATING) += -DSUPPORT_DYNAMIC_3DCLOCKGATING
+SYS_CFLAGS.$(REENTRANCY_PROTECTION) += -DREENTRANCY_PROTECTION
+SYS_CFLAGS.$(SCHEDULER_CONTROL_SUPPORT) += -DSCHEDULER_CONTROL_SUPPORT
+SYS_CFLAGS.$(USE_IMG_POWER_DOMAIN_FUNCTION) += -DUSE_IMG_POWER_DOMAIN_FUNCTION
+
+SYS_CFLAGS.$(USE_DMALLOC) += -DDMALLOC
+
+SYS_CFLAGS.$(DEBUG_LINUX_MEMORY_ALLOCATIONS) += -DDEBUG_LINUX_MEMORY_ALLOCATIONS
+SYS_CFLAGS.$(DEBUG_LINUX_MEM_AREAS) += -DDEBUG_LINUX_MEM_AREAS
+SYS_CFLAGS.$(DEBUG_LINUX_MMAP_AREAS) += -DDEBUG_LINUX_MMAP_AREAS
+SYS_CFLAGS.$(DEBUG_LINUX_XML_PROC_FILES) += -DDEBUG_LINUX_XML_PROC_FILES
+SYS_CFLAGS.$(DEBUG_LINUX_SLAB_ALLOCATIONS) += -DDEBUG_LINUX_SLAB_ALLOCATIONS
+SYS_CFLAGS.$(DEBUG_BRIDGE_KM) += -DDEBUG_BRIDGE_KM
+SYS_CFLAGS.$(DEBUG_TRACE_BRIDGE_KM) += -DDEBUG_TRACE_BRIDGE_KM
+SYS_CFLAGS.$(DEBUG_BRIDGE_KM_DISPATCH_TABLE) += -DDEBUG_BRIDGE_KM_DISPATCH_TABLE
+
+SYS_CFLAGS.$(SUPPORT_LINUX_X86_WRITECOMBINE) += -DSUPPORT_LINUX_X86_WRITECOMBINE
+
+SYS_CFLAGS.$(SGX_PDS_EVENTS_DISABLED) += -DSGX_PDS_EVENTS_DISABLED
+SYS_CFLAGS.$(USE_SUPPORT_NO_TA3D_OVERLAP) += -DUSE_SUPPORT_NO_TA3D_OVERLAP
+SYS_CFLAGS.$(SUPPORT_SGX_TILING) += -DSUPPORT_SGX_TILING
+SYS_CFLAGS.$(TRANSFER_QUEUE) += -DTRANSFER_QUEUE
+
+SYS_CFLAGS.$(SUPPORT_SGX_MMU_DUMMY_PAGE) += -DSUPPORT_SGX_MMU_DUMMY_PAGE
+
+SYS_CFLAGS.$(PVRSRV_USSE_EDM_STATUS_DEBUG) += -DPVRSRV_USSE_EDM_STATUS_DEBUG
+
+SYS_CFLAGS.$(PVRSRV_CLIENT_RESET_ON_HWTIMEOUT) += -DPVRSRV_CLIENT_RESET_ON_HWTIMEOUT
+SYS_CFLAGS.$(PVRSRV_RESET_ON_HWTIMEOUT) += -DPVRSRV_RESET_ON_HWTIMEOUT
+
+SYS_CFLAGS.$(NO_HARDWARE) += -DNO_HARDWARE
+
+SYS_CFLAGS.$(SUPPORT_DRI_DRM) += -DSUPPORT_DRI_DRM
+SYS_CFLAGS.$(SUPPORT_LIBDRM_LITE) += -DSUPPORT_LIBDRM_LITE
+SYS_CFLAGS.$(PVR_PROC_USE_SEQ_FILE) += -DPVR_PROC_USE_SEQ_FILE
+
+ifneq ("$(NO_HARDWARE)", "1")
+SYS_CFLAGS.$(SYS_USING_INTERRUPTS) += -DSYS_USING_INTERRUPTS
+SYS_CFLAGS.$(SUPPORT_HW_RECOVERY) += -DSUPPORT_HW_RECOVERY
+SYS_CFLAGS.$(SUPPORT_ACTIVE_POWER_MANAGEMENT) += -DSUPPORT_ACTIVE_POWER_MANAGEMENT
+endif
+
+SYS_CFLAGS.$(SUPPORT_SECURE_HANDLES) += -DPVR_SECURE_HANDLES
+SYS_CFLAGS.$(SUPPORT_SECURE_FD_EXPORT) += -DPVR_SECURE_FD_EXPORT
+SYS_CFLAGS.$(SUPPORT_SECURE_DRM_AUTH_EXPORT) += -DPVR_SECURE_DRM_AUTH_EXPORT
+
+SYS_CFLAGS.$(USE_PTHREADS) += -DUSE_PTHREADS
+SYS_CFLAGS.$(USE_GCC__thread_KEYWORD) += -DUSE_GCC__thread_KEYWORD
+SYS_CFLAGS.$(OPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP) += -DOPTIMISE_NON_NPTL_SINGLE_THREAD_TLS_LOOKUP
+SYS_CFLAGS.$(DISABLE_THREADS) += -DDISABLE_THREADS
+SYS_CFLAGS.$(SUPPORT_SGX_EVENT_OBJECT) += -DSUPPORT_SGX_EVENT_OBJECT
+SYS_CFLAGS.$(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) += -DSUPPORT_SGX_LOW_LATENCY_SCHEDULING
+SYS_CFLAGS.$(LDM_PLATFORM) += -DLDM_PLATFORM
+SYS_CFLAGS.$(LDM_PCI) += -DLDM_PCI
+SYS_CFLAGS.$(PVR_MANUAL_POWER_CONTROL) += -DPVR_MANUAL_POWER_CONTROL
+
+SYS_CFLAGS.$(PVR2D_ALT_2DHW) += -DPVR2D_ALT_2DHW
+
+SYS_CFLAGS.$(SUPPORT_SGX_HWPERF) += -DSUPPORT_SGX_HWPERF
+
+SYS_CFLAGS.$(SUPPORT_SLC) += -DSGX_FEATURE_SYSTEM_CACHE
+SYS_CFLAGS.$(BYPASS_SLC) += -DSGX_BYPASS_SYSTEM_CACHE
+
+SYS_CFLAGS.$(INTEL_D3_CHANGES) += -DINTEL_D3_CHANGES=1
+SYS_CFLAGS.$(INTEL_D3_PAD) += -DINTEL_D3_PAD=1
+SYS_CFLAGS.$(INTEL_D3_FLUSH) += -DINTEL_D3_FLUSH=1
+SYS_CFLAGS.$(INTEL_D3_DISABLE_TEXTURE_STREAM) += -DINTEL_D3_DISABLE_TEXTURE_STREAM=1
+SYS_CFLAGS.$(INTEL_D3_GDL) += -DINTEL_D3_GDL=1
+SYS_CFLAGS.$(INTEL_D3_NO_PCI_ENUM) += -DINTEL_D3_NO_PCI_ENUM=1
+SYS_CFLAGS.$(INTEL_D3_P_CHANGES) += -DINTEL_D3_P_CHANGES=1
+SYS_CFLAGS.$(INTEL_D3_CACHED_CBUF) += -DINTEL_D3_CACHED_CBUF=1
+SYS_CFLAGS.$(INTEL_D3_MEEGO) += -DINTEL_D3_MEEGO=1
+
+SYS_CFLAGS.$(SUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION) += -DSUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION
+
+SYS_CFLAGS.$(SUPPORT_LINUX_USING_WORKQUEUES) += -DPVR_LINUX_USING_WORKQUEUES \
+ -DPVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE \
+ -DPVR_LINUX_TIMERS_USING_WORKQUEUES \
+ -DSYS_CUSTOM_POWERLOCK_WRAP
+
+SYS_CFLAGS += -DDEBUG_LOG_PATH_TRUNCATE=\"$(PVR_BUILD_DIR)\"
+
+ALL_CFLAGS_kbuild = -DLINUX \
+ $(CBUILD) $(CBUILD.$(BUILD)) \
+ $(SYS_CFLAGS) $(SYS_CFLAGS.1) \
+ $(MODULE_CFLAGS) $(MODULE_CFLAGS.$(BUILD)) \
+ $(CORE) \
+ $(EXTRA_CFLAGS)
+
+ccflags-y := -Idrivers/staging/ice4100/sgx535 \
+ -Idrivers/staging/ice4100/sgx535/include \
+ -Idrivers/staging/ice4100/sgx535/include/env/linux \
+ -Idrivers/staging/ice4100/sgx535/bridged \
+ -Idrivers/staging/ice4100/sgx535/bridged/sgx \
+ -Idrivers/staging/ice4100/sgx535/devices/sgx \
+ -Idrivers/staging/ice4100/sgx535/system \
+ -Idrivers/staging/ice4100/sgx535/system/include \
+ -Idrivers/staging/ice4100/sgx535/system/sgx_intel_ce \
+ -Idrivers/staging/ice4100/sgx535/hwdefs \
+ -Idrivers/staging/ice4100/pal/include \
+ $(ALL_CFLAGS_kbuild)
+
+pvrsrvkm-y := osfunc.o \
+ mmap.o \
+ module.o \
+ pdump.o \
+ proc.o \
+ pvr_bridge_k.o \
+ pvr_debug.o \
+ pvr_drm.o \
+ mm.o \
+ mutils.o \
+ event.o \
+ osperproc.o \
+ common/buffer_manager.o \
+ common/devicemem.o \
+ common/deviceclass.o \
+ common/handle.o \
+ common/hash.o \
+ common/lists.o \
+ common/metrics.o \
+ common/pvrsrv.o \
+ common/queue.o \
+ common/ra.o \
+ common/resman.o \
+ common/power.o \
+ common/mem.o \
+ common/pdump_common.o \
+ common/perproc.o \
+ bridged/bridged_support.o \
+ bridged/bridged_pvr_bridge.o \
+ bridged/sgx/bridged_sgx_bridge.o \
+ devices/sgx/sgxinit.o \
+ devices/sgx/sgxpower.o \
+ devices/sgx/sgxreset.o \
+ devices/sgx/sgxutils.o \
+ devices/sgx/sgxkick.o \
+ devices/sgx/sgxtransfer.o \
+ devices/sgx/mmu.o \
+ devices/sgx/pb.o \
+ system/sgx_intel_ce/sysconfig.o \
+ system/sgx_intel_ce/sysutils.o
+
+obj-$(CONFIG_CE_SGX535) += pvrsrvkm.o
diff --git a/drivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.c b/drivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.c
new file mode 100755
index 00000000000..5cc012fb89b
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.c
@@ -0,0 +1,3419 @@
+/**********************************************************************
+ *
+ * Copyright (c) 2009-2010 Intel Corporation.
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge_km.h"
+#include "pvr_debug.h"
+#include "ra.h"
+#include "pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "msvdx_bridge.h"
+#endif
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+#include "pdump_km.h"
+#include "syscommon.h"
+
+#include "bridged_pvr_bridge.h"
+#if defined(SUPPORT_SGX)
+#include "bridged_sgx_bridge.h"
+#endif
+#if defined(SUPPORT_VGX)
+#include "bridged_vgx_bridge.h"
+#endif
+#if defined(SUPPORT_MSVDX)
+#include "bridged_msvdx_bridge.h"
+#endif
+
+#include "env_data.h"
+
+#if defined (__linux__)
+#include "mmap.h"
+#endif
+
+#include "srvkm.h"
+
+#ifdef INTEL_D3_PM
+#include "graphics_pm.h"
+#endif
+
+PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+ g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+#if defined(PVR_SECURE_HANDLES)
+static int abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static int *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+#else
+static int *pbSharedDeviceMemHeap = (int *)NULL;
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA * pProcData,
+ u32 ui32BridgeID, void *pvDest, void *pvSrc, u32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes +=
+ ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes += ui32Size;
+ return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA * pProcData,
+ u32 ui32BridgeID, void *pvDest, void *pvSrc, u32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes +=
+ ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes += ui32Size;
+ return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+#ifdef INTEL_D3_CHANGES
+
+static int
+PVRSRVWaitForWriteOpSyncBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WAIT_FOR_WRITE_OP_SYNC * psIn,
+ PVRSRV_BRIDGE_OUT_WAIT_FOR_WRITE_OP_SYNC * psOut,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hKernelSyncInfo = NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_WAIT_FOR_WRITE_OP_SYNC);
+
+ psOut->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hKernelSyncInfo,
+ psIn->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if (psOut->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psOut->eError =
+ PVRSRVWaitForWriteOpSyncKM((PVRSRV_KERNEL_SYNC_INFO *)
+ hKernelSyncInfo);
+
+ return 0;
+}
+
+#endif
+
+static int
+PVRSRVEnumerateDevicesBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_ENUMDEVICE * psEnumDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+ psEnumDeviceOUT->eError =
+ PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+ psEnumDeviceOUT->asDeviceIdentifier);
+
+ return 0;
+}
+
+static int
+PVRSRVAcquireDeviceDataBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *
+ psAcquireDevInfoIN,
+ PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *
+ psAcquireDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO);
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAcquireDeviceDataKM(psAcquireDevInfoIN->uiDevIndex,
+ psAcquireDevInfoIN->eDeviceType,
+ &hDevCookieInt);
+ if (psAcquireDevInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psAcquireDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psAcquireDevInfoOUT->hDevCookie,
+ hDevCookieInt,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+static int
+PVRSRVCreateDeviceMemContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *
+ psCreateDevMemContextIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *
+ psCreateDevMemContextOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDevMemContextInt;
+ u32 i;
+ int bCreated;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc,
+ PVRSRV_MAX_CLIENT_HEAPS + 1);
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psCreateDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if (psCreateDevMemContextOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psCreateDevMemContextOUT->eError =
+ PVRSRVCreateDeviceMemContextKM(hDevCookieInt,
+ psPerProc,
+ &hDevMemContextInt,
+ &psCreateDevMemContextOUT->
+ ui32ClientHeapCount,
+ &psCreateDevMemContextOUT->
+ sHeapInfo[0], &bCreated,
+ pbSharedDeviceMemHeap);
+
+ if (psCreateDevMemContextOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ if (bCreated) {
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ } else {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &psCreateDevMemContextOUT->hDevMemContext,
+ hDevMemContextInt,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if (psCreateDevMemContextOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+ }
+
+ for (i = 0; i < psCreateDevMemContextOUT->ui32ClientHeapCount; i++) {
+ void *hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+ if (abSharedDeviceMemHeap[i])
+#endif
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psCreateDevMemContextOUT->
+ sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ }
+#if defined(PVR_SECURE_HANDLES)
+ else {
+
+ if (bCreated) {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psCreateDevMemContextOUT->
+ sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDevMemContextOUT->
+ hDevMemContext);
+ } else {
+ psCreateDevMemContextOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psCreateDevMemContextOUT->
+ sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if (psCreateDevMemContextOUT->eError !=
+ PVRSRV_OK) {
+ return 0;
+ }
+ }
+ }
+#endif
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap =
+ hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVDestroyDeviceMemContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *
+ psDestroyDevMemContextIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDevMemContextInt;
+ int bDestroyed;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psDestroyDevMemContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psDestroyDevMemContextIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVDestroyDeviceMemContextKM(hDevCookieInt, hDevMemContextInt,
+ &bDestroyed);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ if (bDestroyed) {
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDevMemContextIN->
+ hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ }
+
+ return 0;
+}
+
+static int
+PVRSRVGetDeviceMemHeapInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *
+ psGetDevMemHeapInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *
+ psGetDevMemHeapInfoOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDevMemContextInt;
+ u32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc,
+ PVRSRV_MAX_CLIENT_HEAPS);
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psGetDevMemHeapInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if (psGetDevMemHeapInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psGetDevMemHeapInfoIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if (psGetDevMemHeapInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVGetDeviceMemHeapInfoKM(hDevCookieInt,
+ hDevMemContextInt,
+ &psGetDevMemHeapInfoOUT->
+ ui32ClientHeapCount,
+ &psGetDevMemHeapInfoOUT->sHeapInfo[0],
+ pbSharedDeviceMemHeap);
+
+ if (psGetDevMemHeapInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ for (i = 0; i < psGetDevMemHeapInfoOUT->ui32ClientHeapCount; i++) {
+ void *hDevMemHeapExt;
+
+#if defined(PVR_SECURE_HANDLES)
+ if (abSharedDeviceMemHeap[i])
+#endif
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->
+ sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ }
+#if defined(PVR_SECURE_HANDLES)
+ else {
+
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->
+ sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if (psGetDevMemHeapInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+ }
+#endif
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap =
+ hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+int
+PVRSRVAllocDeviceMemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM * psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM * psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc);
+#else
+static int
+PVRSRVAllocDeviceMemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM * psAllocDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM * psAllocDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ void *hDevCookieInt;
+ void *hDevMemHeapInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2);
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psAllocDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if (psAllocDeviceMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemHeapInt,
+ psAllocDeviceMemIN->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+
+ if (psAllocDeviceMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError =
+ PVRSRVAllocDeviceMemKM(hDevCookieInt,
+ psPerProc,
+ hDevMemHeapInt,
+ psAllocDeviceMemIN->ui32Attribs,
+ psAllocDeviceMemIN->ui32Size,
+ psAllocDeviceMemIN->ui32Alignment,
+ &psMemInfo, "");
+
+ if (psAllocDeviceMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ memset(&psAllocDeviceMemOUT->sClientMemInfo,
+ 0, sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+#if defined (__linux__)
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = 0;
+#else
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = psMemInfo->pvLinAddrKM;
+#endif
+ psAllocDeviceMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psAllocDeviceMemOUT->sClientMemInfo.ui32AllocSize =
+ psMemInfo->ui32AllocSize;
+ psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo =
+ psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ if (psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ) {
+
+ memset(&psAllocDeviceMemOUT->sClientSyncInfo,
+ 0, sizeof(PVRSRV_CLIENT_SYNC_INFO));
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo = NULL;
+ psAllocDeviceMemOUT->psKernelSyncInfo = NULL;
+ } else {
+
+ psAllocDeviceMemOUT->psKernelSyncInfo =
+ psMemInfo->psKernelSyncInfo;
+
+ psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psAllocDeviceMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psAllocDeviceMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.
+ hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psAllocDeviceMemOUT->sClientSyncInfo.
+ hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psAllocDeviceMemOUT->sClientMemInfo.
+ hKernelMemInfo);
+
+ psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
+ &psAllocDeviceMemOUT->sClientSyncInfo;
+
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#endif
+
+static int
+PVRSRVFreeDeviceMemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREEDEVICEMEM * psFreeDeviceMemIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ void *pvKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psFreeDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+ psFreeDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO *) pvKernelMemInfo;
+
+ if (psKernelMemInfo->ui32RefCount == 1) {
+ psRetOUT->eError =
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, pvKernelMemInfo);
+ } else {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVFreeDeviceMemBW: mappings are open "
+ "in other processes, deferring free!"));
+
+ psKernelMemInfo->bPendingFree = 1;
+ psRetOUT->eError = PVRSRV_OK;
+ }
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+static int
+PVRSRVExportDeviceMemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM * psExportDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *
+ psExportDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EXPORT_DEVICEMEM);
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psExportDeviceMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if (psExportDeviceMemOUT->eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVExportDeviceMemBW: can't find devcookie"));
+ return 0;
+ }
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&psKernelMemInfo,
+ psExportDeviceMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if (psExportDeviceMemOUT->eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVExportDeviceMemBW: can't find kernel meminfo"));
+ return 0;
+ }
+
+ psExportDeviceMemOUT->eError =
+ PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->hMemInfo,
+ psKernelMemInfo, PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psExportDeviceMemOUT->eError == PVRSRV_OK) {
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVExportDeviceMemBW: allocation is already exported"));
+ return 0;
+ }
+
+ psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psExportDeviceMemOUT->
+ hMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (psExportDeviceMemOUT->eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVExportDeviceMemBW: failed to allocate handle from global handle list"));
+ return 0;
+ }
+
+ psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
+
+ return 0;
+}
+
+static int
+PVRSRVMapDeviceMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY * psMapDevMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY * psMapDevMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psSrcKernelMemInfo = NULL;
+ PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo = NULL;
+ void *hDstDevMemHeap = NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_DEV_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2);
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (void **)
+ &psSrcKernelMemInfo,
+ psMapDevMemIN->
+ hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psMapDevMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDstDevMemHeap,
+ psMapDevMemIN->
+ hDstDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if (psMapDevMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
+ psSrcKernelMemInfo,
+ hDstDevMemHeap,
+ &psDstKernelMemInfo);
+ if (psMapDevMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ memset(&psMapDevMemOUT->sDstClientMemInfo,
+ 0, sizeof(psMapDevMemOUT->sDstClientMemInfo));
+ memset(&psMapDevMemOUT->sDstClientSyncInfo,
+ 0, sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+ psDstKernelMemInfo->pvLinAddrKM;
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = 0;
+ psMapDevMemOUT->sDstClientMemInfo.sDevVAddr =
+ psDstKernelMemInfo->sDevVAddr;
+ psMapDevMemOUT->sDstClientMemInfo.ui32Flags =
+ psDstKernelMemInfo->ui32Flags;
+ psMapDevMemOUT->sDstClientMemInfo.ui32AllocSize =
+ psDstKernelMemInfo->ui32AllocSize;
+ psMapDevMemOUT->sDstClientMemInfo.hMappingInfo =
+ psDstKernelMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
+ psDstKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = NULL;
+ psMapDevMemOUT->psDstKernelSyncInfo = NULL;
+
+ if (psDstKernelMemInfo->psKernelSyncInfo) {
+ psMapDevMemOUT->psDstKernelSyncInfo =
+ psDstKernelMemInfo->psKernelSyncInfo;
+
+ psMapDevMemOUT->sDstClientSyncInfo.psSyncData =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevMemOUT->sDstClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->
+ sWriteOpsCompleteDevVAddr;
+ psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->
+ sReadOpsCompleteDevVAddr;
+
+ psMapDevMemOUT->sDstClientSyncInfo.hMappingInfo =
+ psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->
+ sMemBlk.hOSMemHandle;
+
+ psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo =
+ &psMapDevMemOUT->sDstClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevMemOUT->sDstClientSyncInfo.
+ hKernelSyncInfo,
+ psDstKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevMemOUT->sDstClientMemInfo.
+ hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVUnmapDeviceMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY * psUnmapDevMemIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_DEV_MEMORY);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&psKernelMemInfo,
+ psUnmapDevMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnmapDevMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+static int
+PVRSRVMapDeviceClassMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *
+ psMapDevClassMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *
+ psMapDevClassMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ void *hOSMapInfo;
+ void *hDeviceClassBufferInt;
+ void *hDevMemContextInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2);
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+ &hDeviceClassBufferInt, &eHandleType,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ if (psMapDevClassMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psMapDevClassMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if (psMapDevClassMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ switch (eHandleType) {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+ case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapDevClassMemOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVMapDeviceClassMemoryKM(psPerProc,
+ hDevMemContextInt,
+ hDeviceClassBufferInt,
+ &psMemInfo, &hOSMapInfo);
+ if (psMapDevClassMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ memset(&psMapDevClassMemOUT->sClientMemInfo,
+ 0, sizeof(psMapDevClassMemOUT->sClientMemInfo));
+ memset(&psMapDevClassMemOUT->sClientSyncInfo,
+ 0, sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapDevClassMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psMapDevClassMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psMapDevClassMemOUT->sClientMemInfo.ui32AllocSize =
+ psMemInfo->ui32AllocSize;
+ psMapDevClassMemOUT->sClientMemInfo.hMappingInfo =
+ psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientMemInfo.
+ hKernelMemInfo, psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapDevClassMemIN->hDeviceClassBuffer);
+
+ psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = NULL;
+ psMapDevClassMemOUT->psKernelSyncInfo = NULL;
+
+ if (psMemInfo->psKernelSyncInfo) {
+ psMapDevClassMemOUT->psKernelSyncInfo =
+ psMemInfo->psKernelSyncInfo;
+
+ psMapDevClassMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psMapDevClassMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapDevClassMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.
+ hOSMemHandle;
+
+ psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo =
+ &psMapDevClassMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapDevClassMemOUT->sClientSyncInfo.
+ hKernelSyncInfo,
+ psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapDevClassMemOUT->sClientMemInfo.
+ hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVUnmapDeviceClassMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *
+ psUnmapDevClassMemIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvKernelMemInfo,
+ psUnmapDevClassMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVUnmapDeviceClassMemoryKM(pvKernelMemInfo);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnmapDevClassMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+#if defined(OS_PVRSRV_WRAP_EXT_MEM_BW)
+int
+PVRSRVWrapExtMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY * psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY * psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc);
+#else
+static int
+PVRSRVWrapExtMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY * psWrapExtMemIN,
+ PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY * psWrapExtMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDevMemContextInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ u32 ui32PageTableSize = 0;
+ IMG_SYS_PHYADDR *psSysPAddr = NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_WRAP_EXT_MEMORY);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2);
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psWrapExtMemIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if (psWrapExtMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psWrapExtMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psWrapExtMemIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if (psWrapExtMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ if (psWrapExtMemIN->ui32NumPageTableEntries) {
+ ui32PageTableSize = psWrapExtMemIN->ui32NumPageTableEntries
+ * sizeof(IMG_SYS_PHYADDR);
+
+ ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (void **)&psSysPAddr, 0,
+ "Page Table"));
+
+ if (CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSysPAddr,
+ psWrapExtMemIN->psSysPAddr,
+ ui32PageTableSize) != PVRSRV_OK) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize,
+ (void *)psSysPAddr, 0);
+
+ return -EFAULT;
+ }
+ }
+
+ psWrapExtMemOUT->eError =
+ PVRSRVWrapExtMemoryKM(hDevCookieInt,
+ psPerProc,
+ hDevMemContextInt,
+ psWrapExtMemIN->ui32ByteSize,
+ psWrapExtMemIN->ui32PageOffset,
+ psWrapExtMemIN->bPhysContig,
+ psSysPAddr,
+ psWrapExtMemIN->pvLinAddr,
+ psWrapExtMemIN->ui32Flags, &psMemInfo);
+ if (psWrapExtMemIN->ui32NumPageTableEntries) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize, (void *)psSysPAddr, 0);
+
+ }
+ if (psWrapExtMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM = psMemInfo->pvLinAddrKM;
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
+ psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
+ psWrapExtMemOUT->sClientMemInfo.ui32AllocSize =
+ psMemInfo->ui32AllocSize;
+ psWrapExtMemOUT->sClientMemInfo.hMappingInfo =
+ psMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ psWrapExtMemOUT->sClientSyncInfo.psSyncData =
+ psMemInfo->psKernelSyncInfo->psSyncData;
+ psWrapExtMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psWrapExtMemOUT->sClientSyncInfo.hMappingInfo =
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.
+ hOSMemHandle;
+
+ psWrapExtMemOUT->sClientMemInfo.psClientSyncInfo =
+ &psWrapExtMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psWrapExtMemOUT->sClientSyncInfo.
+ hKernelSyncInfo,
+ (void *)psMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc);
+
+ return 0;
+}
+#endif
+
+static int
+PVRSRVUnwrapExtMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY * psUnwrapExtMemIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVUnwrapExtMemoryKM((PVRSRV_KERNEL_MEM_INFO *) pvMemInfo);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psUnwrapExtMemIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+
+static int
+PVRSRVGetFreeDeviceMemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *
+ psGetFreeDeviceMemIN,
+ PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *
+ psGetFreeDeviceMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+ psGetFreeDeviceMemOUT->eError =
+ PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+ &psGetFreeDeviceMemOUT->ui32Total,
+ &psGetFreeDeviceMemOUT->ui32Free,
+ &psGetFreeDeviceMemOUT->ui32LargestBlock);
+
+ return 0;
+}
+
+static int
+PVRMMapOSMemHandleToMMapDataBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *
+ psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *
+ psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapOSMemHandleToMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->ui32MMapOffset,
+ &psMMapDataOUT->ui32ByteOffset,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+static int
+PVRMMapReleaseMMapDataBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA * psMMapDataIN,
+ PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA * psMMapDataOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+#if defined (__linux__)
+ psMMapDataOUT->eError =
+ PVRMMapReleaseMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->bMUnmap,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+#else
+ psMMapDataOUT->eError = PVRSRV_ERROR_NOT_SUPPORTED;
+#endif
+ return 0;
+}
+
+#ifdef PDUMP
+static int
+PDumpIsCaptureFrameBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *
+ psPDumpIsCapturingOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+ psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+ psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int
+PDumpCommentBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COMMENT * psPDumpCommentIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+ psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+ psPDumpCommentIN->ui32Flags);
+ return 0;
+}
+
+static int
+PDumpSetFrameBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SETFRAME * psPDumpSetFrameIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+
+ psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+ return 0;
+}
+
+static int
+PDumpRegWithFlagsBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPREG * psPDumpRegDumpIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+
+ psRetOUT->eError =
+ PDumpRegWithFlagsKM(psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpRegDumpIN->sHWReg.ui32RegVal,
+ psPDumpRegDumpIN->ui32Flags);
+
+ return 0;
+}
+
+static int
+PDumpRegPolBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_REGPOL * psPDumpRegPolIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+
+ psRetOUT->eError =
+ PDumpRegPolWithFlagsKM(psPDumpRegPolIN->sHWReg.ui32RegAddr,
+ psPDumpRegPolIN->sHWReg.ui32RegVal,
+ psPDumpRegPolIN->ui32Mask,
+ psPDumpRegPolIN->ui32Flags);
+
+ return 0;
+}
+
+static int
+PDumpMemPolBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_MEMPOL * psPDumpMemPolIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_MEMPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psPDumpMemPolIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_MEM_INFO *) pvMemInfo),
+ psPDumpMemPolIN->ui32Offset,
+ psPDumpMemPolIN->ui32Value,
+ psPDumpMemPolIN->ui32Mask,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ psPDumpMemPolIN->ui32Flags, MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static int
+PDumpMemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM * psPDumpMemDumpIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT, PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPMEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psPDumpMemDumpIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpMemDumpIN->pvAltLinAddr,
+ psPDumpMemDumpIN->pvLinAddr,
+ pvMemInfo,
+ psPDumpMemDumpIN->ui32Offset,
+ psPDumpMemDumpIN->ui32Bytes,
+ psPDumpMemDumpIN->ui32Flags, MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static int
+PDumpBitmapBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BITMAP * psPDumpBitmapIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+
+ psRetOUT->eError =
+ PDumpBitmapKM(&psPDumpBitmapIN->szFileName[0],
+ psPDumpBitmapIN->ui32FileOffset,
+ psPDumpBitmapIN->ui32Width,
+ psPDumpBitmapIN->ui32Height,
+ psPDumpBitmapIN->ui32StrideInBytes,
+ psPDumpBitmapIN->sDevBaseAddr,
+ psPDumpBitmapIN->ui32Size,
+ psPDumpBitmapIN->ePixelFormat,
+ psPDumpBitmapIN->eMemFormat,
+ psPDumpBitmapIN->ui32Flags);
+
+ return 0;
+}
+
+static int
+PDumpReadRegBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_READREG * psPDumpReadRegIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+
+ psRetOUT->eError =
+ PDumpReadRegKM(&psPDumpReadRegIN->szFileName[0],
+ psPDumpReadRegIN->ui32FileOffset,
+ psPDumpReadRegIN->ui32Address,
+ psPDumpReadRegIN->ui32Size,
+ psPDumpReadRegIN->ui32Flags);
+
+ return 0;
+}
+
+static int
+PDumpDriverInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO * psPDumpDriverInfoIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ u32 ui32PDumpFlags;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+
+ ui32PDumpFlags = 0;
+ if (psPDumpDriverInfoIN->bContinuous) {
+ ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+ }
+ psRetOUT->eError =
+ PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+ ui32PDumpFlags);
+
+ return 0;
+}
+
+static int
+PDumpSyncDumpBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC * psPDumpSyncDumpIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ u32 ui32Bytes = psPDumpSyncDumpIN->ui32Bytes;
+ void *pvSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPSYNC);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ psPDumpSyncDumpIN->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpMemUM(psPerProc,
+ psPDumpSyncDumpIN->pvAltLinAddr,
+ NULL,
+ ((PVRSRV_KERNEL_SYNC_INFO *) pvSyncInfo)->
+ psSyncDataMemInfoKM, psPDumpSyncDumpIN->ui32Offset,
+ ui32Bytes, 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *) pvSyncInfo)->
+ psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static int
+PDumpSyncPolBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL * psPDumpSyncPolIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ u32 ui32Offset;
+ void *pvSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SYNCPOL);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ psPDumpSyncPolIN->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ if (psPDumpSyncPolIN->bIsRead) {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ } else {
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ }
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((PVRSRV_KERNEL_SYNC_INFO *) pvSyncInfo)->
+ psSyncDataMemInfoKM, ui32Offset,
+ psPDumpSyncPolIN->ui32Value,
+ psPDumpSyncPolIN->ui32Mask, PDUMP_POLL_OPERATOR_EQUAL,
+ 0,
+ MAKEUNIQUETAG(((PVRSRV_KERNEL_SYNC_INFO *)
+ pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static int
+PDumpPDRegBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG * psPDumpPDRegDumpIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PDREG);
+
+ PDumpPDReg(psPDumpPDRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpPDRegDumpIN->sHWReg.ui32RegVal, PDUMP_PD_UNIQUETAG);
+
+ psRetOUT->eError = PVRSRV_OK;
+ return 0;
+}
+
+static int
+PDumpCycleCountRegReadBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ *
+ psPDumpCycleCountRegReadIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+
+ PDumpCycleCountRegRead(psPDumpCycleCountRegReadIN->ui32RegOffset,
+ psPDumpCycleCountRegReadIN->bLastFrame);
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int
+PDumpPDDevPAddrBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR * psPDumpPDDevPAddrIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvMemInfo,
+ psPDumpPDDevPAddrIN->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PDumpPDDevPAddrKM((PVRSRV_KERNEL_MEM_INFO *) pvMemInfo,
+ psPDumpPDDevPAddrIN->ui32Offset,
+ psPDumpPDDevPAddrIN->sPDDevPAddr,
+ MAKEUNIQUETAG(pvMemInfo), PDUMP_PD_UNIQUETAG);
+ return 0;
+}
+
+static int
+PDumpStartInitPhaseBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+
+ psRetOUT->eError = PDumpStartInitPhaseKM();
+
+ return 0;
+}
+
+static int
+PDumpStopInitPhaseBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+
+ psRetOUT->eError = PDumpStopInitPhaseKM();
+
+ return 0;
+}
+
+#endif
+
+static int
+PVRSRVGetMiscInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_MISC_INFO * psGetMiscInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_MISC_INFO * psGetMiscInfoOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_ERROR eError;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+ memcpy(&psGetMiscInfoOUT->sMiscInfo,
+ &psGetMiscInfoIN->sMiscInfo, sizeof(PVRSRV_MISC_INFO));
+
+ if (((psGetMiscInfoIN->sMiscInfo.
+ ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0)
+ &&
+ ((psGetMiscInfoIN->sMiscInfo.
+ ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0)) {
+
+ psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ if (((psGetMiscInfoIN->sMiscInfo.
+ ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0)
+ ||
+ ((psGetMiscInfoIN->sMiscInfo.
+ ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0)) {
+
+ ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.
+ ui32MemoryStrLen,
+ (void **)&psGetMiscInfoOUT->
+ sMiscInfo.pszMemoryStr, 0,
+ "Output string buffer"));
+
+ psGetMiscInfoOUT->eError =
+ PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+ eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+ psGetMiscInfoIN->sMiscInfo.
+ pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.
+ pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.
+ ui32MemoryStrLen);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (void *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = NULL;
+
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr =
+ psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
+
+ if (eError != PVRSRV_OK) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetMiscInfoBW Error copy to user"));
+ return -EFAULT;
+ }
+ } else {
+ psGetMiscInfoOUT->eError =
+ PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+ }
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ if (psGetMiscInfoIN->sMiscInfo.
+ ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) {
+ psGetMiscInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.
+ sGlobalEventObject.hOSEventKM,
+ psGetMiscInfoOUT->sMiscInfo.
+ sGlobalEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+ }
+
+ if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle) {
+
+ psGetMiscInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psGetMiscInfoOUT->sMiscInfo.
+ hSOCTimerRegisterOSMemHandle,
+ psGetMiscInfoOUT->sMiscInfo.
+ hSOCTimerRegisterOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ if (psGetMiscInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int
+PVRSRVConnectBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ PVRSRV_BRIDGE_OUT_CONNECT_SERVICES * psConnectServicesOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+ psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+ psConnectServicesOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int
+PVRSRVDisconnectBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int
+PVRSRVEnumerateDCBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUMCLASS * psEnumDispClassIN,
+ PVRSRV_BRIDGE_OUT_ENUMCLASS * psEnumDispClassOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
+
+ psEnumDispClassOUT->eError =
+ PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
+ &psEnumDispClassOUT->ui32NumDevices,
+ &psEnumDispClassOUT->ui32DevID[0]);
+
+ return 0;
+}
+
+static int
+PVRSRVOpenDCDeviceBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *
+ psOpenDispClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *
+ psOpenDispClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError, psPerProc,
+ 1);
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenDispClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if (psOpenDispClassDeviceOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psOpenDispClassDeviceOUT->eError =
+ PVRSRVOpenDCDeviceKM(psPerProc,
+ psOpenDispClassDeviceIN->ui32DeviceID,
+ hDevCookieInt, &hDispClassInfoInt);
+
+ if (psOpenDispClassDeviceOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenDispClassDeviceOUT->hDeviceKM,
+ hDispClassInfoInt,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenDispClassDeviceOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVCloseDCDeviceBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *
+ psCloseDispClassDeviceIN, PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, 0);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseDispClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ return 0;
+}
+
+static int
+PVRSRVEnumDCFormatsBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *
+ psEnumDispClassFormatsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *
+ psEnumDispClassFormatsOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS);
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassFormatsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psEnumDispClassFormatsOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psEnumDispClassFormatsOUT->eError =
+ PVRSRVEnumDCFormatsKM(pvDispClassInfoInt,
+ &psEnumDispClassFormatsOUT->ui32Count,
+ psEnumDispClassFormatsOUT->asFormat);
+
+ return 0;
+}
+
+static int
+PVRSRVEnumDCDimsBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS * psEnumDispClassDimsIN,
+ PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *
+ psEnumDispClassDimsOUT, PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS);
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psEnumDispClassDimsIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if (psEnumDispClassDimsOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psEnumDispClassDimsOUT->eError =
+ PVRSRVEnumDCDimsKM(pvDispClassInfoInt,
+ &psEnumDispClassDimsIN->sFormat,
+ &psEnumDispClassDimsOUT->ui32Count,
+ psEnumDispClassDimsOUT->asDim);
+
+ return 0;
+}
+
+static int
+PVRSRVGetDCSystemBufferBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *
+ psGetDispClassSysBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *
+ psGetDispClassSysBufferOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hBufferInt;
+ void *pvDispClassInfoInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError, psPerProc,
+ 1);
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfoInt,
+ psGetDispClassSysBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psGetDispClassSysBufferOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetDispClassSysBufferOUT->eError =
+ PVRSRVGetDCSystemBufferKM(pvDispClassInfoInt, &hBufferInt);
+
+ if (psGetDispClassSysBufferOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetDispClassSysBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)
+ (PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE |
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassSysBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassSysBufferOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVGetDCInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO * psGetDispClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO * psGetDispClassInfoOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_GET_DISPCLASS_INFO);
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psGetDispClassInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetDispClassInfoOUT->eError =
+ PVRSRVGetDCInfoKM(pvDispClassInfo,
+ &psGetDispClassInfoOUT->sDisplayInfo);
+
+ return 0;
+}
+
+static int
+PVRSRVCreateDCSwapChainBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN *
+ psCreateDispClassSwapChainIN,
+ PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN *
+ psCreateDispClassSwapChainOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *hSwapChainInt;
+ u32 ui32SwapChainID;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError,
+ psPerProc, 1);
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psCreateDispClassSwapChainIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+
+ if (psCreateDispClassSwapChainOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+ psCreateDispClassSwapChainIN->ui32Flags,
+ &psCreateDispClassSwapChainIN->
+ sDstSurfAttrib,
+ &psCreateDispClassSwapChainIN->
+ sSrcSurfAttrib,
+ psCreateDispClassSwapChainIN->
+ ui32BufferCount,
+ psCreateDispClassSwapChainIN->
+ ui32OEMFlags, &hSwapChainInt,
+ &ui32SwapChainID);
+
+ if (psCreateDispClassSwapChainOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psCreateDispClassSwapChainOUT->hSwapChain,
+ hSwapChainInt,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psCreateDispClassSwapChainIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDispClassSwapChainOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVDestroyDCSwapChainBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN *
+ psDestroyDispClassSwapChainIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSwapChain,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVDestroyDCSwapChainKM(pvSwapChain);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psDestroyDispClassSwapChainIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ return 0;
+}
+
+static int
+PVRSRVSetDCDstRectBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *
+ psSetDispClassDstRectIN, PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassDstRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassDstRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstRectKM(pvDispClassInfo,
+ pvSwapChain, &psSetDispClassDstRectIN->sRect);
+
+ return 0;
+}
+
+static int
+PVRSRVSetDCSrcRectBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *
+ psSetDispClassSrcRectIN, PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassSrcRectIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassSrcRectIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcRectKM(pvDispClassInfo,
+ pvSwapChain, &psSetDispClassSrcRectIN->sRect);
+
+ return 0;
+}
+
+static int
+PVRSRVSetDCDstColourKeyBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *
+ psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCDstColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static int
+PVRSRVSetDCSrcColourKeyBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *
+ psSetDispClassColKeyIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSetDispClassColKeyIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSetDispClassColKeyIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSetDCSrcColourKeyKM(pvDispClassInfo,
+ pvSwapChain,
+ psSetDispClassColKeyIN->ui32CKColour);
+
+ return 0;
+}
+
+static int
+PVRSRVGetDCBuffersBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *
+ psGetDispClassBuffersIN,
+ PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *
+ psGetDispClassBuffersOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *pvSwapChain;
+ u32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError, psPerProc,
+ PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psGetDispClassBuffersIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psGetDispClassBuffersOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psGetDispClassBuffersIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN);
+ if (psGetDispClassBuffersOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetDispClassBuffersOUT->eError =
+ PVRSRVGetDCBuffersKM(pvDispClassInfo,
+ pvSwapChain,
+ &psGetDispClassBuffersOUT->ui32BufferCount,
+ psGetDispClassBuffersOUT->ahBuffer);
+ if (psGetDispClassBuffersOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ PVR_ASSERT(psGetDispClassBuffersOUT->ui32BufferCount <=
+ PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ for (i = 0; i < psGetDispClassBuffersOUT->ui32BufferCount; i++) {
+ void *hBufferExt;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &hBufferExt,
+ psGetDispClassBuffersOUT->ahBuffer[i],
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)
+ (PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE |
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetDispClassBuffersIN->hSwapChain);
+
+ psGetDispClassBuffersOUT->ahBuffer[i] = hBufferExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDispClassBuffersOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVSwapToDCBufferBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *
+ psSwapDispClassBufferIN, PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *pvSwapChainBuf;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChainBuf,
+ psSwapDispClassBufferIN->hBuffer,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVSwapToDCBufferKM(pvDispClassInfo,
+ pvSwapChainBuf,
+ psSwapDispClassBufferIN->ui32SwapInterval,
+ psSwapDispClassBufferIN->hPrivateTag,
+ psSwapDispClassBufferIN->ui32ClipRectCount,
+ psSwapDispClassBufferIN->sClipRect);
+
+ return 0;
+}
+
+static int
+PVRSRVSwapToDCSystemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *
+ psSwapDispClassSystemIN, PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvDispClassInfo;
+ void *pvSwapChain;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassSystemIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSwapDispClassSystemIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ psSwapDispClassSystemIN->hDeviceKM);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+ psRetOUT->eError = PVRSRVSwapToDCSystemKM(pvDispClassInfo, pvSwapChain);
+
+ return 0;
+}
+
+static int
+PVRSRVOpenBCDeviceBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *
+ psOpenBufferClassDeviceIN,
+ PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *
+ psOpenBufferClassDeviceOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevCookieInt;
+ void *hBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError, psPerProc,
+ 1);
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psOpenBufferClassDeviceIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if (psOpenBufferClassDeviceOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psOpenBufferClassDeviceOUT->eError =
+ PVRSRVOpenBCDeviceKM(psPerProc,
+ psOpenBufferClassDeviceIN->ui32DeviceID,
+ hDevCookieInt, &hBufClassInfo);
+ if (psOpenBufferClassDeviceOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psOpenBufferClassDeviceOUT->hDeviceKM,
+ hBufClassInfo,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psOpenBufferClassDeviceOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVCloseBCDeviceBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *
+ psCloseBufferClassDeviceIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psCloseBufferClassDeviceIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVCloseBCDeviceKM(pvBufClassInfo, 0);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psCloseBufferClassDeviceIN->
+ hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+
+ return 0;
+}
+
+static int
+PVRSRVGetBCInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *
+ psGetBufferClassInfoIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *
+ psGetBufferClassInfoOUT, PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvBufClassInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO);
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassInfoIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if (psGetBufferClassInfoOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetBufferClassInfoOUT->eError =
+ PVRSRVGetBCInfoKM(pvBufClassInfo,
+ &psGetBufferClassInfoOUT->sBufferInfo);
+ return 0;
+}
+
+static int
+PVRSRVGetBCBufferBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *
+ psGetBufferClassBufferIN,
+ PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *
+ psGetBufferClassBufferOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *pvBufClassInfo;
+ void *hBufferInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError, psPerProc,
+ 1);
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvBufClassInfo,
+ psGetBufferClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_BUF_INFO);
+ if (psGetBufferClassBufferOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetBufferClassBufferOUT->eError =
+ PVRSRVGetBCBufferKM(pvBufClassInfo,
+ psGetBufferClassBufferIN->ui32BufferIndex,
+ &hBufferInt);
+
+ if (psGetBufferClassBufferOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psGetBufferClassBufferOUT->hBuffer,
+ hBufferInt,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ (PVRSRV_HANDLE_ALLOC_FLAG)
+ (PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE |
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED),
+ psGetBufferClassBufferIN->hDeviceKM);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetBufferClassBufferOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVAllocSharedSysMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *
+ psAllocSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *
+ psAllocSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc, 1);
+
+ psAllocSharedSysMemOUT->eError =
+ PVRSRVAllocSharedSysMemoryKM(psPerProc,
+ psAllocSharedSysMemIN->ui32Flags,
+ psAllocSharedSysMemIN->ui32Size,
+ &psKernelMemInfo);
+ if (psAllocSharedSysMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ memset(&psAllocSharedSysMemOUT->sClientMemInfo,
+ 0, sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psAllocSharedSysMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psAllocSharedSysMemOUT->sClientMemInfo.ui32AllocSize =
+ psKernelMemInfo->ui32AllocSize;
+ psAllocSharedSysMemOUT->sClientMemInfo.hMappingInfo =
+ psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psAllocSharedSysMemOUT->sClientMemInfo.
+ hKernelMemInfo, psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psAllocSharedSysMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVFreeSharedSysMemoryBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *
+ psFreeSharedSysMemIN,
+ PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *
+ psFreeSharedSysMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM);
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&psKernelMemInfo,
+ psFreeSharedSysMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+
+ if (psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVFreeSharedSysMemoryKM(psKernelMemInfo);
+ if (psFreeSharedSysMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psFreeSharedSysMemOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psFreeSharedSysMemIN->psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ return 0;
+}
+
+static int
+PVRSRVMapMemInfoMemBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM * psMapMemInfoMemIN,
+ PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM * psMapMemInfoMemOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_HANDLE_TYPE eHandleType;
+ void *hParent;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MAP_MEMINFO_MEM);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc, 2);
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
+ (void **)&psKernelMemInfo,
+ &eHandleType,
+ psMapMemInfoMemIN->hKernelMemInfo);
+ if (psMapMemInfoMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ switch (eHandleType) {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+#endif
+ break;
+ default:
+ psMapMemInfoMemOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psMapMemInfoMemOUT->eError =
+ PVRSRVGetParentHandle(psPerProc->psHandleBase,
+ &hParent,
+ psMapMemInfoMemIN->hKernelMemInfo,
+ eHandleType);
+ if (psMapMemInfoMemOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+ if (hParent == NULL) {
+ hParent = psMapMemInfoMemIN->hKernelMemInfo;
+ }
+
+ memset(&psMapMemInfoMemOUT->sClientMemInfo,
+ 0, sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapMemInfoMemOUT->sClientMemInfo.sDevVAddr =
+ psKernelMemInfo->sDevVAddr;
+ psMapMemInfoMemOUT->sClientMemInfo.ui32Flags =
+ psKernelMemInfo->ui32Flags;
+ psMapMemInfoMemOUT->sClientMemInfo.ui32AllocSize =
+ psKernelMemInfo->ui32AllocSize;
+ psMapMemInfoMemOUT->sClientMemInfo.hMappingInfo =
+ psKernelMemInfo->sMemBlk.hOSMemHandle;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientMemInfo.
+ hKernelMemInfo, psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI, hParent);
+
+ if (psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) {
+
+ memset(&psMapMemInfoMemOUT->sClientSyncInfo,
+ 0, sizeof(PVRSRV_CLIENT_SYNC_INFO));
+ psMapMemInfoMemOUT->psKernelSyncInfo = NULL;
+ } else {
+
+ psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
+ psKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapMemInfoMemOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->
+ sWriteOpsCompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psMapMemInfoMemOUT->sClientSyncInfo.hMappingInfo =
+ psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->
+ sMemBlk.hOSMemHandle;
+
+ psMapMemInfoMemOUT->sClientMemInfo.psClientSyncInfo =
+ &psMapMemInfoMemOUT->sClientSyncInfo;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapMemInfoMemOUT->sClientSyncInfo.
+ hKernelSyncInfo,
+ psKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psMapMemInfoMemOUT->sClientMemInfo.
+ hKernelMemInfo);
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psMapMemInfoMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static int
+MMU_GetPDDevPAddrBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR * psGetMmuPDDevPAddrIN,
+ PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR *
+ psGetMmuPDDevPAddrOUT, PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hDevMemContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR);
+
+ psGetMmuPDDevPAddrOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
+ psGetMmuPDDevPAddrIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if (psGetMmuPDDevPAddrOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psGetMmuPDDevPAddrOUT->sPDDevPAddr =
+ BM_GetDeviceNode(hDevMemContextInt)->
+ pfnMMUGetPDDevPAddr(BM_GetMMUContextFromMemContext
+ (hDevMemContextInt));
+ if (psGetMmuPDDevPAddrOUT->sPDDevPAddr.uiAddr) {
+ psGetMmuPDDevPAddrOUT->eError = PVRSRV_OK;
+ } else {
+ psGetMmuPDDevPAddrOUT->eError = PVRSRV_ERROR_GENERIC;
+ }
+ return 0;
+}
+
+int
+DummyBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ void *psBridgeOut, PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %lu (%s) mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID,
+ g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR, "%s: BRIDGE ERROR: BridgeID %lu mapped to "
+ "Dummy Wrapper (probably not what you want!)",
+ __FUNCTION__, ui32BridgeID));
+#endif
+ return -ENOTTY;
+}
+
+void
+_SetDispatchTableEntry(u32 ui32Index,
+ const char *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const char *pszFunctionName)
+{
+ static u32 ui32PrevIndex = ~0UL;
+
+#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
+
+ PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index,
+ pszIOCName, pszFunctionName));
+#endif
+
+#if defined(INTEL_D3_P_CHANGES)
+ if (ui32Index >= BRIDGE_DISPATCH_TABLE_ENTRY_COUNT) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: ui32BridgeID = %d is out if range!", __FUNCTION__,
+ ui32Index));
+ return;
+ }
+#endif
+
+ if (g_BridgeDispatchTable[ui32Index].pfFunction) {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry for %s",
+ __FUNCTION__, pszIOCName,
+ g_BridgeDispatchTable[ui32Index].pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: BUG!: Adding dispatch table entry for %s clobbers an existing entry (index=%lu)",
+ __FUNCTION__, pszIOCName, ui32Index));
+#endif
+ PVR_DPF((PVR_DBG_ERROR,
+ "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+ __FUNCTION__));
+ }
+
+ if ((ui32PrevIndex != ~0UL) &&
+ ((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
+ (ui32Index <= ui32PrevIndex))) {
+#if defined(DEBUG_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %lu (%s) and %lu (%s)",
+ __FUNCTION__, ui32PrevIndex,
+ g_BridgeDispatchTable[ui32PrevIndex].pszIOCName,
+ ui32Index, pszIOCName));
+#else
+ PVR_DPF((PVR_DBG_WARNING,
+ "%s: There is a gap in the dispatch table between indices %u and %u (%s)",
+ __FUNCTION__, (u32) ui32PrevIndex, (u32) ui32Index,
+ pszIOCName));
+#endif
+ PVR_DPF((PVR_DBG_ERROR,
+ "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+ __FUNCTION__));
+ }
+
+ g_BridgeDispatchTable[ui32Index].pfFunction = pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32Index].pszIOCName = pszIOCName;
+ g_BridgeDispatchTable[ui32Index].pszFunctionName = pszFunctionName;
+ g_BridgeDispatchTable[ui32Index].ui32CallCount = 0;
+ g_BridgeDispatchTable[ui32Index].ui32CopyFromUserTotalBytes = 0;
+#endif
+
+ ui32PrevIndex = ui32Index;
+}
+
+static int
+PVRSRVInitSrvConnectBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+
+ if (!OSProcHasPrivSrvInit()
+ || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING)
+ || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN)) {
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+#if defined (__linux__)
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, 1);
+#endif
+ psPerProc->bInitProcess = 1;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int
+PVRSRVInitSrvDisconnectBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *
+ psInitSrvDisconnectIN,
+ PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_INITSRV_DISCONNECT);
+
+ if (!psPerProc->bInitProcess) {
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psPerProc->bInitProcess = 0;
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, 0);
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, 1);
+
+ psRetOUT->eError =
+ PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL,
+ (((psRetOUT->eError == PVRSRV_OK)
+ && (psInitSrvDisconnectIN->bInitSuccesful)))
+ ? 1 : 0);
+
+ return 0;
+}
+
+static int
+PVRSRVEventObjectWaitBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *
+ psEventObjectWaitIN, PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hOSEventKM;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_WAIT);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectWaitIN->hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = OSEventObjectWait(hOSEventKM);
+
+ return 0;
+}
+
+static int
+PVRSRVEventObjectOpenBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *
+ psEventObjectOpenIN,
+ PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *
+ psEventObjectOpenOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_EVENT_OBJECT_OPEN);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc, 1);
+
+ psEventObjectOpenOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psEventObjectOpenIN->sEventObject.hOSEventKM,
+ psEventObjectOpenIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+
+ if (psEventObjectOpenOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psEventObjectOpenOUT->eError =
+ OSEventObjectOpen(&psEventObjectOpenIN->sEventObject,
+ &psEventObjectOpenOUT->hOSEvent);
+
+ if (psEventObjectOpenOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psEventObjectOpenOUT->hOSEvent,
+ psEventObjectOpenOUT->hOSEvent,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psEventObjectOpenOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static int
+PVRSRVEventObjectCloseBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *
+ psEventObjectCloseIN, PVRSRV_BRIDGE_RETURN * psRetOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hOSEventKM;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psEventObjectCloseIN->sEventObject.hOSEventKM,
+ psEventObjectCloseIN->sEventObject.hOSEventKM,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT);
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &hOSEventKM,
+ psEventObjectCloseIN->
+ hOSEventKM,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT);
+
+ if (psRetOUT->eError != PVRSRV_OK) {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ OSEventObjectClose(&psEventObjectCloseIN->sEventObject, hOSEventKM);
+
+ return 0;
+}
+
+typedef struct _MODIFY_SYNC_OP_INFO {
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ u32 ui32ModifyFlags;
+ u32 ui32ReadOpsPendingSnapShot;
+ u32 ui32WriteOpsPendingSnapShot;
+} MODIFY_SYNC_OP_INFO;
+
+static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(void *pvParam, u32 ui32Param)
+{
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ if (!pvParam) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "ModifyCompleteSyncOpsCallBack: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psModSyncOpInfo = (MODIFY_SYNC_OP_INFO *) pvParam;
+ psKernelSyncInfo = psModSyncOpInfo->psKernelSyncInfo;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if ((psModSyncOpInfo->ui32WriteOpsPendingSnapShot ==
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
+ && (psModSyncOpInfo->ui32ReadOpsPendingSnapShot ==
+ psKernelSyncInfo->psSyncData->ui32ReadOpsComplete)) {
+ goto OpFlushedComplete;
+ }
+ PVR_DPF((PVR_DBG_ERROR,
+ "ModifyCompleteSyncOpsCallBack: waiting for old Ops to flush"));
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "ModifyCompleteSyncOpsCallBack: waiting for old Ops to flush timed out"));
+
+ return PVRSRV_ERROR_TIMEOUT;
+
+OpFlushedComplete:
+
+ if (psModSyncOpInfo->
+ ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC) {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+ }
+
+ if (psModSyncOpInfo->
+ ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC) {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MODIFY_SYNC_OP_INFO),
+ (void *)psModSyncOpInfo, 0);
+
+ PVRSRVCommandCompleteCallbacks();
+
+ return PVRSRV_OK;
+}
+
+static int
+PVRSRVModifyPendingSyncOpsBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_PENDING_SYNC_OPS *
+ psModifySyncOpsIN,
+ PVRSRV_BRIDGE_OUT_MODIFY_PENDING_SYNC_OPS *
+ psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ void *hKernelSyncInfo;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ MODIFY_SYNC_OP_INFO *psModSyncOpInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hKernelSyncInfo,
+ psModifySyncOpsIN->
+ hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVModifyPendingSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ psKernelSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) hKernelSyncInfo;
+
+ if (psKernelSyncInfo->hResItem != NULL) {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
+ return 0;
+ }
+
+ ASSIGN_AND_EXIT_ON_ERROR(psModifySyncOpsOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(MODIFY_SYNC_OP_INFO),
+ (void **)&psModSyncOpInfo, 0,
+ "ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
+
+ psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
+ psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
+ psModSyncOpInfo->ui32ReadOpsPendingSnapShot =
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot =
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ psModifySyncOpsOUT->ui32ReadOpsPending =
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ psModifySyncOpsOUT->ui32WriteOpsPending =
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if (psModifySyncOpsIN->
+ ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC) {
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ if (psModifySyncOpsIN->
+ ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC) {
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+ }
+
+ psKernelSyncInfo->hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_MODIFY_SYNC_OPS, psModSyncOpInfo, 0,
+ ModifyCompleteSyncOpsCallBack);
+ return 0;
+}
+
+static int
+PVRSRVModifyCompleteSyncOpsBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MODIFY_COMPLETE_SYNC_OPS *
+ psModifySyncOpsIN,
+ PVRSRV_BRIDGE_RETURN * psModifySyncOpsOUT,
+ PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)
+ &psKernelSyncInfo,
+ psModifySyncOpsIN->
+ hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVModifyCompleteSyncOpsBW: PVRSRVLookupHandle failed"));
+ return 0;
+ }
+
+ if (psKernelSyncInfo->hResItem == NULL) {
+
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ eError = ResManFreeResByPtr(psKernelSyncInfo->hResItem);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVModifyCompleteSyncOpsBW: ResManFreeResByPtr failed"));
+ return 0;
+ }
+
+ psKernelSyncInfo->hResItem = NULL;
+
+ return 0;
+}
+
+PVRSRV_ERROR CommonBridgeInit(void)
+{
+ u32 i;
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DEVICES,
+ PVRSRVEnumerateDevicesBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO,
+ PVRSRVAcquireDeviceDataBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_DEVICEINFO, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT,
+ PVRSRVCreateDeviceMemContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT,
+ PVRSRVDestroyDeviceMemContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO,
+ PVRSRVGetDeviceMemHeapInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_DEVICEMEM,
+ PVRSRVAllocDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEVICEMEM,
+ PVRSRVFreeDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETFREE_DEVICEMEM,
+ PVRSRVGetFreeDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_COMMANDQUEUE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA,
+ PVRMMapOSMemHandleToMMapDataBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CONNECT_SERVICES, PVRSRVConnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DISCONNECT_SERVICES,
+ PVRSRVDisconnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_DEVICE_MEM, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DEVICEMEMINFO, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_DEV_VIRTMEM, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_EXT_MEMORY, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_EXT_MEMORY, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEV_MEMORY,
+ PVRSRVMapDeviceMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEV_MEMORY,
+ PVRSRVUnmapDeviceMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY,
+ PVRSRVMapDeviceClassMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY,
+ PVRSRVUnmapDeviceClassMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EXPORT_DEVICEMEM,
+ PVRSRVExportDeviceMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MMAP_DATA,
+ PVRMMapReleaseMMapDataBW);
+
+#ifdef INTEL_D3_CHANGES
+ SetDispatchTableEntry(PVRSRV_BRIDGE_WAIT_FOR_WRITE_OP_SYNC,
+ PVRSRVWaitForWriteOpSyncBW);
+#endif
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
+
+#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES, DummyBW);
+#endif
+
+#if defined(PDUMP)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPMEM, PDumpMemBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REG, PDumpRegWithFlagsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_REGPOL, PDumpRegPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_COMMENT, PDumpCommentBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SETFRAME, PDumpSetFrameBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_ISCAPTURING,
+ PDumpIsCaptureFrameBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPBITMAP, PDumpBitmapBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPREADREG, PDumpReadRegBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_SYNCPOL, PDumpSyncPolBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPSYNC, PDumpSyncDumpBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DRIVERINFO,
+ PDumpDriverInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_PDREG, PDumpPDRegBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR,
+ PDumpPDDevPAddrBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ,
+ PDumpCycleCountRegReadBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STARTINITPHASE,
+ PDumpStartInitPhaseBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STOPINITPHASE,
+ PDumpStopInitPhaseBW);
+#endif
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE,
+ PVRSRVOpenDCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE,
+ PVRSRVCloseDCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS,
+ PVRSRVEnumDCFormatsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS,
+ PVRSRVEnumDCDimsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER,
+ PVRSRVGetDCSystemBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO,
+ PVRSRVGetDCInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN,
+ PVRSRVCreateDCSwapChainBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN,
+ PVRSRVDestroyDCSwapChainBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT,
+ PVRSRVSetDCDstRectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT,
+ PVRSRVSetDCSrcRectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY,
+ PVRSRVSetDCDstColourKeyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY,
+ PVRSRVSetDCSrcColourKeyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS,
+ PVRSRVGetDCBuffersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER,
+ PVRSRVSwapToDCBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM,
+ PVRSRVSwapToDCSystemBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE,
+ PVRSRVOpenBCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE,
+ PVRSRVCloseBCDeviceBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO,
+ PVRSRVGetBCInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER,
+ PVRSRVGetBCBufferBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY,
+ PVRSRVWrapExtMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY,
+ PVRSRVUnwrapExtMemoryBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM,
+ PVRSRVAllocSharedSysMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM,
+ PVRSRVFreeSharedSysMemoryBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM,
+ PVRSRVMapMemInfoMemBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR,
+ MMU_GetPDDevPAddrBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT,
+ PVRSRVInitSrvConnectBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT,
+ PVRSRVInitSrvDisconnectBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT,
+ PVRSRVEventObjectWaitBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN,
+ PVRSRVEventObjectOpenBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE,
+ PVRSRVEventObjectCloseBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_PENDING_SYNC_OPS,
+ PVRSRVModifyPendingSyncOpsBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MODIFY_COMPLETE_SYNC_OPS,
+ PVRSRVModifyCompleteSyncOpsBW);
+
+#if defined (SUPPORT_SGX)
+ SetSGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_VGX)
+ SetVGXDispatchTableEntry();
+#endif
+#if defined (SUPPORT_MSVDX)
+ SetMSVDXDispatchTableEntry();
+#endif
+
+ for (i = 0; i < BRIDGE_DISPATCH_TABLE_ENTRY_COUNT; i++) {
+ if (!g_BridgeDispatchTable[i].pfFunction) {
+ g_BridgeDispatchTable[i].pfFunction = DummyBW;
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[i].pszIOCName =
+ "_PVRSRV_BRIDGE_DUMMY";
+ g_BridgeDispatchTable[i].pszFunctionName = "DummyBW";
+ g_BridgeDispatchTable[i].ui32CallCount = 0;
+ g_BridgeDispatchTable[i].ui32CopyFromUserTotalBytes = 0;
+ g_BridgeDispatchTable[i].ui32CopyToUserTotalBytes = 0;
+#endif
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+int BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
+{
+
+ void *psBridgeIn;
+ void *psBridgeOut;
+ BridgeWrapperFunction pfBridgeHandler;
+ u32 ui32BridgeID = psBridgePackageKM->ui32BridgeID;
+ int err = -EFAULT;
+
+#if defined(DEBUG_TRACE_BRIDGE_KM)
+ PVR_DPF((PVR_DBG_ERROR, "%s: %s",
+ __FUNCTION__, g_BridgeDispatchTable[ui32BridgeID].pszIOCName));
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[ui32BridgeID].ui32CallCount++;
+ g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+
+ if (!psPerProc->bInitProcess) {
+ if (PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN)) {
+ if (!PVRSRVGetInitServerState
+ (PVRSRV_INIT_SERVER_SUCCESSFUL)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Initialisation failed. Driver unusable.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ } else {
+ if (PVRSRVGetInitServerState
+ (PVRSRV_INIT_SERVER_RUNNING)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Initialisation is in progress",
+ __FUNCTION__));
+ goto return_fault;
+ } else {
+
+ switch (ui32BridgeID) {
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_DISCONNECT_SERVICES):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_CONNECT):
+ case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_INITSRV_DISCONNECT):
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Driver initialisation not completed yet.",
+ __FUNCTION__));
+ goto return_fault;
+ }
+ }
+ }
+ }
+#ifdef INTEL_D3_PM
+ graphics_pm_wait_not_suspended();
+#endif
+
+#if defined(__linux__)
+ {
+
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ psBridgeIn =
+ ((ENV_DATA *) psSysData->pvEnvSpecificData)->pvBridgeData;
+ psBridgeOut =
+ (void *)((IMG_PBYTE) psBridgeIn +
+ PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+ if (psBridgePackageKM->ui32InBufferSize > 0) {
+ if (!OSAccessOK(PVR_VERIFY_READ,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->ui32InBufferSize)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: Invalid pvParamIn pointer",
+ __FUNCTION__));
+ }
+
+ if (CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgeIn,
+ psBridgePackageKM->pvParamIn,
+ psBridgePackageKM->
+ ui32InBufferSize)
+ != PVRSRV_OK) {
+ goto return_fault;
+ }
+ }
+ }
+#else
+ psBridgeIn = psBridgePackageKM->pvParamIn;
+ psBridgeOut = psBridgePackageKM->pvParamOut;
+#endif
+
+ if (ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "%s: ui32BridgeID = %d is out if range!", __FUNCTION__,
+ ui32BridgeID));
+ goto return_fault;
+ }
+ pfBridgeHandler =
+ (BridgeWrapperFunction) g_BridgeDispatchTable[ui32BridgeID].
+ pfFunction;
+ err = pfBridgeHandler(ui32BridgeID, psBridgeIn, psBridgeOut, psPerProc);
+ if (err < 0) {
+ goto return_fault;
+ }
+
+#if defined(__linux__)
+
+ if (CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psBridgePackageKM->pvParamOut,
+ psBridgeOut, psBridgePackageKM->ui32OutBufferSize)
+ != PVRSRV_OK) {
+ goto return_fault;
+ }
+#endif
+
+ err = 0;
+return_fault:
+ ReleaseHandleBatch(psPerProc);
+ return err;
+}
diff --git a/drivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.h b/drivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.h
new file mode 100755
index 00000000000..eb5b48ab1dd
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/bridged/bridged_pvr_bridge.h
@@ -0,0 +1,218 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_PVR_BRIDGE_H__
+#define __BRIDGED_PVR_BRIDGE_H__
+
+#include "pvr_bridge.h"
+
+#if defined(__linux__)
+#define PVRSRV_GET_BRIDGE_ID(X) _IOC_NR(X)
+#else
+#define PVRSRV_GET_BRIDGE_ID(X) (X - PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST))
+#endif
+
+#ifndef ENOMEM
+#define ENOMEM 12
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef ENOTTY
+#define ENOTTY 25
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+PVRSRV_ERROR
+CopyFromUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ u32 ui32BridgeID,
+ void *pvDest,
+ void *pvSrc,
+ u32 ui32Size);
+PVRSRV_ERROR
+CopyToUserWrapper(PVRSRV_PER_PROCESS_DATA *pProcData,
+ u32 ui32BridgeID,
+ void *pvDest,
+ void *pvSrc,
+ u32 ui32Size);
+#else
+#define CopyFromUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size)
+#define CopyToUserWrapper(pProcData, ui32BridgeID, pvDest, pvSrc, ui32Size) \
+ OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size)
+#endif
+
+
+#define ASSIGN_AND_RETURN_ON_ERROR(error, src, res) \
+ do \
+ { \
+ (error) = (src); \
+ if ((error) != PVRSRV_OK) \
+ { \
+ return (res); \
+ } \
+ } while (error != PVRSRV_OK)
+
+#define ASSIGN_AND_EXIT_ON_ERROR(error, src) \
+ ASSIGN_AND_RETURN_ON_ERROR(error, src, 0)
+
+#if defined (PVR_SECURE_HANDLES)
+static PVRSRV_ERROR
+NewHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ u32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+ eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+ if (eError == PVRSRV_OK)
+ {
+ psPerProc->bHandlesBatched = 1;
+ }
+
+ return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, ui32BatchSize))
+
+static PVRSRV_ERROR
+CommitHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_ASSERT(psPerProc->bHandlesBatched);
+
+ psPerProc->bHandlesBatched = 0;
+
+ return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+static void
+ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->bHandlesBatched)
+ {
+ psPerProc->bHandlesBatched = 0;
+
+ PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+ }
+}
+#else
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
+#define ReleaseHandleBatch(psPerProc)
+#endif
+
+int
+DummyBW(u32 ui32BridgeID,
+ void *psBridgeIn,
+ void *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef int (*BridgeWrapperFunction)(u32 ui32BridgeID,
+ void *psBridgeIn,
+ void *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+{
+ BridgeWrapperFunction pfFunction;
+#if defined(DEBUG_BRIDGE_KM)
+ const char *pszIOCName;
+ const char *pszFunctionName;
+ u32 ui32CallCount;
+ u32 ui32CopyFromUserTotalBytes;
+ u32 ui32CopyToUserTotalBytes;
+#endif
+}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
+
+#if defined(SUPPORT_VGX) || defined(SUPPORT_MSVDX)
+ #if defined(SUPPORT_VGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_VGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_VGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_MSVDX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_MSVDX_CMD
+ #endif
+#else
+ #if defined(SUPPORT_SGX)
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_SGX_CMD
+ #else
+ #define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+ #define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD
+ #endif
+#endif
+
+extern PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+void
+_SetDispatchTableEntry(u32 ui32Index,
+ const char *pszIOCName,
+ BridgeWrapperFunction pfFunction,
+ const char *pszFunctionName);
+
+
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+ _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(DEBUG)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) do {} while(0)
+#endif
+
+
+#if defined(DEBUG_BRIDGE_KM)
+typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
+{
+ u32 ui32IOCTLCount;
+ u32 ui32TotalCopyFromUserBytes;
+ u32 ui32TotalCopyToUserBytes;
+}PVRSRV_BRIDGE_GLOBAL_STATS;
+
+extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+
+PVRSRV_ERROR CommonBridgeInit(void);
+
+int BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/ice4100/sgx535/bridged/bridged_support.c b/drivers/staging/ice4100/sgx535/bridged/bridged_support.c
new file mode 100755
index 00000000000..99578bb0bef
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/bridged/bridged_support.c
@@ -0,0 +1,84 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "img_defs.h"
+#include "servicesint.h"
+#include "bridged_support.h"
+
+PVRSRV_ERROR
+PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE * psHandleBase, void **phOSMemHandle,
+ void *hMHandle)
+{
+ void *hMHandleInt;
+ PVRSRV_HANDLE_TYPE eHandleType;
+ PVRSRV_ERROR eError;
+
+ eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+ &eHandleType, hMHandle);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ switch (eHandleType) {
+#if defined(PVR_SECURE_HANDLES)
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+ {
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ (PVRSRV_KERNEL_MEM_INFO *) hMHandleInt;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+ (PVRSRV_KERNEL_SYNC_INFO *) hMHandleInt;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psSyncInfo->psSyncDataMemInfoKM;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SOC_TIMER:
+ {
+ *phOSMemHandle = (void *)hMHandleInt;
+ break;
+ }
+#else
+ case PVRSRV_HANDLE_TYPE_NONE:
+ *phOSMemHandle = (void *)hMHandleInt;
+ break;
+#endif
+ default:
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/staging/ice4100/sgx535/bridged/bridged_support.h b/drivers/staging/ice4100/sgx535/bridged/bridged_support.h
new file mode 100755
index 00000000000..2b6d16fcd9b
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/bridged/bridged_support.h
@@ -0,0 +1,43 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SUPPORT_H__
+#define __BRIDGED_SUPPORT_H__
+
+#include "handle.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, void * *phOSMemHandle, void * hMHandle);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.c b/drivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.c
new file mode 100755
index 00000000000..df307a89bdd
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.c
@@ -0,0 +1,2497 @@
+/**********************************************************************
+ *
+ * Copyright (c) 2009-2010 Intel Corporation.
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+
+#include <stddef.h>
+
+#include "img_defs.h"
+
+#if defined(SUPPORT_SGX)
+
+#include "services.h"
+#include "pvr_debug.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "power.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+
+#if defined(SUPPORT_MSVDX)
+ #include "msvdx_bridge.h"
+#endif
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+static int
+SGXGetClientInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+ PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETCLIENTINFO);
+
+ psGetClientInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psGetClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psGetClientInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psGetClientInfoOUT->eError =
+ SGXGetClientInfoKM(hDevCookieInt,
+ &psGetClientInfoOUT->sClientInfo);
+ return 0;
+}
+
+static int
+SGXReleaseClientInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ void * hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psReleaseClientInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+ psDevInfo->ui32ClientRefCount--;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+
+static int
+SGXGetInternalDevInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+ PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO);
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psSGXGetInternalDevInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXGetInternalDevInfoOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXGetInternalDevInfoOUT->eError =
+ SGXGetInternalDevInfoKM(hDevCookieInt,
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
+
+
+ psSGXGetInternalDevInfoOUT->eError =
+ PVRSRVAllocHandle(psPerProc->psHandleBase,
+ &psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+ psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+
+ return 0;
+}
+
+
+static int
+SGXDoKickBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ u32 i;
+ int ret = 0;
+ u32 ui32NumDstSyncs;
+ void * *phKernelSyncInfoHandles = NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psDoKickIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+ psDoKickIN->sCCBKick.hCCBKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(psDoKickIN->sCCBKick.hTA3DSyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hTA3DSyncInfo,
+ psDoKickIN->sCCBKick.hTA3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if(psDoKickIN->sCCBKick.hTASyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hTASyncInfo,
+ psDoKickIN->sCCBKick.hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if(psDoKickIN->sCCBKick.h3DSyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.h3DSyncInfo,
+ psDoKickIN->sCCBKick.h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
+
+ if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTASrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTASrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32NumTADstSyncs > SGX_MAX_TA_DST_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumTADstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTADstKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DSrcSyncs > SGX_MAX_3D_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ for(i=0; i<psDoKickIN->sCCBKick.ui32Num3DSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ah3DSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#else
+
+ if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for(i=0; i<psDoKickIN->sCCBKick.ui32NumSrcSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+ psDoKickIN->sCCBKick.ahSrcKernelSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psDoKickIN->sCCBKick.ui32NumTAStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+ psDoKickIN->sCCBKick.asTAStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > SGX_MAX_3D_STATUS_VALS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for(i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++)
+ {
+ psRetOUT->eError =
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+ psDoKickIN->sCCBKick.as3DStatusUpdate[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+#else
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+#endif
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ ui32NumDstSyncs = psDoKickIN->sCCBKick.ui32NumDstSyncObjects;
+
+ if(ui32NumDstSyncs > 0)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(void *)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: SGXDoKickBW:"
+ " Invalid pasDstSyncHandles pointer", __FUNCTION__));
+ return -EFAULT;
+ }
+
+ psRetOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(void *),
+ (void **)&phKernelSyncInfoHandles,
+ 0,
+ "Array of Synchronization Info Handles");
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelSyncInfoHandles,
+ psDoKickIN->sCCBKick.pahDstSyncHandles,
+ ui32NumDstSyncs * sizeof(void *)) != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+
+ psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
+
+ for( i = 0; i < ui32NumDstSyncs; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+ psDoKickIN->sCCBKick.pahDstSyncHandles[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+ psDoKickIN->sCCBKick.hKernelHWSyncListMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
+ }
+ }
+
+ psRetOUT->eError =
+ SGXDoKickKM(hDevCookieInt,
+ &psDoKickIN->sCCBKick);
+
+PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+
+ if(phKernelSyncInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NumDstSyncs * sizeof(void *),
+ (void *)phKernelSyncInfoHandles,
+ 0);
+
+ }
+ return ret;
+}
+
+
+static int
+SGXScheduleProcessQueuesBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psScheduleProcQIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXScheduleProcessQueuesKM(hDevCookieInt);
+
+ return 0;
+}
+
+
+#if defined(TRANSFER_QUEUE)
+static int
+SGXSubmitTransferBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ PVRSRV_TRANSFER_SGX_KICK *psKick;
+ u32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+
+ psKick = &psSubmitTransferIN->sKick;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmitTransferIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hCCBMemInfo,
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKick->hTASyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hTASyncInfo,
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->h3DSyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->h3DSyncInfo,
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumDstSync > SGX_MAX_TRANSFER_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumDstSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahDstSyncInfo[i],
+ psKick->ahDstSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ psRetOUT->eError = SGXSubmitTransferKM(hDevCookieInt, psKick);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static int
+SGXSubmit2DBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SUBMIT2D *psSubmit2DIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ PVRSRV_2D_SGX_KICK *psKick;
+ u32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_SUBMIT2D);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSubmit2DIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psKick = &psSubmit2DIN->sKick;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hCCBMemInfo,
+ psKick->hCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ if (psKick->hTASyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hTASyncInfo,
+ psKick->hTASyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->h3DSyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->h3DSyncInfo,
+ psKick->h3DSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->ui32NumSrcSync > SGX_MAX_2D_SRC_SYNC_OPS)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psKick->ui32NumSrcSync; i++)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->ahSrcSyncInfo[i],
+ psKick->ahSrcSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ if (psKick->hDstSyncInfo != NULL)
+ {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psKick->hDstSyncInfo,
+ psKick->hDstSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ psRetOUT->eError =
+ SGXSubmit2DKM(hDevCookieInt, psKick);
+
+ return 0;
+}
+#endif
+#endif
+
+
+static int
+SGXGetMiscInfoBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ void * hDevMemContextInt = 0;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ SGX_MISC_INFO sMiscInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_GETMISCINFO);
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXGetMiscInfoIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
+
+ if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
+ {
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevMemContextInt,
+ psSGXGetMiscInfoIN->psMiscInfo->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+#endif
+
+ psDeviceNode = hDevCookieInt;
+ PVR_ASSERT(psDeviceNode != NULL);
+ if (psDeviceNode == NULL)
+ {
+ return -EFAULT;
+ }
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+
+ psRetOUT->eError = CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ &sMiscInfo,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+
+#ifdef SUPPORT_SGX_HWPERF
+ if (sMiscInfo.eRequest == SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB)
+ {
+
+ void * pAllocated;
+ void * hAllocatedHandle;
+ void * psTmpUserData;
+ u32 allocatedSize;
+
+ allocatedSize = (u32)(sMiscInfo.uData.sRetrieveCB.ui32ArraySize * sizeof(PVRSRV_SGX_HWPERF_CBDATA));
+
+ ASSIGN_AND_EXIT_ON_ERROR(psRetOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize,
+ &pAllocated,
+ &hAllocatedHandle,
+ "Array of Hardware Performance Circular Buffer Data"));
+
+
+ psTmpUserData = sMiscInfo.uData.sRetrieveCB.psHWPerfData;
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData = pAllocated;
+
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, 0);
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize,
+ pAllocated,
+ hAllocatedHandle);
+
+ return 0;
+ }
+
+
+ psRetOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psTmpUserData,
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData,
+ allocatedSize);
+
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData = psTmpUserData;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize,
+ pAllocated,
+ hAllocatedHandle);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+ }
+ else
+#endif
+ {
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, hDevMemContextInt);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+
+ psRetOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ &sMiscInfo,
+ sizeof(SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ {
+ return -EFAULT;
+ }
+ return 0;
+}
+
+
+#if defined(SUPPORT_SGX_HWPERF)
+static int
+SGXReadDiffCountersBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS *psSGXReadDiffCountersIN,
+ PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS *psSGXReadDiffCountersOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS);
+
+ psSGXReadDiffCountersOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXReadDiffCountersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXReadDiffCountersOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXReadDiffCountersOUT->eError = SGXReadDiffCountersKM(hDevCookieInt,
+ psSGXReadDiffCountersIN->ui32Reg,
+ &psSGXReadDiffCountersOUT->ui32Old,
+ psSGXReadDiffCountersIN->bNew,
+ psSGXReadDiffCountersIN->ui32New,
+ psSGXReadDiffCountersIN->ui32NewReset,
+ psSGXReadDiffCountersIN->ui32CountersReg,
+ psSGXReadDiffCountersIN->ui32Reg2,
+ &psSGXReadDiffCountersOUT->bActive,
+ &psSGXReadDiffCountersOUT->sDiffs);
+
+ return 0;
+}
+
+
+static int
+SGXReadHWPerfCBBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBIN,
+ PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ PVRSRV_SGX_HWPERF_CB_ENTRY *psAllocated;
+ void * hAllocatedHandle;
+ u32 ui32AllocatedSize;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_READ_HWPERF_CB);
+
+ psSGXReadHWPerfCBOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXReadHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXReadHWPerfCBOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ ui32AllocatedSize = psSGXReadHWPerfCBIN->ui32ArraySize *
+ sizeof(psSGXReadHWPerfCBIN->psHWPerfCBData[0]);
+ ASSIGN_AND_EXIT_ON_ERROR(psSGXReadHWPerfCBOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ (void **)&psAllocated,
+ &hAllocatedHandle,
+ "Array of Hardware Performance Circular Buffer Data"));
+
+ psSGXReadHWPerfCBOUT->eError = SGXReadHWPerfCBKM(hDevCookieInt,
+ psSGXReadHWPerfCBIN->ui32ArraySize,
+ psAllocated,
+ &psSGXReadHWPerfCBOUT->ui32DataCount,
+ &psSGXReadHWPerfCBOUT->ui32ClockSpeed,
+ &psSGXReadHWPerfCBOUT->ui32HostTimeStamp);
+ if (psSGXReadHWPerfCBOUT->eError == PVRSRV_OK)
+ {
+ psSGXReadHWPerfCBOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXReadHWPerfCBIN->psHWPerfCBData,
+ psAllocated,
+ ui32AllocatedSize);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32AllocatedSize,
+ psAllocated,
+ hAllocatedHandle);
+
+
+ return 0;
+}
+#endif
+
+
+static int
+SGXDevInitPart2BW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ PVRSRV_ERROR eError;
+ int bDissociateFailed = 0;
+ int bLookupFailed = 0;
+ int bReleaseFailed = 0;
+ void * hDummy;
+ u32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXDevInitPart2IN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ void * hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == NULL)
+ {
+ continue;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDummy,
+ hHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (int)(eError != PVRSRV_OK);
+ }
+
+ if (bLookupFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle lookup failed"));
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+
+
+ #if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ void * *phHandle = &psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (*phHandle == NULL)
+ continue;
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ phHandle,
+ *phHandle,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (int)(eError != PVRSRV_OK);
+ }
+
+ if (bReleaseFailed)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBEventKickerMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+
+
+#if defined(SGX_SUPPORT_HWPROFILING)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWProfilingMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SUPPORT_SGX_HWPERF)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelHWPerfCBMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelEDMStatusBufferMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+#if defined(SGX_FEATURE_SPM_MODE_0)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelTmpDPMStateMemInfo);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+#endif
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ void * hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == NULL)
+ continue;
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, hHandle);
+ bDissociateFailed |= (int)(eError != PVRSRV_OK);
+ }
+
+
+
+
+ if(bDissociateFailed)
+ {
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelCCBCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXHostCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXTA3DCtlMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelSGXMiscMemInfo);
+
+ for (i = 0; i < SGX_MAX_INIT_MEM_HANDLES; i++)
+ {
+ void * hHandle = psSGXDevInitPart2IN->sInitInfo.asInitMemHandles[i];
+
+ if (hHandle == NULL)
+ continue;
+
+ PVRSRVFreeDeviceMemKM(hDevCookieInt, (PVRSRV_KERNEL_MEM_INFO *)hHandle);
+
+ }
+
+ PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A dissociate failed"));
+
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+
+
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+ psRetOUT->eError =
+ DevInitSGXPart2KM(psPerProc,
+ hDevCookieInt,
+ &psSGXDevInitPart2IN->sInitInfo);
+
+ return 0;
+}
+
+
+static int
+SGXRegisterHWRenderContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT *psSGXRegHWRenderContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ void * hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWRenderContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWRenderContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWRenderContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWRenderContextInt =
+ SGXRegisterHWRenderContextKM(hDevCookieInt,
+ &psSGXRegHWRenderContextIN->sHWRenderContextDevVAddr,
+ psPerProc);
+
+ if (hHWRenderContextInt == NULL)
+ {
+ psSGXRegHWRenderContextOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWRenderContextOUT->hHWRenderContext,
+ hHWRenderContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWRenderContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static int
+SGXUnregisterHWRenderContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT *psSGXUnregHWRenderContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hHWRenderContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWRenderContextInt,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWRenderContextKM(hHWRenderContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWRenderContextIN->hHWRenderContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT);
+
+ return 0;
+}
+
+
+static int
+SGXRegisterHWTransferContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT *psSGXRegHWTransferContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ void * hHWTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHWTransferContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHWTransferContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHWTransferContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHWTransferContextInt =
+ SGXRegisterHWTransferContextKM(hDevCookieInt,
+ &psSGXRegHWTransferContextIN->sHWTransferContextDevVAddr,
+ psPerProc);
+
+ if (hHWTransferContextInt == NULL)
+ {
+ psSGXRegHWTransferContextOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHWTransferContextOUT->hHWTransferContext,
+ hHWTransferContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHWTransferContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static int
+SGXUnregisterHWTransferContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT *psSGXUnregHWTransferContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hHWTransferContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHWTransferContextInt,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHWTransferContextKM(hHWTransferContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHWTransferContextIN->hHWTransferContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT);
+
+ return 0;
+}
+
+
+#if defined(SGX_FEATURE_2D_HARDWARE)
+static int
+SGXRegisterHW2DContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextIN,
+ PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_2D_CONTEXT *psSGXRegHW2DContextOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ void * hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc, 1);
+
+ psSGXRegHW2DContextOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXRegHW2DContextIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXRegHW2DContextOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ hHW2DContextInt =
+ SGXRegisterHW2DContextKM(hDevCookieInt,
+ &psSGXRegHW2DContextIN->sHW2DContextDevVAddr,
+ psPerProc);
+
+ if (hHW2DContextInt == NULL)
+ {
+ psSGXRegHW2DContextOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXRegHW2DContextOUT->hHW2DContext,
+ hHW2DContextInt,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXRegHW2DContextOUT->eError, psPerProc);
+
+ return 0;
+}
+
+
+static int
+SGXUnregisterHW2DContextBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_2D_CONTEXT *psSGXUnregHW2DContextIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hHW2DContextInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hHW2DContextInt,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError = SGXUnregisterHW2DContextKM(hHW2DContextInt);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnregHW2DContextIN->hHW2DContext,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT);
+
+ return 0;
+}
+#endif
+
+static int
+SGXFlushHWRenderTargetBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET *psSGXFlushHWRenderTargetIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFlushHWRenderTargetIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr);
+
+ return 0;
+}
+
+
+static int
+SGX2DQueryBlitsCompleteBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ void *pvSyncInfo;
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ ps2DQueryBltsCompleteIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ ps2DQueryBltsCompleteIN->hKernSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ psRetOUT->eError =
+ SGX2DQueryBlitsCompleteKM(psDevInfo,
+ (PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+ ps2DQueryBltsCompleteIN->bWaitForComplete);
+
+ return 0;
+}
+
+
+static int
+SGXFindSharedPBDescBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = NULL;
+ u32 ui32SharedPBDescSubKernelMemInfosCount = 0;
+ u32 i;
+ void * hSharedPBDesc = NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc, PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS + 4);
+
+ psSGXFindSharedPBDescOUT->hSharedPBDesc = NULL;
+
+ psSGXFindSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXFindSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ psSGXFindSharedPBDescOUT->eError =
+ SGXFindSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSGXFindSharedPBDescIN->bLockOnFailure,
+ psSGXFindSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ &psSharedPBDescKernelMemInfo,
+ &psHWPBDescKernelMemInfo,
+ &psBlockKernelMemInfo,
+ &psHWBlockKernelMemInfo,
+ &ppsSharedPBDescSubKernelMemInfos,
+ &ui32SharedPBDescSubKernelMemInfosCount);
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+
+ PVR_ASSERT(ui32SharedPBDescSubKernelMemInfosCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ psSGXFindSharedPBDescOUT->ui32SharedPBDescSubKernelMemInfoHandlesCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+
+ if(hSharedPBDesc == NULL)
+ {
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
+
+ goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
+ psSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWPBDescKernelMemInfoHandle,
+ psHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hBlockKernelMemInfoHandle,
+ psBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOUT->hHWBlockKernelMemInfoHandle,
+ psHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDesc);
+
+
+ for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
+ {
+ PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOut =
+ psSGXFindSharedPBDescOUT;
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psSGXFindSharedPBDescOut->ahSharedPBDescSubKernelMemInfoHandles[i],
+ ppsSharedPBDescSubKernelMemInfos[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI,
+ psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle);
+ }
+
+PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT:
+ if (ppsSharedPBDescSubKernelMemInfos != NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos,
+ NULL);
+ }
+
+ if(psSGXFindSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ if(hSharedPBDesc != NULL)
+ {
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+ }
+ }
+ else
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXFindSharedPBDescOUT->eError, psPerProc);
+ }
+
+ return 0;
+}
+
+
+static int
+SGXUnrefSharedPBDescBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hSharedPBDesc;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC);
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hSharedPBDesc,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ SGXUnrefSharedPBDescKM(hSharedPBDesc);
+
+ if(psSGXUnrefSharedPBDescOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXUnrefSharedPBDescOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXUnrefSharedPBDescIN->hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC);
+
+ return 0;
+}
+
+
+static int
+SGXAddSharedPBDescBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+ PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo;
+ u32 ui32KernelMemInfoHandlesCount =
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+ int ret = 0;
+ void * *phKernelMemInfoHandles = NULL;
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = NULL;
+ u32 i;
+ PVRSRV_ERROR eError;
+ void * hSharedPBDesc = NULL;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc, 1);
+
+ psSGXAddSharedPBDescOUT->hSharedPBDesc = NULL;
+
+ PVR_ASSERT(ui32KernelMemInfoHandlesCount
+ <= PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hDevCookieInt,
+ psSGXAddSharedPBDescIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&psSharedPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&psHWPBDescKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&psBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(void *)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+ " Invalid phKernelMemInfos pointer", __FUNCTION__));
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(void *),
+ (void **)&phKernelMemInfoHandles,
+ 0,
+ "Array of Handles");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ phKernelMemInfoHandles,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(void *))
+ != PVRSRV_OK)
+ {
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (void **)&ppsKernelMemInfos,
+ 0,
+ "Array of pointers to Kernel Memory Info");
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (void **)&ppsKernelMemInfos[i],
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+ }
+
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
+ {
+
+ eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
+ phKernelMemInfoHandles[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ PVR_ASSERT(eError == PVRSRV_OK);
+ }
+
+ eError = SGXAddSharedPBDescKM(psPerProc, hDevCookieInt,
+ psSharedPBDescKernelMemInfo,
+ psHWPBDescKernelMemInfo,
+ psBlockKernelMemInfo,
+ psHWBlockKernelMemInfo,
+ psSGXAddSharedPBDescIN->ui32TotalPBSize,
+ &hSharedPBDesc,
+ ppsKernelMemInfos,
+ ui32KernelMemInfoHandlesCount);
+
+
+ if (eError != PVRSRV_OK)
+ {
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psSGXAddSharedPBDescOUT->hSharedPBDesc,
+ hSharedPBDesc,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT:
+
+ if(phKernelMemInfoHandles)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(void *),
+ (void *)phKernelMemInfoHandles,
+ 0);
+ }
+ if(ppsKernelMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount * sizeof(PVRSRV_KERNEL_MEM_INFO *),
+ (void *)ppsKernelMemInfos,
+ 0);
+ }
+
+ if(ret == 0 && eError == PVRSRV_OK)
+ {
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError, psPerProc);
+ }
+
+ psSGXAddSharedPBDescOUT->eError = eError;
+
+ return ret;
+}
+
+static int
+SGXGetInfoForSrvinitBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+ PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void * hDevCookieInt;
+ u32 i;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT);
+
+ NEW_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS);
+
+ if(!psPerProc->bInitProcess)
+ {
+ psSGXInfoForSrvinitOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psSGXInfoForSrvinitIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psSGXInfoForSrvinitOUT->eError =
+ SGXGetInfoForSrvinitKM(hDevCookieInt,
+ &psSGXInfoForSrvinitOUT->sInitInfo);
+
+ if(psSGXInfoForSrvinitOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ for(i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ PVRSRV_HEAP_INFO *psHeapInfo;
+
+ psHeapInfo = &psSGXInfoForSrvinitOUT->sInitInfo.asHeapInfo[i];
+
+ if (psHeapInfo->ui32HeapID != (u32)SGX_UNDEFINED_HEAP_ID)
+ {
+ void * hDevMemHeapExt;
+
+ if (psHeapInfo->hDevMemHeap != NULL)
+ {
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psHeapInfo->hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ psHeapInfo->hDevMemHeap = hDevMemHeapExt;
+ }
+ }
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXInfoForSrvinitOUT->eError, psPerProc);
+
+ return 0;
+}
+
+#if defined(PDUMP)
+static void
+DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ PSGX_KICKTA_DUMP_BUFFER psBufferArray,
+ u32 ui32BufferArrayLength,
+ int bDumpPolls)
+{
+ u32 i;
+
+ for (i=0; i<ui32BufferArrayLength; i++)
+ {
+ PSGX_KICKTA_DUMP_BUFFER psBuffer;
+ PVRSRV_KERNEL_MEM_INFO *psCtrlMemInfoKM;
+ char * pszName;
+ void * hUniqueTag;
+ u32 ui32Offset;
+
+ psBuffer = &psBufferArray[i];
+ pszName = psBuffer->pszName;
+ if (!pszName)
+ {
+ pszName = "Nameless buffer";
+ }
+
+ hUniqueTag = MAKEUNIQUETAG((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo);
+
+ #if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hCtrlKernelMemInfo);
+ ui32Offset = psBuffer->sCtrlDevVAddr.uiAddr - psCtrlMemInfoKM->sDevVAddr.uiAddr;
+ #else
+ psCtrlMemInfoKM = ((PVRSRV_KERNEL_MEM_INFO *)psBuffer->hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+ ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ #endif
+
+ if (psBuffer->ui32Start <= psBuffer->ui32End)
+ {
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32SpaceUsed,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+
+ PDUMPCOMMENTWITHFLAGS(0, "%s\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32End - psBuffer->ui32Start,
+ 0,
+ hUniqueTag);
+ }
+ else
+ {
+
+
+ if (bDumpPolls)
+ {
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 1)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength,
+ 0,
+ hUniqueTag);
+
+ if (bDumpPolls)
+ {
+ PDUMPMEMPOL(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+
+ PDUMPCOMMENTWITHFLAGS(0, "Wait for %s space\r\n", pszName);
+ PDUMPCBP(psCtrlMemInfoKM,
+ ui32Offset,
+ 0,
+ psBuffer->ui32End,
+ psBuffer->ui32BufferSize,
+ 0,
+ MAKEUNIQUETAG(psCtrlMemInfoKM));
+ }
+ PDUMPCOMMENTWITHFLAGS(0, "%s (part 2)\r\n", pszName);
+ PDUMPMEMUM(psPerProc,
+ NULL,
+ psBuffer->pvLinAddr,
+ (PVRSRV_KERNEL_MEM_INFO*)psBuffer->hKernelMemInfo,
+ 0,
+ psBuffer->ui32End,
+ 0,
+ hUniqueTag);
+ }
+ }
+}
+static int
+SGXPDumpBufferArrayBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+ void *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 i;
+ SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+ u32 ui32BufferArrayLength =
+ psPDumpBufferArrayIN->ui32BufferArrayLength;
+ u32 ui32BufferArraySize =
+ ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
+ PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32BufferArraySize,
+ (void * *)&psKickTADumpBuffer, 0,
+ "Array of Kick Tile Accelerator Dump Buffer") != PVRSRV_OK)
+ {
+ return -ENOMEM;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ psKickTADumpBuffer,
+ psPDumpBufferArrayIN->psBufferArray,
+ ui32BufferArraySize) != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+ return -EFAULT;
+ }
+
+ for(i = 0; i < ui32BufferArrayLength; i++)
+ {
+ void *pvMemInfo;
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psKickTADumpBuffer[i].hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+ psKickTADumpBuffer[i].hKernelMemInfo = pvMemInfo;
+
+#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvMemInfo,
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY: "
+ "PVRSRVLookupHandle failed (%d)", eError));
+ break;
+ }
+ psKickTADumpBuffer[i].hCtrlKernelMemInfo = pvMemInfo;
+#endif
+ }
+
+ if(eError == PVRSRV_OK)
+ {
+ DumpBufferArray(psPerProc,
+ psKickTADumpBuffer,
+ ui32BufferArrayLength,
+ psPDumpBufferArrayIN->bDumpPolls);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
+
+
+ return 0;
+}
+
+static int
+SGXPDump3DSignatureRegistersBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS *psPDump3DSignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 ui32RegisterArraySize = psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(u32);
+ u32 *pui32Registers = NULL;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ PVRSRV_SGXDEV_INFO *psDevInfo = NULL;
+ void * hDevCookieInt;
+ u32 ui32RegVal = 0;
+#endif
+ int ret = -EFAULT;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psPDump3DSignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+ psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (void * *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: OSAllocMem failed"));
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDump3DSignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDump3DSignatureRegisters(psPDump3DSignatureRegistersIN->ui32DumpFrameNum,
+ psPDump3DSignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDump3DSignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDump3DSignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+
+static int
+SGXPDumpCounterRegistersBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS *psPDumpCounterRegistersIN,
+ void *psBridgeOut,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 ui32RegisterArraySize = psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(u32);
+ u32 *pui32Registers = NULL;
+ int ret = -EFAULT;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (void * *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpCounterRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpCounterRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpCounterRegisters(psPDumpCounterRegistersIN->ui32DumpFrameNum,
+ psPDumpCounterRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpCounterRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ ret = 0;
+Exit:
+ if (pui32Registers != NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+ return ret;
+}
+
+static int
+SGXPDumpTASignatureRegistersBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS *psPDumpTASignatureRegistersIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 ui32RegisterArraySize = psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(u32);
+ u32 *pui32Registers = NULL;
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ PVRSRV_SGXDEV_INFO *psDevInfo = NULL;
+ void * hDevCookieInt;
+ u32 ui32RegVal = 0;
+#endif
+ int ret = -EFAULT;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ {
+ goto ExitNoError;
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psPDumpTASignatureRegistersIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: hDevCookie lookup failed"));
+ goto Exit;
+ }
+
+ psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+#endif
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (void * *)&pui32Registers, 0,
+ "Array of Registers") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: OSAllocMem failed"));
+ ret = -ENOMEM;
+ goto Exit;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->pui32Registers,
+ ui32RegisterArraySize) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpTASignatureRegistersBW: CopyFromUserWrapper failed"));
+ goto Exit;
+ }
+
+ PDumpTASignatureRegisters(psPDumpTASignatureRegistersIN->ui32DumpFrameNum,
+ psPDumpTASignatureRegistersIN->ui32TAKickCount,
+ psPDumpTASignatureRegistersIN->bLastFrame,
+ pui32Registers,
+ psPDumpTASignatureRegistersIN->ui32NumRegisters);
+
+ExitNoError:
+ psRetOUT->eError = PVRSRV_OK;
+ ret = 0;
+Exit:
+ if (pui32Registers != NULL)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize, pui32Registers, 0);
+ }
+
+#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
+ if (psDevInfo != NULL)
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, ui32RegVal);
+#if defined(PDUMP)
+ PDUMPREGWITHFLAGS(EUR_CR_MASTER_CORE, ui32RegVal,
+ psPDumpTASignatureRegistersIN->bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+#endif
+ }
+#endif
+
+ return ret;
+}
+static int
+SGXPDumpHWPerfCBBW(u32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if defined(SUPPORT_SGX_HWPERF)
+#if defined(__linux__)
+ PVRSRV_SGXDEV_INFO *psDevInfo;
+ void * hDevCookieInt;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
+ psPDumpHWPerfCBIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ PDumpHWPerfCBKM(&psPDumpHWPerfCBIN->szFileName[0],
+ psPDumpHWPerfCBIN->ui32FileOffset,
+ psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+ psDevInfo->psKernelHWPerfCBMemInfo->ui32AllocSize,
+ psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+ return 0;
+#else
+ return 0;
+#endif
+#else
+ return -EFAULT;
+#endif
+}
+
+#endif
+
+
+void SetSGXDispatchTableEntry(void)
+{
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETCLIENTINFO, SGXGetClientInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO, SGXReleaseClientInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO, SGXGetInternalDevInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DOKICK, SGXDoKickBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READREGISTRYDWORD, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE, SGX2DQueryBlitsCompleteBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMMUPDADDR, DummyBW);
+
+#if defined(TRANSFER_QUEUE)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER, SGXSubmitTransferBW);
+#endif
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMISCINFO, SGXGetMiscInfoBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT , SGXGetInfoForSrvinitBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_DEVINITPART2, SGXDevInitPart2BW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC, SGXFindSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC, SGXUnrefSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC, SGXAddSharedPBDescBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT, SGXRegisterHWRenderContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET, SGXFlushHWRenderTargetBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT, SGXUnregisterHWRenderContextBW);
+#if defined(SGX_FEATURE_2D_HARDWARE)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMIT2D, SGXSubmit2DBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_2D_CONTEXT, SGXRegisterHW2DContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_2D_CONTEXT, SGXUnregisterHW2DContextBW);
+#endif
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT, SGXRegisterHWTransferContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT, SGXUnregisterHWTransferContextBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES, SGXScheduleProcessQueuesBW);
+
+#if defined(SUPPORT_SGX_HWPERF)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS, SGXReadDiffCountersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_HWPERF_CB, SGXReadHWPerfCBBW);
+#endif
+
+#if defined(PDUMP)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY, SGXPDumpBufferArrayBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS, SGXPDump3DSignatureRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS, SGXPDumpCounterRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS, SGXPDumpTASignatureRegistersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB, SGXPDumpHWPerfCBBW);
+#endif
+}
+
+#endif
diff --git a/drivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.h b/drivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.h
new file mode 100755
index 00000000000..fddec830175
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/bridged/sgx/bridged_sgx_bridge.h
@@ -0,0 +1,42 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef __BRIDGED_SGX_BRIDGE_H__
+#define __BRIDGED_SGX_BRIDGE_H__
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+void SetSGXDispatchTableEntry(void);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/drivers/staging/ice4100/sgx535/common/buffer_manager.c b/drivers/staging/ice4100/sgx535/common/buffer_manager.c
new file mode 100755
index 00000000000..af3f72437d9
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/buffer_manager.c
@@ -0,0 +1,1803 @@
+/**********************************************************************
+ *
+ * Copyright (c) 2009-2010 Intel Corporation.
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "sysconfig.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+
+#define MIN(a,b) (a > b ? b : a)
+
+#include "lists.h"
+
+DECLARE_LIST_ANY_VA(BM_HEAP);
+DECLARE_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+DECLARE_LIST_INSERT(BM_HEAP);
+DECLARE_LIST_REMOVE(BM_HEAP);
+
+/* FIXME MLD */
+typedef void *mldhack;
+
+DECLARE_LIST_FOR_EACH(BM_CONTEXT);
+DECLARE_LIST_ANY_VA(BM_CONTEXT);
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, mldhack, NULL);
+DECLARE_LIST_INSERT(BM_CONTEXT);
+DECLARE_LIST_REMOVE(BM_CONTEXT);
+
+static int
+ZeroBuf(BM_BUF * pBuf, BM_MAPPING * pMapping, u32 ui32Bytes, u32 ui32Flags);
+static void BM_FreeMemory(void *pH, u32 base, BM_MAPPING * psMapping);
+static int
+BM_ImportMemory(void *pH, u32 uSize,
+ u32 * pActualSize, BM_MAPPING ** ppsMapping,
+ u32 uFlags, u32 * pBase);
+
+static int
+DevMemoryAlloc(BM_CONTEXT * pBMContext,
+ BM_MAPPING * pMapping,
+ u32 * pActualSize,
+ u32 uFlags,
+ u32 dev_vaddr_alignment, IMG_DEV_VIRTADDR * pDevVAddr);
+static void DevMemoryFree(BM_MAPPING * pMapping);
+
+static int
+AllocMemory(BM_CONTEXT * pBMContext,
+ BM_HEAP * psBMHeap,
+ IMG_DEV_VIRTADDR * psDevVAddr,
+ u32 uSize, u32 uFlags, u32 uDevVAddrAlignment, BM_BUF * pBuf)
+{
+ BM_MAPPING *pMapping;
+ u32 uOffset;
+ RA_ARENA *pArena = NULL;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "AllocMemory (pBMContext=%08X, uSize=0x%x, uFlags=0x%x, align=0x%x, pBuf=%08X)",
+ pBMContext, uSize, uFlags, uDevVAddrAlignment, pBuf));
+
+ if (uFlags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) {
+ if (uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
+ return 0;
+ }
+
+ if (psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ | PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) {
+
+ pArena = psBMHeap->pImportArena;
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: backing store type doesn't match heap"));
+ return 0;
+ }
+
+ if (!RA_Alloc(pArena,
+ uSize,
+ NULL,
+ (void *)&pMapping,
+ uFlags,
+ uDevVAddrAlignment,
+ 0, (u32 *) & (pBuf->DevVAddr.uiAddr))) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
+ return 0;
+ }
+
+ uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
+ if (pMapping->CpuVAddr) {
+ pBuf->CpuVAddr =
+ (void *)((u32) pMapping->CpuVAddr + uOffset);
+ } else {
+ pBuf->CpuVAddr = NULL;
+ }
+
+ if (uSize == pMapping->uSize) {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ } else {
+ if (OSGetSubMemHandle(pMapping->hOSMemHandle,
+ uOffset,
+ uSize,
+ psBMHeap->ui32Attribs,
+ &pBuf->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: OSGetSubMemHandle FAILED"));
+ return 0;
+ }
+ }
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+ if (uFlags & PVRSRV_MEM_ZERO) {
+ if (!ZeroBuf
+ (pBuf, pMapping, uSize,
+ psBMHeap->ui32Attribs | uFlags)) {
+ return 0;
+ }
+ }
+ } else {
+ if (uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) {
+
+ PVR_ASSERT(psDevVAddr != NULL);
+
+ if (psDevVAddr == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: invalid parameter - psDevVAddr"));
+ return 0;
+ }
+
+ pBMContext->psDeviceNode->pfnMMUAlloc(psBMHeap->
+ pMMUHeap, uSize,
+ NULL,
+ PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+ uDevVAddrAlignment,
+ psDevVAddr);
+
+ pBuf->DevVAddr = *psDevVAddr;
+ } else {
+
+ pBMContext->psDeviceNode->pfnMMUAlloc(psBMHeap->
+ pMMUHeap, uSize,
+ NULL, 0,
+ uDevVAddrAlignment,
+ &pBuf->DevVAddr);
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct _BM_MAPPING_),
+ (void **)&pMapping, NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: OSAllocMem(0x%x) FAILED"));
+ return 0;
+ }
+
+ pBuf->CpuVAddr = NULL;
+ pBuf->hOSMemHandle = 0;
+ pBuf->CpuPAddr.uiAddr = 0;
+
+ pMapping->CpuVAddr = NULL;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->DevVAddr = pBuf->DevVAddr;
+ pMapping->psSysAddr = NULL;
+ pMapping->uSize = uSize;
+ pMapping->hOSMemHandle = 0;
+ }
+
+ pMapping->pArena = pArena;
+
+ pMapping->pBMHeap = psBMHeap;
+ pBuf->pMapping = pMapping;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "AllocMemory: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pMapping,
+ pMapping->DevVAddr.uiAddr,
+ pMapping->CpuVAddr,
+ pMapping->CpuPAddr.uiAddr, pMapping->uSize));
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "AllocMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pBuf,
+ pBuf->DevVAddr.uiAddr,
+ pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr, uSize));
+
+ PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
+
+ return 1;
+}
+
+static int
+WrapMemory(BM_HEAP * psBMHeap,
+ u32 uSize,
+ u32 ui32BaseOffset,
+ int bPhysContig,
+ IMG_SYS_PHYADDR * psAddr,
+ void *pvCPUVAddr, u32 uFlags, BM_BUF * pBuf)
+{
+ IMG_DEV_VIRTADDR DevVAddr = { 0 };
+ BM_MAPPING *pMapping;
+ int bResult;
+ u32 const ui32PageSize = HOST_PAGESIZE();
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "WrapMemory(psBMHeap=%08X, size=0x%x, offset=0x%x, bPhysContig=0x%x, pvCPUVAddr = 0x%x, flags=0x%x, pBuf=%08X)",
+ psBMHeap, uSize, ui32BaseOffset, bPhysContig, pvCPUVAddr,
+ uFlags, pBuf));
+
+ PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
+
+ PVR_ASSERT(((u32) pvCPUVAddr & (ui32PageSize - 1)) == 0);
+
+ uSize += ui32BaseOffset;
+ uSize = HOST_PAGEALIGN(uSize);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*pMapping),
+ (void **)&pMapping, NULL,
+ "Mocked-up mapping") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",
+ sizeof(*pMapping)));
+ return 0;
+ }
+
+ memset(pMapping, 0, sizeof(*pMapping));
+
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = psBMHeap;
+
+ if (pvCPUVAddr) {
+ pMapping->CpuVAddr = pvCPUVAddr;
+
+ if (bPhysContig) {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_virtaddr;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if (OSRegisterMem(pMapping->CpuPAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: OSRegisterMem Phys=0x%08X, CpuVAddr = 0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr, pMapping->CpuVAddr,
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+ } else {
+ pMapping->eCpuMemoryOrigin =
+ hm_wrapped_scatter_virtaddr;
+ pMapping->psSysAddr = psAddr;
+
+ if (OSRegisterDiscontigMem(pMapping->psSysAddr,
+ pMapping->CpuVAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->hOSMemHandle) !=
+ PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: OSRegisterDiscontigMem CpuVAddr = 0x%08X, Size=%d) failed",
+ pMapping->CpuVAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ } else {
+ if (bPhysContig) {
+ pMapping->eCpuMemoryOrigin = hm_wrapped;
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(psAddr[0]);
+
+ if (OSReservePhys(pMapping->CpuPAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: OSReservePhys Phys=0x%08X, Size=%d) failed",
+ pMapping->CpuPAddr, pMapping->uSize));
+ goto fail_cleanup;
+ }
+ } else {
+ pMapping->eCpuMemoryOrigin = hm_wrapped_scatter;
+ pMapping->psSysAddr = psAddr;
+
+ if (OSReserveDiscontigPhys(pMapping->psSysAddr,
+ pMapping->uSize,
+ uFlags,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) !=
+ PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: OSReserveDiscontigPhys Size=%d) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+ }
+ }
+
+ bResult = DevMemoryAlloc(psBMHeap->pBMContext,
+ pMapping,
+ NULL,
+ uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32PageSize),
+ &DevVAddr);
+ if (!bResult) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_cleanup;
+ }
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
+ if (!ui32BaseOffset) {
+ pBuf->hOSMemHandle = pMapping->hOSMemHandle;
+ } else {
+ if (OSGetSubMemHandle(pMapping->hOSMemHandle,
+ ui32BaseOffset,
+ (pMapping->uSize - ui32BaseOffset),
+ uFlags,
+ &pBuf->hOSMemHandle) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "WrapMemory: OSGetSubMemHandle failed"));
+ goto fail_cleanup;
+ }
+ }
+ if (pMapping->CpuVAddr) {
+ pBuf->CpuVAddr =
+ (void *)((u32) pMapping->CpuVAddr + ui32BaseOffset);
+ }
+ pBuf->DevVAddr.uiAddr =
+ pMapping->DevVAddr.uiAddr +
+ IMG_CAST_TO_DEVVADDR_UINT(ui32BaseOffset);
+
+ if (uFlags & PVRSRV_MEM_ZERO) {
+ if (!ZeroBuf(pBuf, pMapping, uSize, uFlags)) {
+ return 0;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "DevVaddr.uiAddr=%08X", DevVAddr.uiAddr));
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "WrapMemory: pMapping=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pMapping, pMapping->DevVAddr.uiAddr,
+ pMapping->CpuVAddr, pMapping->CpuPAddr.uiAddr,
+ pMapping->uSize));
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "WrapMemory: pBuf=%08X: DevV=%08X CpuV=%08X CpuP=%08X uSize=0x%x",
+ pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr,
+ pBuf->CpuPAddr.uiAddr, uSize));
+
+ pBuf->pMapping = pMapping;
+ return 1;
+
+fail_cleanup:
+ if (ui32BaseOffset && pBuf->hOSMemHandle) {
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
+ }
+
+ if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle)) {
+ switch (pMapping->eCpuMemoryOrigin) {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr, pMapping->uSize,
+ uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr, pMapping->uSize,
+ uFlags, pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr,
+ pMapping->uSize, uFlags,
+ pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr,
+ pMapping->uSize, uFlags,
+ pMapping->hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, NULL);
+
+ return 0;
+}
+
+static int
+ZeroBuf(BM_BUF * pBuf, BM_MAPPING * pMapping, u32 ui32Bytes, u32 ui32Flags)
+{
+ void *pvCpuVAddr;
+
+ if (pBuf->CpuVAddr) {
+ memset(pBuf->CpuVAddr, 0, ui32Bytes);
+ } else if (pMapping->eCpuMemoryOrigin == hm_contiguous
+ || pMapping->eCpuMemoryOrigin == hm_wrapped) {
+ pvCpuVAddr = OSMapPhysToLin(pBuf->CpuPAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags &
+ PVRSRV_HAP_CACHETYPE_MASK),
+ NULL);
+ if (!pvCpuVAddr) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "ZeroBuf: OSMapPhysToLin for contiguous buffer failed"));
+ return 0;
+ }
+ memset(pvCpuVAddr, 0, ui32Bytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ NULL);
+ } else {
+ u32 ui32BytesRemaining = ui32Bytes;
+ u32 ui32CurrentOffset = 0;
+ IMG_CPU_PHYADDR CpuPAddr;
+
+ PVR_ASSERT(pBuf->hOSMemHandle);
+
+ while (ui32BytesRemaining > 0) {
+ u32 ui32BlockBytes =
+ MIN(ui32BytesRemaining, HOST_PAGESIZE());
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(pBuf->hOSMemHandle,
+ ui32CurrentOffset);
+
+ if (CpuPAddr.uiAddr & (HOST_PAGESIZE() - 1)) {
+ ui32BlockBytes =
+ MIN(ui32BytesRemaining,
+ HOST_PAGEALIGN(CpuPAddr.uiAddr) -
+ CpuPAddr.uiAddr);
+ }
+
+ pvCpuVAddr = OSMapPhysToLin(CpuPAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags &
+ PVRSRV_HAP_CACHETYPE_MASK),
+ NULL);
+ if (!pvCpuVAddr) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "ZeroBuf: OSMapPhysToLin while zeroing non-contiguous memory FAILED"));
+ return 0;
+ }
+ memset(pvCpuVAddr, 0, ui32BlockBytes);
+ OSUnMapPhysToLin(pvCpuVAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY
+ | (ui32Flags &
+ PVRSRV_HAP_CACHETYPE_MASK), NULL);
+
+ ui32BytesRemaining -= ui32BlockBytes;
+ ui32CurrentOffset += ui32BlockBytes;
+ }
+ }
+
+ return 1;
+}
+
+static void FreeBuf(BM_BUF * pBuf, u32 ui32Flags)
+{
+ BM_MAPPING *pMapping;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "FreeBuf: pBuf=%08X: DevVAddr=%08X CpuVAddr=%08X CpuPAddr=%08X",
+ pBuf, pBuf->DevVAddr.uiAddr, pBuf->CpuVAddr,
+ pBuf->CpuPAddr.uiAddr));
+
+ pMapping = pBuf->pMapping;
+
+ if (ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) {
+
+ if (ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
+ } else {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING),
+ pMapping, NULL);
+ pBuf->pMapping = NULL;
+ }
+ } else {
+
+ if (pBuf->hOSMemHandle != pMapping->hOSMemHandle) {
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
+ }
+ if (ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION) {
+
+ RA_Free(pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr,
+ 0);
+ } else {
+ switch (pMapping->eCpuMemoryOrigin) {
+ case hm_wrapped:
+ OSUnReservePhys(pMapping->CpuVAddr,
+ pMapping->uSize, ui32Flags,
+ pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_virtaddr:
+ OSUnRegisterMem(pMapping->CpuVAddr,
+ pMapping->uSize, ui32Flags,
+ pMapping->hOSMemHandle);
+ break;
+ case hm_wrapped_scatter:
+ OSUnReserveDiscontigPhys(pMapping->CpuVAddr,
+ pMapping->uSize,
+ ui32Flags,
+ pMapping->
+ hOSMemHandle);
+ break;
+ case hm_wrapped_scatter_virtaddr:
+ OSUnRegisterDiscontigMem(pMapping->CpuVAddr,
+ pMapping->uSize,
+ ui32Flags,
+ pMapping->
+ hOSMemHandle);
+ break;
+ default:
+ break;
+ }
+
+ DevMemoryFree(pMapping);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING),
+ pMapping, NULL);
+ pBuf->pMapping = NULL;
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, NULL);
+
+}
+
+PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP * psBMHeap)
+{
+ if (psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ | PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) {
+ if (psBMHeap->pImportArena) {
+ int bTestDelete = RA_TestDelete(psBMHeap->pImportArena);
+ if (!bTestDelete) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_DestroyContext_AnyCb: RA_TestDelete failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BM_DestroyContext(void *hBMContext, int *pbDestroyed)
+{
+ PVRSRV_ERROR eError;
+ BM_CONTEXT *pBMContext = (BM_CONTEXT *) hBMContext;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyContext"));
+
+ if (pbDestroyed != NULL) {
+ *pbDestroyed = 0;
+ }
+
+ if (pBMContext == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBMContext->ui32RefCount--;
+
+ if (pBMContext->ui32RefCount > 0) {
+
+ return PVRSRV_OK;
+ }
+
+ eError =
+ List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap,
+ BM_DestroyContext_AnyCb);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
+#if 0
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
+ if (ResManFreeSpecial() != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_DestroyContext: ResManFreeSpecial failed %d",
+ eError));
+ }
+#endif
+ return eError;
+ } else {
+
+ eError = ResManFreeResByPtr(pBMContext->hResItem);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_DestroyContext: ResManFreeResByPtr failed %d",
+ eError));
+ return eError;
+ }
+
+ if (pbDestroyed != NULL) {
+ *pbDestroyed = 1;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP * psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE *);
+
+ if (psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ | PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) {
+ if (psBMHeap->pImportArena) {
+ RA_Delete(psBMHeap->pImportArena);
+ }
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_DestroyContext: backing store type unsupported"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, NULL);
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR BM_DestroyContextCallBack(void *pvParam, u32 ui32Param)
+{
+ BM_CONTEXT *pBMContext = pvParam;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+ if (List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
+ BM_DestroyContextCallBack_AnyVaCb,
+ psDeviceNode) != PVRSRV_OK) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (pBMContext->psMMUContext) {
+ psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+ }
+
+ if (pBMContext->pBufferHash) {
+ HASH_Delete(pBMContext->pBufferHash);
+ }
+
+ if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext) {
+
+ psDeviceNode->sDevMemoryInfo.pBMKernelContext = NULL;
+ } else {
+
+ List_BM_CONTEXT_Remove(pBMContext);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext,
+ NULL);
+
+ return PVRSRV_OK;
+}
+
+void *BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT * pBMContext, va_list va)
+{
+ PRESMAN_CONTEXT hResManContext;
+ hResManContext = va_arg(va, PRESMAN_CONTEXT);
+ if (ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) ==
+ PVRSRV_OK) {
+
+ pBMContext->ui32RefCount++;
+ return pBMContext;
+ }
+ return NULL;
+}
+
+void BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP * psBMHeap, va_list va)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_CONTEXT *pBMContext;
+ psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE *);
+ pBMContext = va_arg(va, BM_CONTEXT *);
+ switch (psBMHeap->sDevArena.DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext,
+ psBMHeap->pMMUHeap);
+ break;
+ }
+ }
+}
+
+void *BM_CreateContext(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_DEV_PHYADDR * psPDDevPAddr,
+ PVRSRV_PER_PROCESS_DATA * psPerProc, int *pbCreated)
+{
+ BM_CONTEXT *pBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ int bKernelContext;
+ PRESMAN_CONTEXT hResManContext;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateContext"));
+
+ if (psPerProc == NULL) {
+ bKernelContext = 1;
+ hResManContext = psDeviceNode->hResManContext;
+ } else {
+ bKernelContext = 0;
+ hResManContext = psPerProc->hResManContext;
+ }
+
+ if (pbCreated != NULL) {
+ *pbCreated = 0;
+ }
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ if (bKernelContext == 0) {
+ void *res =
+ (void *)List_BM_CONTEXT_Any_va(psDevMemoryInfo->pBMContext,
+ BM_CreateContext_IncRefCount_AnyVaCb,
+ hResManContext);
+ if (res) {
+ return res;
+ }
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct _BM_CONTEXT_),
+ (void **)&pBMContext, NULL,
+ "Buffer Manager Context") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateContext: Alloc failed"));
+ return NULL;
+ }
+ memset(pBMContext, 0, sizeof(BM_CONTEXT));
+
+ pBMContext->psDeviceNode = psDeviceNode;
+
+ pBMContext->pBufferHash = HASH_Create(32);
+ if (pBMContext->pBufferHash == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_CreateContext: HASH_Create failed"));
+ goto cleanup;
+ }
+
+ if (psDeviceNode->pfnMMUInitialise(psDeviceNode,
+ &pBMContext->psMMUContext,
+ psPDDevPAddr) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_CreateContext: MMUInitialise failed"));
+ goto cleanup;
+ }
+
+ if (bKernelContext) {
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == NULL);
+ psDevMemoryInfo->pBMKernelContext = pBMContext;
+ } else {
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
+
+ if (psDevMemoryInfo->pBMKernelContext == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_CreateContext: psDevMemoryInfo->pBMKernelContext invalid"));
+ goto cleanup;
+ }
+
+ PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
+
+ pBMContext->psBMSharedHeap =
+ psDevMemoryInfo->pBMKernelContext->psBMHeap;
+
+ List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
+ BM_CreateContext_InsertHeap_ForEachVaCb,
+ psDeviceNode, pBMContext);
+
+ List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext,
+ pBMContext);
+ }
+
+ pBMContext->ui32RefCount++;
+
+ pBMContext->hResItem = ResManRegisterRes(hResManContext,
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ pBMContext,
+ 0, BM_DestroyContextCallBack);
+ if (pBMContext->hResItem == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_CreateContext: ResManRegisterRes failed"));
+ goto cleanup;
+ }
+
+ if (pbCreated != NULL) {
+ *pbCreated = 1;
+ }
+ return (void *)pBMContext;
+
+cleanup:
+ (void)BM_DestroyContextCallBack(pBMContext, 0);
+
+ return NULL;
+}
+
+void *BM_CreateHeap_AnyVaCb(BM_HEAP * psBMHeap, va_list va)
+{
+ DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo;
+ psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO *);
+ if (psBMHeap->sDevArena.ui32HeapID == psDevMemHeapInfo->ui32HeapID) {
+
+ return psBMHeap;
+ } else {
+ return NULL;
+ }
+}
+
+void *BM_CreateHeap(void *hBMContext,
+ DEVICE_MEMORY_HEAP_INFO * psDevMemHeapInfo)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT *) hBMContext;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_HEAP *psBMHeap;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_CreateHeap"));
+
+ if (!pBMContext) {
+ return NULL;
+ }
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+ if (pBMContext->ui32RefCount > 0) {
+ psBMHeap = (BM_HEAP *) List_BM_HEAP_Any_va(pBMContext->psBMHeap,
+ BM_CreateHeap_AnyVaCb,
+ psDevMemHeapInfo);
+
+ if (psBMHeap) {
+ return psBMHeap;
+ }
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BM_HEAP),
+ (void **)&psBMHeap, NULL,
+ "Buffer Manager Heap") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed"));
+ return NULL;
+ }
+
+ memset(psBMHeap, 0, sizeof(BM_HEAP));
+
+ psBMHeap->sDevArena.ui32HeapID = psDevMemHeapInfo->ui32HeapID;
+ psBMHeap->sDevArena.pszName = psDevMemHeapInfo->pszName;
+ psBMHeap->sDevArena.BaseDevVAddr = psDevMemHeapInfo->sDevVAddrBase;
+ psBMHeap->sDevArena.ui32Size = psDevMemHeapInfo->ui32HeapSize;
+ psBMHeap->sDevArena.DevMemHeapType = psDevMemHeapInfo->DevMemHeapType;
+ psBMHeap->sDevArena.ui32DataPageSize =
+ psDevMemHeapInfo->ui32DataPageSize;
+ psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
+ psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+
+ psBMHeap->pBMContext = pBMContext;
+
+ psBMHeap->pMMUHeap =
+ psDeviceNode->pfnMMUCreate(pBMContext->psMMUContext,
+ &psBMHeap->sDevArena,
+ &psBMHeap->pVMArena);
+ if (!psBMHeap->pMMUHeap) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: MMUCreate failed"));
+ goto ErrorExit;
+ }
+
+ psBMHeap->pImportArena = RA_Create(psDevMemHeapInfo->pszBSName,
+ 0, 0, NULL,
+ psBMHeap->sDevArena.ui32DataPageSize,
+ BM_ImportMemory,
+ BM_FreeMemory, NULL, psBMHeap);
+ if (psBMHeap->pImportArena == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_CreateHeap: RA_Create failed"));
+ goto ErrorExit;
+ }
+
+ if (psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) {
+
+ psBMHeap->pLocalDevMemArena =
+ psDevMemHeapInfo->psLocalDevMemArena;
+ if (psBMHeap->pLocalDevMemArena == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_CreateHeap: LocalDevMemArena null"));
+ goto ErrorExit;
+ }
+ }
+
+ List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
+
+ return (void *)psBMHeap;
+
+ErrorExit:
+
+ if (psBMHeap->pMMUHeap != NULL) {
+ psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+ psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, NULL);
+
+ return NULL;
+}
+
+void BM_DestroyHeap(void *hDevMemHeap)
+{
+ BM_HEAP *psBMHeap = (BM_HEAP *) hDevMemHeap;
+ PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_DestroyHeap"));
+
+ if (psBMHeap) {
+
+ if (psBMHeap->ui32Attribs
+ & (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
+ | PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)) {
+ if (psBMHeap->pImportArena) {
+ RA_Delete(psBMHeap->pImportArena);
+ }
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_DestroyHeap: backing store type unsupported"));
+ return;
+ }
+
+ psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+ List_BM_HEAP_Remove(psBMHeap);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap,
+ NULL);
+
+ } else {
+ PVR_DPF((PVR_DBG_ERROR, "BM_DestroyHeap: invalid heap handle"));
+ }
+}
+
+int BM_Reinitialise(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
+
+ return 1;
+}
+
+int
+BM_Alloc(void *hDevMemHeap,
+ IMG_DEV_VIRTADDR * psDevVAddr,
+ u32 uSize, u32 * pui32Flags, u32 uDevVAddrAlignment, BM_HANDLE * phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *pBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ u32 uFlags;
+
+ if (pui32Flags == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: invalid parameter"));
+ PVR_DBG_BREAK;
+ return 0;
+ }
+
+ uFlags = *pui32Flags;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+ uSize, uFlags, uDevVAddrAlignment));
+
+ SysAcquireData(&psSysData);
+
+ psBMHeap = (BM_HEAP *) hDevMemHeap;
+ pBMContext = psBMHeap->pBMContext;
+
+ if (uDevVAddrAlignment == 0) {
+ uDevVAddrAlignment = 1;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BM_BUF),
+ (void **)&pBuf, NULL,
+ "Buffer Manager buffer") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED"));
+ return 0;
+ }
+ memset(pBuf, 0, sizeof(BM_BUF));
+
+ if (AllocMemory(pBMContext,
+ psBMHeap,
+ psDevVAddr,
+ uSize, uFlags, uDevVAddrAlignment, pBuf) != 1) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, NULL);
+
+ PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
+ return 0;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x)=%08X",
+ uSize, uFlags, pBuf));
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE) pBuf;
+#if defined(INTEL_D3_P_CHANGES)
+ if (pui32Flags) {
+#endif
+ *pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+ if (uFlags & PVRSRV_HAP_CACHETYPE_MASK) {
+ *pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ *pui32Flags |= (uFlags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+#if defined(INTEL_D3_P_CHANGES)
+ }
+#endif
+
+ return 1;
+}
+
+#if defined(PVR_LMA)
+static int
+ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_SYS_PHYADDR * psSysPAddr, u32 ui32PageCount,
+ u32 ui32PageSize)
+{
+ u32 i;
+
+ for (i = 0; i < ui32PageCount; i++) {
+ IMG_SYS_PHYADDR sStartSysPAddr = psSysPAddr[i];
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr
+ (psDeviceNode->sDevId.eDeviceType, sStartSysPAddr)) {
+ return 0;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32PageSize;
+
+ if (!SysVerifySysPAddrToDevPAddr
+ (psDeviceNode->sDevId.eDeviceType, sEndSysPAddr)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int
+ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE * psDeviceNode,
+ IMG_SYS_PHYADDR sStartSysPAddr, u32 ui32Range)
+{
+ IMG_SYS_PHYADDR sEndSysPAddr;
+
+ if (!SysVerifySysPAddrToDevPAddr
+ (psDeviceNode->sDevId.eDeviceType, sStartSysPAddr)) {
+ return 0;
+ }
+
+ sEndSysPAddr.uiAddr = sStartSysPAddr.uiAddr + ui32Range;
+
+ if (!SysVerifySysPAddrToDevPAddr
+ (psDeviceNode->sDevId.eDeviceType, sEndSysPAddr)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+#define WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) HOST_PAGEALIGN((ui32ByteSize) + (ui32PageOffset))
+
+#define WRAP_PAGE_COUNT(ui32ByteSize, ui32PageOffset, ui32HostPageSize) (WRAP_MAPPING_SIZE(ui32ByteSize, ui32PageOffset) / (ui32HostPageSize))
+
+#endif
+
+int
+BM_Wrap(void *hDevMemHeap,
+ u32 ui32Size,
+ u32 ui32Offset,
+ int bPhysContig,
+ IMG_SYS_PHYADDR * psSysAddr,
+ void *pvCPUVAddr, u32 * pui32Flags, BM_HANDLE * phBuf)
+{
+ BM_BUF *pBuf;
+ BM_CONTEXT *psBMContext;
+ BM_HEAP *psBMHeap;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddress;
+ u32 uFlags;
+
+ psBMHeap = (BM_HEAP *) hDevMemHeap;
+ psBMContext = psBMHeap->pBMContext;
+
+ uFlags =
+ psBMHeap->
+ ui32Attribs & (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+ if ((pui32Flags != NULL)
+ && ((*pui32Flags & PVRSRV_HAP_CACHETYPE_MASK) != 0)) {
+ uFlags &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ uFlags |= *pui32Flags & PVRSRV_HAP_CACHETYPE_MASK;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uOffset=0x%x, bPhysContig=0x%x, pvCPUVAddr=0x%x, uFlags=0x%x)",
+ ui32Size, ui32Offset, bPhysContig, pvCPUVAddr, uFlags));
+
+ SysAcquireData(&psSysData);
+
+#if defined(PVR_LMA)
+ if (bPhysContig) {
+ if (!ValidSysPAddrRangeForDev
+ (psBMContext->psDeviceNode, *psSysAddr,
+ WRAP_MAPPING_SIZE(ui32Size, ui32Offset))) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_Wrap: System address range invalid for device"));
+ return 0;
+ }
+ } else {
+ u32 ui32HostPageSize = HOST_PAGESIZE();
+
+ if (!ValidSysPAddrArrayForDev
+ (psBMContext->psDeviceNode, psSysAddr,
+ WRAP_PAGE_COUNT(ui32Size, ui32Offset, ui32HostPageSize),
+ ui32HostPageSize)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_Wrap: Array of system addresses invalid for device"));
+ return 0;
+ }
+ }
+#endif
+
+ sHashAddress = psSysAddr[0];
+
+ sHashAddress.uiAddr += ui32Offset;
+
+ pBuf =
+ (BM_BUF *) HASH_Retrieve(psBMContext->pBufferHash,
+ (u32) sHashAddress.uiAddr);
+
+ if (pBuf) {
+ u32 ui32MappingSize = HOST_PAGEALIGN(ui32Size + ui32Offset);
+
+ if (pBuf->pMapping->uSize == ui32MappingSize
+ && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped
+ || pBuf->pMapping->eCpuMemoryOrigin ==
+ hm_wrapped_virtaddr)) {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
+ ui32Size, ui32Offset, sHashAddress.uiAddr));
+
+ pBuf->ui32RefCount++;
+ *phBuf = (BM_HANDLE) pBuf;
+ if (pui32Flags)
+ *pui32Flags = uFlags;
+
+ return 1;
+ }
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BM_BUF),
+ (void **)&pBuf, NULL,
+ "Buffer Manager buffer") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED"));
+ return 0;
+ }
+ memset(pBuf, 0, sizeof(BM_BUF));
+
+ if (WrapMemory
+ (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr,
+ uFlags, pBuf) != 1) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, NULL);
+
+ return 0;
+ }
+
+ if (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped
+ || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr) {
+
+ PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr ==
+ pBuf->CpuPAddr.uiAddr);
+
+ if (!HASH_Insert
+ (psBMContext->pBufferHash, (u32) sHashAddress.uiAddr,
+ (u32) pBuf)) {
+ FreeBuf(pBuf, uFlags);
+ PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: HASH_Insert FAILED"));
+ return 0;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_Wrap (uSize=0x%x, uFlags=0x%x)=%08X(devVAddr=%08X)",
+ ui32Size, uFlags, pBuf, pBuf->DevVAddr.uiAddr));
+
+ pBuf->ui32RefCount = 1;
+ *phBuf = (BM_HANDLE) pBuf;
+ if (pui32Flags) {
+
+ *pui32Flags =
+ (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) |
+ PVRSRV_HAP_MULTI_PROCESS;
+ }
+
+ return 1;
+}
+
+void BM_Free(BM_HANDLE hBuf, u32 ui32Flags)
+{
+ BM_BUF *pBuf = (BM_BUF *) hBuf;
+ SYS_DATA *psSysData;
+ IMG_SYS_PHYADDR sHashAddr;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_Free (h=%08X)", hBuf));
+ PVR_ASSERT(pBuf != NULL);
+
+ if (pBuf == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_Free: invalid parameter"));
+ return;
+ }
+
+ SysAcquireData(&psSysData);
+
+ pBuf->ui32RefCount--;
+
+ if (pBuf->ui32RefCount == 0) {
+ if (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped
+ || pBuf->pMapping->eCpuMemoryOrigin ==
+ hm_wrapped_virtaddr) {
+ sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+ HASH_Remove(pBuf->pMapping->pBMHeap->pBMContext->
+ pBufferHash, (u32) sHashAddr.uiAddr);
+ }
+ FreeBuf(pBuf, ui32Flags);
+ }
+}
+
+IMG_CPU_VIRTADDR BM_HandleToCpuVaddr(BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *) hBuf;
+
+ PVR_ASSERT(pBuf != NULL);
+ if (pBuf == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_HandleToCpuVaddr: invalid parameter"));
+ return NULL;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_HandleToCpuVaddr(h=%08X)=%08X", hBuf, pBuf->CpuVAddr));
+ return pBuf->CpuVAddr;
+}
+
+IMG_DEV_VIRTADDR BM_HandleToDevVaddr(BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *) hBuf;
+
+ PVR_ASSERT(pBuf != NULL);
+ if (pBuf == NULL) {
+ IMG_DEV_VIRTADDR DevVAddr = { 0 };
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_HandleToDevVaddr: invalid parameter"));
+ return DevVAddr;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_HandleToDevVaddr(h=%08X)=%08X", hBuf,
+ pBuf->DevVAddr));
+ return pBuf->DevVAddr;
+}
+
+IMG_SYS_PHYADDR BM_HandleToSysPaddr(BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *) hBuf;
+
+ PVR_ASSERT(pBuf != NULL);
+
+ if (pBuf == NULL) {
+ IMG_SYS_PHYADDR PhysAddr = { 0 };
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_HandleToSysPaddr: invalid parameter"));
+ return PhysAddr;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_HandleToSysPaddr(h=%08X)=%08X", hBuf,
+ pBuf->CpuPAddr.uiAddr));
+ return SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+}
+
+void *BM_HandleToOSMemHandle(BM_HANDLE hBuf)
+{
+ BM_BUF *pBuf = (BM_BUF *) hBuf;
+
+ PVR_ASSERT(pBuf != NULL);
+
+ if (pBuf == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_HandleToOSMemHandle: invalid parameter"));
+ return NULL;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_HandleToOSMemHandle(h=%08X)=%08X",
+ hBuf, pBuf->hOSMemHandle));
+ return pBuf->hOSMemHandle;
+}
+
+int
+BM_ContiguousStatistics(u32 uFlags, u32 * pTotalBytes, u32 * pAvailableBytes)
+{
+ if (pAvailableBytes || pTotalBytes || uFlags) ;
+ return 0;
+}
+
+static int
+DevMemoryAlloc(BM_CONTEXT * pBMContext,
+ BM_MAPPING * pMapping,
+ u32 * pActualSize,
+ u32 uFlags,
+ u32 dev_vaddr_alignment, IMG_DEV_VIRTADDR * pDevVAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+ u32 ui32PDumpSize = pMapping->uSize;
+#endif
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+ if (uFlags & PVRSRV_MEM_INTERLEAVED) {
+
+ pMapping->uSize *= 2;
+ }
+#ifdef PDUMP
+ if (uFlags & PVRSRV_MEM_DUMMY) {
+
+ ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ }
+#endif
+
+ if (!psDeviceNode->pfnMMUAlloc(pMapping->pBMHeap->pMMUHeap,
+ pMapping->uSize,
+ pActualSize,
+ 0,
+ dev_vaddr_alignment,
+ &(pMapping->DevVAddr))) {
+ PVR_DPF((PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc"));
+ return 0;
+ }
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ EnableHostAccess(pBMContext->psMMUContext);
+#endif
+
+ PDUMPMALLOCPAGES(psDeviceNode->sDevId.eDeviceType,
+ pMapping->DevVAddr.uiAddr, pMapping->CpuVAddr,
+ pMapping->hOSMemHandle, ui32PDumpSize,
+ pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+ (void *)pMapping);
+
+ switch (pMapping->eCpuMemoryOrigin) {
+ case hm_wrapped:
+ case hm_wrapped_virtaddr:
+ case hm_contiguous:
+ {
+ psDeviceNode->pfnMMUMapPages(pMapping->pBMHeap->
+ pMMUHeap,
+ pMapping->DevVAddr,
+ SysCpuPAddrToSysPAddr
+ (pMapping->CpuPAddr),
+ pMapping->uSize, uFlags,
+ (void *)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ case hm_env:
+ {
+ psDeviceNode->pfnMMUMapShadow(pMapping->pBMHeap->
+ pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->uSize,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr, uFlags,
+ (void *)pMapping);
+ break;
+ }
+ case hm_wrapped_scatter:
+ case hm_wrapped_scatter_virtaddr:
+ {
+ psDeviceNode->pfnMMUMapScatter(pMapping->pBMHeap->
+ pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->psSysAddr,
+ pMapping->uSize, uFlags,
+ (void *)pMapping);
+
+ *pDevVAddr = pMapping->DevVAddr;
+ break;
+ }
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "Illegal value %d for pMapping->eCpuMemoryOrigin",
+ pMapping->eCpuMemoryOrigin));
+ return 0;
+ }
+
+#ifdef SUPPORT_SGX_MMU_BYPASS
+ DisableHostAccess(pBMContext->psMMUContext);
+#endif
+
+ return 1;
+}
+
+static void DevMemoryFree(BM_MAPPING * pMapping)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+#ifdef PDUMP
+ u32 ui32PSize;
+#endif
+
+#ifdef PDUMP
+
+ if (pMapping->ui32Flags & PVRSRV_MEM_DUMMY) {
+
+ ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ } else {
+ ui32PSize = pMapping->uSize;
+ }
+
+ PDUMPFREEPAGES(pMapping->pBMHeap,
+ pMapping->DevVAddr,
+ ui32PSize,
+ pMapping->pBMHeap->sDevArena.ui32DataPageSize,
+ (void *)pMapping,
+ (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? 1 : 0);
+#endif
+
+ psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ psDeviceNode->pfnMMUFree(pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+}
+
+static int
+BM_ImportMemory(void *pH,
+ u32 uRequestSize,
+ u32 * pActualSize,
+ BM_MAPPING ** ppsMapping, u32 uFlags, u32 * pBase)
+{
+ BM_MAPPING *pMapping;
+ BM_HEAP *pBMHeap = pH;
+ BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+ int bResult;
+ u32 uSize;
+ u32 uPSize;
+ u32 uDevVAddrAlignment = 0;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_ImportMemory (pBMContext=%08X, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
+ pBMContext, uRequestSize, uFlags, uDevVAddrAlignment));
+
+ PVR_ASSERT(ppsMapping != NULL);
+ PVR_ASSERT(pBMContext != NULL);
+
+ if (ppsMapping == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: invalid parameter"));
+ goto fail_exit;
+ }
+
+ uSize = HOST_PAGEALIGN(uRequestSize);
+ PVR_ASSERT(uSize >= uRequestSize);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BM_MAPPING),
+ (void **)&pMapping, NULL,
+ "Buffer Manager Mapping") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: failed BM_MAPPING alloc"));
+ goto fail_exit;
+ }
+
+ pMapping->hOSMemHandle = 0;
+ pMapping->CpuVAddr = 0;
+ pMapping->DevVAddr.uiAddr = 0;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->uSize = uSize;
+ pMapping->pBMHeap = pBMHeap;
+ pMapping->ui32Flags = uFlags;
+
+ if (pActualSize) {
+ *pActualSize = uSize;
+ }
+
+ if (pMapping->ui32Flags & PVRSRV_MEM_DUMMY) {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ } else {
+ uPSize = pMapping->uSize;
+ }
+
+ if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) {
+ u32 ui32Attribs = pBMHeap->ui32Attribs;
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |=
+ (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ if (OSAllocPages(ui32Attribs,
+ uPSize,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ (void **)&pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: OSAllocPages(0x%x) failed",
+ uPSize));
+ goto fail_mapping_alloc;
+ }
+
+ pMapping->eCpuMemoryOrigin = hm_env;
+ } else if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) {
+ IMG_SYS_PHYADDR sSysPAddr;
+ u32 ui32Attribs = pBMHeap->ui32Attribs;
+
+ if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) {
+ ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
+ ui32Attribs |=
+ (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
+ }
+
+ PVR_ASSERT(pBMHeap->pLocalDevMemArena != NULL);
+
+ if (!RA_Alloc(pBMHeap->pLocalDevMemArena,
+ uPSize,
+ NULL,
+ NULL,
+ 0,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ 0, (u32 *) & sSysPAddr.uiAddr)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: RA_Alloc(0x%x) FAILED",
+ uPSize));
+ goto fail_mapping_alloc;
+ }
+
+ pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ if (OSReservePhys(pMapping->CpuPAddr,
+ uPSize,
+ ui32Attribs,
+ &pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: OSReservePhys failed"));
+ goto fail_dev_mem_alloc;
+ }
+
+ pMapping->eCpuMemoryOrigin = hm_contiguous;
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: Invalid backing store type"));
+ goto fail_mapping_alloc;
+ }
+
+ bResult = DevMemoryAlloc(pBMContext,
+ pMapping,
+ NULL,
+ uFlags,
+ uDevVAddrAlignment, &pMapping->DevVAddr);
+ if (!bResult) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_dev_mem_alloc;
+ }
+
+ PVR_ASSERT(uDevVAddrAlignment >
+ 1 ? (pMapping->DevVAddr.uiAddr % uDevVAddrAlignment) ==
+ 0 : 1);
+
+ *pBase = pMapping->DevVAddr.uiAddr;
+ *ppsMapping = pMapping;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_ImportMemory: 1"));
+ return 1;
+
+fail_dev_mem_alloc:
+ if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle)) {
+
+ if (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) {
+ pMapping->uSize /= 2;
+ }
+
+ if (pMapping->ui32Flags & PVRSRV_MEM_DUMMY) {
+ uPSize = pBMHeap->sDevArena.ui32DataPageSize;
+ } else {
+ uPSize = pMapping->uSize;
+ }
+
+ if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (void *)pMapping->CpuVAddr,
+ pMapping->hOSMemHandle);
+ } else {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ if (pMapping->CpuVAddr) {
+ OSUnReservePhys(pMapping->CpuVAddr,
+ uPSize,
+ pBMHeap->ui32Attribs,
+ pMapping->hOSMemHandle);
+ }
+ sSysPAddr = SysCpuPAddrToSysPAddr(pMapping->CpuPAddr);
+ RA_Free(pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr,
+ 0);
+ }
+ }
+fail_mapping_alloc:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, NULL);
+
+fail_exit:
+ return 0;
+}
+
+static void BM_FreeMemory(void *h, u32 _base, BM_MAPPING * psMapping)
+{
+ BM_HEAP *pBMHeap = h;
+ u32 uPSize;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)", h, _base,
+ psMapping));
+
+#ifdef INTEL_D3_P_CHANGES
+ if (NULL == pBMHeap) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+ return;
+ }
+#endif
+
+ PVR_ASSERT(psMapping != NULL);
+
+ if (psMapping == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "BM_FreeMemory: invalid parameter"));
+ return;
+ }
+
+ DevMemoryFree(psMapping);
+
+ if ((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0) {
+ psMapping->uSize /= 2;
+ }
+
+ if (psMapping->ui32Flags & PVRSRV_MEM_DUMMY) {
+ uPSize = psMapping->pBMHeap->sDevArena.ui32DataPageSize;
+ } else {
+ uPSize = psMapping->uSize;
+ }
+
+ if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) {
+ OSFreePages(pBMHeap->ui32Attribs,
+ uPSize,
+ (void *)psMapping->CpuVAddr,
+ psMapping->hOSMemHandle);
+ } else if (pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) {
+ IMG_SYS_PHYADDR sSysPAddr;
+
+ OSUnReservePhys(psMapping->CpuVAddr, uPSize,
+ pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+ sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+ RA_Free(pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr, 0);
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_FreeMemory: Invalid backing store type"));
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, NULL);
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "..BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)",
+ h, _base, psMapping));
+}
+
+void BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO * psMemInfo,
+ IMG_DEV_VIRTADDR sDevVPageAddr,
+ IMG_DEV_PHYADDR * psDevPAddr)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
+
+ PVR_ASSERT(psMemInfo && psDevPAddr)
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ psDeviceNode =
+ ((BM_BUF *) psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->
+ pBMContext->psDeviceNode;
+
+ *psDevPAddr =
+ psDeviceNode->
+ pfnMMUGetPhysPageAddr(((BM_BUF *) psMemInfo->sMemBlk.hBuffer)->
+ pMapping->pBMHeap->pMMUHeap, sDevVPageAddr);
+}
+
+PVRSRV_ERROR BM_GetHeapInfo(void *hDevMemHeap, PVRSRV_HEAP_INFO * psHeapInfo)
+{
+ BM_HEAP *psBMHeap = (BM_HEAP *) hDevMemHeap;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetHeapInfo"));
+
+ psHeapInfo->hDevMemHeap = hDevMemHeap;
+ psHeapInfo->sDevVAddrBase = psBMHeap->sDevArena.BaseDevVAddr;
+ psHeapInfo->ui32HeapByteSize = psBMHeap->sDevArena.ui32Size;
+ psHeapInfo->ui32Attribs = psBMHeap->ui32Attribs;
+
+ return PVRSRV_OK;
+}
+
+MMU_CONTEXT *BM_GetMMUContext(void *hDevMemHeap)
+{
+ BM_HEAP *pBMHeap = (BM_HEAP *) hDevMemHeap;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContext"));
+
+ return pBMHeap->pBMContext->psMMUContext;
+}
+
+MMU_CONTEXT *BM_GetMMUContextFromMemContext(void *hDevMemContext)
+{
+ BM_CONTEXT *pBMContext = (BM_CONTEXT *) hDevMemContext;
+
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUContextFromMemContext"));
+
+ return pBMContext->psMMUContext;
+}
+
+void *BM_GetMMUHeap(void *hDevMemHeap)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
+
+ return (void *)((BM_HEAP *) hDevMemHeap)->pMMUHeap;
+}
+
+PVRSRV_DEVICE_NODE *BM_GetDeviceNode(void *hDevMemContext)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
+
+ return ((BM_CONTEXT *) hDevMemContext)->psDeviceNode;
+}
+
+void *BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO * psMemInfo)
+{
+ PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
+
+ return ((BM_BUF *) psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
diff --git a/drivers/staging/ice4100/sgx535/common/deviceclass.c b/drivers/staging/ice4100/sgx535/common/deviceclass.c
new file mode 100755
index 00000000000..5d68d3b36ee
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/deviceclass.c
@@ -0,0 +1,1732 @@
+/**********************************************************************
+ *
+ * Copyright (c) 2009-2010 Intel Corporation.
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "pvr_bridge_km.h"
+
+#include "lists.h"
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+void *MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE * psDeviceNode, va_list va);
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA * psSysData, u32 * pui32DevID);
+PVRSRV_ERROR FreeDeviceID(SYS_DATA * psSysData, u32 ui32DevID);
+
+#if defined(SUPPORT_MISR_IN_THREAD)
+void OSVSyncMISR(void *, int);
+#endif
+
+typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+
+typedef struct PVRSRV_DC_BUFFER_TAG {
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+} PVRSRV_DC_BUFFER;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_TAG {
+ void *hExtSwapChain;
+ u32 ui32SwapChainID;
+ u32 ui32Flags;
+ u32 ui32RefCount;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ u32 ui32BufferCount;
+ PVRSRV_DC_BUFFER *psLastFlipBuffer;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psNext;
+ struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
+} PVRSRV_DC_SWAPCHAIN;
+
+typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG {
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
+ void *hResItem;
+} PVRSRV_DC_SWAPCHAIN_REF;
+
+typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG {
+ u32 ui32RefCount;
+ u32 ui32DeviceID;
+ void *hExtDevice;
+ PPVRSRV_DC_SRV2DISP_KMJTABLE psFuncTable;
+ void *hDevMemContext;
+ PVRSRV_DC_BUFFER sSystemBuffer;
+ struct PVRSRV_DC_SWAPCHAIN_TAG *psDCSwapChainShared;
+} PVRSRV_DISPLAYCLASS_INFO;
+
+typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG {
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PRESMAN_ITEM hResItem;
+} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+
+typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG
+ *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+typedef struct PVRSRV_BC_BUFFER_TAG {
+
+ PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+
+ struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
+} PVRSRV_BC_BUFFER;
+
+typedef struct PVRSRV_BUFFERCLASS_INFO_TAG {
+ u32 ui32RefCount;
+ u32 ui32DeviceID;
+ void *hExtDevice;
+ PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable;
+ void *hDevMemContext;
+
+ u32 ui32BufferCount;
+ PVRSRV_BC_BUFFER *psBuffer;
+
+} PVRSRV_BUFFERCLASS_INFO;
+
+typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG {
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ void *hResItem;
+} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+
+static PVRSRV_DISPLAYCLASS_INFO *DCDeviceHandleToDCInfo(void *hDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *) hDeviceKM;
+
+ return psDCPerContextInfo->psDCInfo;
+}
+
+static PVRSRV_BUFFERCLASS_INFO *BCDeviceHandleToBCInfo(void *hDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *) hDeviceKM;
+
+ return psBCPerContextInfo->psBCInfo;
+}
+
+void PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE * psDeviceNode,
+ va_list va)
+{
+ u32 *pui32DevCount;
+ u32 **ppui32DevID;
+ PVRSRV_DEVICE_CLASS peDeviceClass;
+
+ pui32DevCount = va_arg(va, u32 *);
+ ppui32DevID = va_arg(va, u32 **);
+ peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+
+ if ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass)
+ && (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT)) {
+ (*pui32DevCount)++;
+ if (*ppui32DevID) {
+ *(*ppui32DevID)++ =
+ psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+ }
+}
+
+PVRSRV_ERROR PVRSRVEnumerateDCKM(PVRSRV_DEVICE_CLASS DeviceClass,
+ u32 * pui32DevCount, u32 * pui32DevID)
+{
+
+ u32 ui32DevCount = 0;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ PVRSRVEnumerateDCKM_ForEachVaCb,
+ &ui32DevCount,
+ &pui32DevID, DeviceClass);
+
+ if (pui32DevCount) {
+ *pui32DevCount = ui32DevCount;
+ } else if (pui32DevID == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVEnumerateDCKM: Invalid parameters"));
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM(PVRSRV_DC_SRV2DISP_KMJTABLE * psFuncTable,
+ u32 * pui32DeviceID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCInfo),
+ (void **)&psDCInfo, NULL,
+ "Display Class Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psDCInfo, 0, sizeof(*psDCInfo));
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ (void **)&psDCInfo->psFuncTable, NULL,
+ "Function table for SRVKM->DISPLAY") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ memset(psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+ *psDCInfo->psFuncTable = *psFuncTable;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (void **)&psDeviceNode, NULL,
+ "Device Node") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ memset(psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (void *)psDCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
+ psDeviceNode->psSysData = psSysData;
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex)
+ != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID) {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+ SysRegisterExternalDevice(psDeviceNode);
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList,
+ psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psDCInfo->psFuncTable) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ psDCInfo->psFuncTable, NULL);
+ psDCInfo->psFuncTable = NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO),
+ psDCInfo, NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(u32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ 0, PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveDCDeviceKM: requested device %d not present",
+ ui32DevIndex));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice;
+
+ if (psDCInfo->ui32RefCount == 0) {
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+ SysRemoveExternalDevice(psDeviceNode);
+
+ PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+ (void)FreeDeviceID(psSysData, ui32DevIndex);
+ (void)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
+ psDCInfo->psFuncTable, NULL);
+ psDCInfo->psFuncTable = NULL;
+ (void)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo,
+ NULL);
+
+ (void)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, NULL);
+
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open",
+ psDCInfo->ui32RefCount));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVRegisterBCDeviceKM(PVRSRV_BC_SRV2BUFFER_KMJTABLE *
+ psFuncTable, u32 * pui32DeviceID)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo = NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCInfo),
+ (void **)&psBCInfo, NULL,
+ "Buffer Class Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psBCInfo, 0, sizeof(*psBCInfo));
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ (void **)&psBCInfo->psFuncTable, NULL,
+ "Function table for SRVKM->BUFFER") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc"));
+ goto ErrorExit;
+ }
+ memset(psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+ *psBCInfo->psFuncTable = *psFuncTable;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (void **)&psDeviceNode, NULL,
+ "Device Node") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc"));
+ goto ErrorExit;
+ }
+ memset(psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ psDeviceNode->pvDevice = (void *)psBCInfo;
+ psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo);
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT;
+ psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
+ psDeviceNode->psSysData = psSysData;
+
+ if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex)
+ != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
+ goto ErrorExit;
+ }
+ psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID) {
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList,
+ psDeviceNode);
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psBCInfo->psFuncTable) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ psBCInfo->psFuncTable, NULL);
+ psBCInfo->psFuncTable = NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO),
+ psBCInfo, NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(u32 ui32DevIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ SysAcquireData(&psSysData);
+
+ psDevNode = (PVRSRV_DEVICE_NODE *)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex,
+ 0, PVRSRV_DEVICE_CLASS_BUFFER);
+
+ if (!psDevNode) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveBCDeviceKM: requested device %d not present",
+ ui32DevIndex));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO *) psDevNode->pvDevice;
+
+ if (psBCInfo->ui32RefCount == 0) {
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
+
+ (void)FreeDeviceID(psSysData, ui32DevIndex);
+
+ (void)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ psBCInfo->psFuncTable, NULL);
+ psBCInfo->psFuncTable = NULL;
+ (void)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo,
+ NULL);
+
+ (void)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDevNode, NULL);
+
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open",
+ psBCInfo->ui32RefCount));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM(void *hDeviceKM, int bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *) hDeviceKM;
+
+ eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem);
+
+ return eError;
+}
+
+static PVRSRV_ERROR CloseDCDeviceCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *) pvParam;
+ psDCInfo = psDCPerContextInfo->psDCInfo;
+
+ psDCInfo->ui32RefCount--;
+ if (psDCInfo->ui32RefCount == 0) {
+
+ psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+ if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.
+ psKernelSyncInfo->ui32RefCount == 0) {
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ }
+
+ psDCInfo->hDevMemContext = NULL;
+ psDCInfo->hExtDevice = NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO),
+ psDCPerContextInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVOpenDCDeviceKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ u32 ui32DeviceID,
+ void *hDevCookie, void **phDeviceKM)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ if (!phDeviceKM || !hDevCookie) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ 0, PVRSRV_DEVICE_CLASS_DISPLAY);
+ if (!psDeviceNode) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: no devnode matching index %d",
+ ui32DeviceID));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCPerContextInfo),
+ (void **)&psDCPerContextInfo, NULL,
+ "Display Class per Context Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+ if (psDCInfo->ui32RefCount++ == 0) {
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+
+ psDCInfo->hDevMemContext =
+ (void *)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+ eError = PVRSRVAllocSyncInfoKM(NULL,
+ (void *)psDeviceNode->
+ sDevMemoryInfo.pBMKernelContext,
+ &psDCInfo->sSystemBuffer.
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: Failed sync info alloc"));
+ psDCInfo->ui32RefCount--;
+ return eError;
+ }
+
+ eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
+ &psDCInfo->
+ hExtDevice,
+ (PVRSRV_SYNC_DATA
+ *) psDCInfo->
+ sSystemBuffer.
+ sDeviceClassBuffer.
+ psKernelSyncInfo->
+ psSyncDataMemInfoKM->
+ pvLinAddrKM);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
+ psDCInfo->ui32RefCount--;
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ return eError;
+ }
+
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->
+ ui32RefCount++;
+ }
+
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ psDCPerContextInfo->hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+ psDCPerContextInfo, 0, CloseDCDeviceCallBack);
+
+ *phDeviceKM = (void *)psDCPerContextInfo;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVEnumDCFormatsKM(void *hDeviceKM,
+ u32 * pui32Count, DISPLAY_FORMAT * psFormat)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if (!hDeviceKM || !pui32Count || !psFormat) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVEnumDCFormatsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice,
+ pui32Count, psFormat);
+}
+
+PVRSRV_ERROR PVRSRVEnumDCDimsKM(void *hDeviceKM,
+ DISPLAY_FORMAT * psFormat,
+ u32 * pui32Count, DISPLAY_DIMS * psDim)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if (!hDeviceKM || !pui32Count || !psFormat) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVEnumDCDimsKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice,
+ psFormat, pui32Count,
+ psDim);
+}
+
+PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(void *hDeviceKM, void **phBuffer)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ void *hExtBuffer;
+
+ if (!hDeviceKM || !phBuffer) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetDCSystemBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ eError =
+ psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice,
+ &hExtBuffer);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver"));
+ return eError;
+ }
+
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr =
+ psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext =
+ psDCInfo->hDevMemContext;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice =
+ psDCInfo->hExtDevice;
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer;
+
+ psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
+
+ *phBuffer = (void *)&(psDCInfo->sSystemBuffer);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetDCInfoKM(void *hDeviceKM, DISPLAY_INFO * psDisplayInfo)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_ERROR eError;
+
+ if (!hDeviceKM || !psDisplayInfo) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetDCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ eError =
+ psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice,
+ psDisplayInfo);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ if (psDisplayInfo->ui32MaxSwapChainBuffers >
+ PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) {
+ psDisplayInfo->ui32MaxSwapChainBuffers =
+ PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(void *hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+
+ if (!hSwapChainRef) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDestroyDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChainRef = hSwapChainRef;
+
+ eError = ResManFreeResByPtr(psSwapChainRef->hResItem);
+
+ return eError;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN * psSwapChain)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
+ u32 i;
+
+ if (psDCInfo->psDCSwapChainShared) {
+ if (psDCInfo->psDCSwapChainShared == psSwapChain) {
+ psDCInfo->psDCSwapChainShared = psSwapChain->psNext;
+ } else {
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+ psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ while (psCurrentSwapChain->psNext) {
+ if (psCurrentSwapChain->psNext != psSwapChain) {
+ psCurrentSwapChain =
+ psCurrentSwapChain->psNext;
+ continue;
+ }
+ psCurrentSwapChain->psNext =
+ psSwapChain->psNext;
+ break;
+ }
+ }
+ }
+
+ PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
+
+ eError =
+ psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
+ psSwapChain->
+ hExtSwapChain);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "DestroyDCSwapChainCallBack: Failed to destroy DC swap chain"));
+ return eError;
+ }
+
+ for (i = 0; i < psSwapChain->ui32BufferCount; i++) {
+ if (psSwapChain->asBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo) {
+ if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo->ui32RefCount == 0) {
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ }
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN),
+ psSwapChain, NULL);
+
+ return eError;
+}
+
+static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef =
+ (PVRSRV_DC_SWAPCHAIN_REF *) pvParam;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (--psSwapChainRef->psSwapChain->ui32RefCount == 0) {
+ eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+ psSwapChainRef, NULL);
+ return eError;
+}
+
+static PVRSRV_DC_SWAPCHAIN
+ *PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO * psDCInfo,
+ u32 ui32SwapChainID)
+{
+ PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain;
+
+ for (psCurrentSwapChain = psDCInfo->psDCSwapChainShared;
+ psCurrentSwapChain;
+ psCurrentSwapChain = psCurrentSwapChain->psNext) {
+ if (psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID)
+ return psCurrentSwapChain;
+ }
+ return NULL;
+}
+
+static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *
+ psPerProc,
+ PVRSRV_DC_SWAPCHAIN *
+ psSwapChain,
+ PVRSRV_DC_SWAPCHAIN_REF **
+ ppsSwapChainRef)
+{
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = NULL;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN_REF),
+ (void **)&psSwapChainRef, NULL,
+ "Display Class Swapchain Reference") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
+
+ psSwapChain->ui32RefCount++;
+
+ psSwapChainRef->psSwapChain = psSwapChain;
+ psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
+ psSwapChainRef,
+ 0,
+ &DestroyDCSwapChainRefCallBack);
+ *ppsSwapChainRef = psSwapChainRef;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ void *hDeviceKM,
+ u32 ui32Flags,
+ DISPLAY_SURF_ATTRIBUTES *
+ psDstSurfAttrib,
+ DISPLAY_SURF_ATTRIBUTES *
+ psSrcSurfAttrib, u32 ui32BufferCount,
+ u32 ui32OEMFlags, void **phSwapChainRef,
+ u32 * pui32SwapChainID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain = NULL;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = NULL;
+ PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_QUEUE_INFO *psQueue = NULL;
+ PVRSRV_ERROR eError;
+ u32 i;
+ DISPLAY_INFO sDisplayInfo;
+
+ if (!hDeviceKM
+ || !psDstSurfAttrib
+ || !psSrcSurfAttrib || !phSwapChainRef || !pui32SwapChainID) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Too many buffers"));
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+ }
+
+ if (ui32BufferCount < 2) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Too few buffers"));
+ return PVRSRV_ERROR_TOO_FEW_BUFFERS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ if (ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY) {
+
+ psSwapChain =
+ PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID);
+ if (psSwapChain) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: found query"));
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain,
+ &psSwapChainRef);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ return eError;
+ }
+
+ *phSwapChainRef = (void *)psSwapChainRef;
+ return PVRSRV_OK;
+ }
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query"));
+ return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DC_SWAPCHAIN),
+ (void **)&psSwapChain, NULL,
+ "Display Class Swapchain") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+ memset(psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
+
+ eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue"));
+ goto ErrorExit;
+ }
+
+ psSwapChain->psQueue = psQueue;
+
+ for (i = 0; i < ui32BufferCount; i++) {
+ eError = PVRSRVAllocSyncInfoKM(NULL,
+ psDCInfo->hDevMemContext,
+ &psSwapChain->asBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain"));
+ goto ErrorExit;
+ }
+
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->
+ ui32RefCount++;
+
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr =
+ psDCInfo->psFuncTable->pfnGetBufferAddr;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext =
+ psDCInfo->hDevMemContext;
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice =
+ psDCInfo->hExtDevice;
+
+ psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
+ psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
+
+ apsSyncData[i] =
+ (PVRSRV_SYNC_DATA *) psSwapChain->asBuffer[i].
+ sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->
+ pvLinAddrKM;
+ }
+
+ psSwapChain->ui32BufferCount = ui32BufferCount;
+ psSwapChain->psDCInfo = psDCInfo;
+
+ eError =
+ psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice,
+ &sDisplayInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Failed to get DC info"));
+ return eError;
+ }
+
+ eError =
+ psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+ ui32Flags,
+ psDstSurfAttrib,
+ psSrcSurfAttrib,
+ ui32BufferCount,
+ apsSyncData,
+ ui32OEMFlags,
+ &psSwapChain->
+ hExtSwapChain,
+ &psSwapChain->
+ ui32SwapChainID);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain"));
+ goto ErrorExit;
+ }
+
+ eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
+ psSwapChain, &psSwapChainRef);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference"));
+ goto ErrorExit;
+ }
+
+ psSwapChain->ui32RefCount = 1;
+ psSwapChain->ui32Flags = ui32Flags;
+
+ if (ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED) {
+ if (!psDCInfo->psDCSwapChainShared) {
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ } else {
+ PVRSRV_DC_SWAPCHAIN *psOldHead =
+ psDCInfo->psDCSwapChainShared;
+ psDCInfo->psDCSwapChainShared = psSwapChain;
+ psSwapChain->psNext = psOldHead;
+ }
+ }
+
+ *pui32SwapChainID = psSwapChain->ui32SwapChainID;
+
+ *phSwapChainRef = (void *)psSwapChainRef;
+
+ return eError;
+
+ErrorExit:
+
+ for (i = 0; i < ui32BufferCount; i++) {
+ if (psSwapChain->asBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo) {
+ if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo->ui32RefCount == 0) {
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ }
+ }
+ }
+
+ if (psQueue) {
+ PVRSRVDestroyCommandQueueKM(psQueue);
+ }
+
+ if (psSwapChain) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN),
+ psSwapChain, NULL);
+
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSetDCDstRectKM(void *hDeviceKM,
+ void *hSwapChainRef, IMG_RECT * psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChainRef) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDCDstRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF *) hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+ psSwapChain->
+ hExtSwapChain, psRect);
+}
+
+PVRSRV_ERROR PVRSRVSetDCSrcRectKM(void *hDeviceKM,
+ void *hSwapChainRef, IMG_RECT * psRect)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChainRef) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDCSrcRectKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF *) hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+ psSwapChain->
+ hExtSwapChain, psRect);
+}
+
+PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(void *hDeviceKM,
+ void *hSwapChainRef, u32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChainRef) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDCDstColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF *) hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+ psSwapChain->
+ hExtSwapChain,
+ ui32CKColour);
+}
+
+PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(void *hDeviceKM,
+ void *hSwapChainRef, u32 ui32CKColour)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChainRef) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDCSrcColourKeyKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF *) hSwapChainRef)->psSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+ psSwapChain->
+ hExtSwapChain,
+ ui32CKColour);
+}
+
+PVRSRV_ERROR PVRSRVGetDCBuffersKM(void *hDeviceKM,
+ void *hSwapChainRef,
+ u32 * pui32BufferCount, void **phBuffer)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ void *ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ PVRSRV_ERROR eError;
+ u32 i;
+
+ if (!hDeviceKM || !hSwapChainRef || !phBuffer) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetDCBuffersKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF *) hSwapChainRef)->psSwapChain;
+
+ eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
+ psSwapChain->
+ hExtSwapChain,
+ pui32BufferCount,
+ ahExtBuffer);
+
+ PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
+
+ for (i = 0; i < *pui32BufferCount; i++) {
+ psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer =
+ ahExtBuffer[i];
+ phBuffer[i] = (void *)&psSwapChain->asBuffer[i];
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSwapToDCBufferKM(void *hDeviceKM,
+ void *hBuffer,
+ u32 ui32SwapInterval,
+ void *hPrivateTag,
+ u32 ui32ClipRectCount,
+ IMG_RECT * psClipRect)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_BUFFER *psBuffer;
+ PVRSRV_QUEUE_INFO *psQueue;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ u32 i;
+ u32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+
+ if (!hDeviceKM || !hBuffer || !psClipRect) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#if defined(SUPPORT_LMA)
+ eError = PVRSRVPowerLock(KERNEL_ID, 0);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+#endif
+
+ psBuffer = (PVRSRV_DC_BUFFER *) hBuffer;
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ psQueue = psBuffer->psSwapChain->psQueue;
+
+ apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
+
+ if (psBuffer->psSwapChain->psLastFlipBuffer &&
+ psBuffer != psBuffer->psSwapChain->psLastFlipBuffer) {
+ apsSrcSync[1] =
+ psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
+ psKernelSyncInfo;
+
+ ui32NumSrcSyncs++;
+ }
+
+ eError = PVRSRVInsertCommandKM(psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ DC_FLIP_COMMAND,
+ 0,
+ NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND) +
+ (sizeof(IMG_RECT) * ui32ClipRectCount));
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND *) psCommand->pvData;
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+ psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
+
+ psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
+
+ psFlipCmd->hPrivateTag = hPrivateTag;
+
+ psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
+
+ psFlipCmd->psClipRect =
+ (IMG_RECT *) ((u8 *) psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));
+
+ for (i = 0; i < ui32ClipRectCount; i++) {
+ psFlipCmd->psClipRect[i] = psClipRect[i];
+ }
+
+ psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+ eError = PVRSRVSubmitCommandKM(psQueue, psCommand);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCBufferKM: Failed to submit command"));
+ goto Exit;
+ }
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if (PVRSRVProcessQueues(KERNEL_ID, 0) !=
+ PVRSRV_ERROR_PROCESSING_BLOCKED) {
+ goto ProcessedQueues;
+ }
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCBufferKM: Failed to process queues"));
+
+ eError = PVRSRV_ERROR_GENERIC;
+ goto Exit;
+
+ProcessedQueues:
+
+ psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
+
+Exit:
+
+ if (eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+#if defined(SUPPORT_LMA)
+ PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSwapToDCSystemKM(void *hDeviceKM, void *hSwapChainRef)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef;
+ DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ u32 ui32NumSrcSyncs = 1;
+ PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ PVRSRV_COMMAND *psCommand;
+
+ if (!hDeviceKM || !hSwapChainRef) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCSystemKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#if defined(SUPPORT_LMA)
+ eError = PVRSRVPowerLock(KERNEL_ID, 0);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+#endif
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) hSwapChainRef;
+ psSwapChain = psSwapChainRef->psSwapChain;
+
+ psQueue = psSwapChain->psQueue;
+
+ apsSrcSync[0] =
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
+
+ if (psSwapChain->psLastFlipBuffer) {
+
+ if (apsSrcSync[0] !=
+ psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
+ psKernelSyncInfo) {
+ apsSrcSync[1] =
+ psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.
+ psKernelSyncInfo;
+
+ ui32NumSrcSyncs++;
+ }
+ }
+
+ eError = PVRSRVInsertCommandKM(psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ DC_FLIP_COMMAND,
+ 0,
+ NULL,
+ ui32NumSrcSyncs,
+ apsSrcSync,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND));
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND *) psCommand->pvData;
+
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+ psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+ psFlipCmd->hExtBuffer =
+ psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
+
+ psFlipCmd->hPrivateTag = NULL;
+
+ psFlipCmd->ui32ClipRectCount = 0;
+
+ psFlipCmd->ui32SwapInterval = 1;
+
+ eError = PVRSRVSubmitCommandKM(psQueue, psCommand);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCSystemKM: Failed to submit command"));
+ goto Exit;
+ }
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if (PVRSRVProcessQueues(KERNEL_ID, 0) !=
+ PVRSRV_ERROR_PROCESSING_BLOCKED) {
+ goto ProcessedQueues;
+ }
+
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSwapToDCSystemKM: Failed to process queues"));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto Exit;
+
+ProcessedQueues:
+
+ psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
+
+ eError = PVRSRV_OK;
+
+Exit:
+
+ if (eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+#if defined(SUPPORT_LMA)
+ PVRSRVPowerUnlock(KERNEL_ID);
+#endif
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRegisterSystemISRHandler(PFN_ISR_HANDLER pfnISRHandler,
+ void *pvISRHandlerData,
+ u32 ui32ISRSourceMask,
+ u32 ui32DeviceID)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_DEVICE_NODE *psDevNode;
+
+ SysAcquireData(&psSysData);
+
+ psDevNode = (PVRSRV_DEVICE_NODE *)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DeviceID, 1);
+
+ if (psDevNode == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterSystemISRHandler: Failed to get psDevNode"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDevNode->pvISRData = (void *)pvISRHandlerData;
+
+ psDevNode->pfnDeviceISR = pfnISRHandler;
+
+ return PVRSRV_OK;
+}
+
+void PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE * psDeviceNode, va_list va)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ u32 ui32State;
+ ui32State = va_arg(va, u32);
+
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY) {
+ psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *) psDeviceNode->pvDevice;
+ if (psDCInfo->psFuncTable->pfnSetDCState
+ && psDCInfo->hExtDevice) {
+ psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->
+ hExtDevice,
+ ui32State);
+ }
+ }
+}
+
+void PVRSRVSetDCState(u32 ui32State)
+{
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ PVRSRVSetDCState_ForEachVaCb,
+ ui32State);
+}
+
+int PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE * psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE);
+ psJTable->pfnPVRSRVRegisterDCDevice = PVRSRVRegisterDCDeviceKM;
+ psJTable->pfnPVRSRVRemoveDCDevice = PVRSRVRemoveDCDeviceKM;
+ psJTable->pfnPVRSRVOEMFunction = SysOEMFunction;
+ psJTable->pfnPVRSRVRegisterCmdProcList = PVRSRVRegisterCmdProcListKM;
+ psJTable->pfnPVRSRVRemoveCmdProcList = PVRSRVRemoveCmdProcListKM;
+#if defined(SUPPORT_MISR_IN_THREAD)
+ psJTable->pfnPVRSRVCmdComplete = OSVSyncMISR;
+#else
+ psJTable->pfnPVRSRVCmdComplete = PVRSRVCommandCompleteKM;
+#endif
+ psJTable->pfnPVRSRVRegisterSystemISRHandler =
+ PVRSRVRegisterSystemISRHandler;
+ psJTable->pfnPVRSRVRegisterPowerDevice = PVRSRVRegisterPowerDevice;
+
+ return 1;
+}
+
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM(void *hDeviceKM, int bResManCallback)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *) hDeviceKM;
+
+ eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem);
+
+ return eError;
+}
+
+static PVRSRV_ERROR CloseBCDeviceCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *) pvParam;
+ psBCInfo = psBCPerContextInfo->psBCInfo;
+
+ psBCInfo->ui32RefCount--;
+ if (psBCInfo->ui32RefCount == 0) {
+ u32 i;
+
+ psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->hExtDevice);
+
+ for (i = 0; i < psBCInfo->ui32BufferCount; i++) {
+ if (psBCInfo->psBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo) {
+ if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo->ui32RefCount == 0) {
+ PVRSRVFreeSyncInfoKM(psBCInfo->
+ psBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ }
+ }
+ }
+
+ if (psBCInfo->psBuffer) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer,
+ NULL);
+ psBCInfo->psBuffer = NULL;
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO),
+ psBCPerContextInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVOpenBCDeviceKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ u32 ui32DeviceID,
+ void *hDevCookie, void **phDeviceKM)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ u32 i;
+ PVRSRV_ERROR eError;
+
+ if (!phDeviceKM || !hDevCookie) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Invalid params"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DeviceID,
+ 0, PVRSRV_DEVICE_CLASS_BUFFER);
+ if (!psDeviceNode) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: No devnode matching index %d",
+ ui32DeviceID));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ psBCInfo = (PVRSRV_BUFFERCLASS_INFO *) psDeviceNode->pvDevice;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCPerContextInfo),
+ (void **)&psBCPerContextInfo, NULL,
+ "Buffer Class per Context Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+ if (psBCInfo->ui32RefCount++ == 0) {
+ BUFFER_INFO sBufferInfo;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+
+ psBCInfo->hDevMemContext =
+ (void *)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
+
+ eError =
+ psBCInfo->psFuncTable->pfnOpenBCDevice(&psBCInfo->
+ hExtDevice);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Failed to open external BC device"));
+ return eError;
+ }
+
+ eError =
+ psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice,
+ &sBufferInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM : Failed to get BC Info"));
+ return eError;
+ }
+
+ psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_BC_BUFFER) *
+ sBufferInfo.ui32BufferCount,
+ (void **)&psBCInfo->psBuffer, NULL,
+ "Array of Buffer Class Buffer");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers"));
+ return eError;
+ }
+ memset(psBCInfo->psBuffer,
+ 0,
+ sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount);
+
+ for (i = 0; i < psBCInfo->ui32BufferCount; i++) {
+
+ eError = PVRSRVAllocSyncInfoKM(NULL,
+ psBCInfo->hDevMemContext,
+ &psBCInfo->psBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
+ goto ErrorExit;
+ }
+
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo->ui32RefCount++;
+
+ eError =
+ psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->
+ hExtDevice, i,
+ psBCInfo->
+ psBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo->
+ psSyncData,
+ &psBCInfo->
+ psBuffer[i].
+ sDeviceClassBuffer.
+ hExtBuffer);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Failed to get BC buffers"));
+ goto ErrorExit;
+ }
+
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.
+ pfnGetBufferAddr =
+ psBCInfo->psFuncTable->pfnGetBufferAddr;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.
+ hDevMemContext = psBCInfo->hDevMemContext;
+ psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice =
+ psBCInfo->hExtDevice;
+ }
+ }
+
+ psBCPerContextInfo->psBCInfo = psBCInfo;
+ psBCPerContextInfo->hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+ psBCPerContextInfo, 0, CloseBCDeviceCallBack);
+
+ *phDeviceKM = (void *)psBCPerContextInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+#if defined(INTEL_D3_P_CHANGES)
+ if (psBCInfo->psBuffer == NULL) {
+ return eError;
+ }
+#endif
+
+ for (i = 0; i < psBCInfo->ui32BufferCount; i++) {
+ if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) {
+ if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo->ui32RefCount == 0) {
+ PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ }
+ }
+ }
+
+ if (psBCInfo->psBuffer) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER),
+ psBCInfo->psBuffer, NULL);
+ psBCInfo->psBuffer = NULL;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVGetBCInfoKM(void *hDeviceKM, BUFFER_INFO * psBufferInfo)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ PVRSRV_ERROR eError;
+
+ if (!hDeviceKM || !psBufferInfo) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetBCInfoKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ eError =
+ psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice,
+ psBufferInfo);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetBCInfoKM : Failed to get BC Info"));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetBCBufferKM(void *hDeviceKM,
+ u32 ui32BufferIndex, void **phBuffer)
+{
+ PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ if (!hDeviceKM || !phBuffer) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetBCBufferKM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM);
+
+ if (ui32BufferIndex < psBCInfo->ui32BufferCount) {
+ *phBuffer = (void *)&psBCInfo->psBuffer[ui32BufferIndex];
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)",
+ ui32BufferIndex, psBCInfo->ui32BufferCount));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+int PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE * psJTable)
+{
+ psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+ psJTable->pfnPVRSRVRegisterBCDevice = PVRSRVRegisterBCDeviceKM;
+ psJTable->pfnPVRSRVRemoveBCDevice = PVRSRVRemoveBCDeviceKM;
+
+ return 1;
+}
diff --git a/drivers/staging/ice4100/sgx535/common/devicemem.c b/drivers/staging/ice4100/sgx535/common/devicemem.c
new file mode 100755
index 00000000000..f7a38e59463
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/devicemem.c
@@ -0,0 +1,1253 @@
+/**********************************************************************
+ *
+ * Copyright (c) 2009-2010 Intel Corporation.
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pdump_km.h"
+#include "pvr_bridge_km.h"
+
+static PVRSRV_ERROR AllocDeviceMem(void *hDevCookie,
+ void *hDevMemHeap,
+ u32 ui32Flags,
+ u32 ui32Size,
+ u32 ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO ** ppsMemInfo);
+
+typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_ {
+
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+
+ PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
+} RESMAN_MAP_DEVICE_MEM_DATA;
+
+PVRSRV_ERROR PVRSRVGetDeviceMemHeapsKM(void *hDevCookie,
+ PVRSRV_HEAP_INFO * psHeapInfo)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ u32 ui32HeapCount;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ u32 i;
+
+ if (hDevCookie == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetDeviceMemHeapsKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+ for (i = 0; i < ui32HeapCount; i++) {
+
+ psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[i].sDevVAddrBase =
+ psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[i].ui32HeapByteSize =
+ psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ }
+
+ for (; i < PVRSRV_MAX_CLIENT_HEAPS; i++) {
+ memset(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+ psHeapInfo[i].ui32HeapID = (u32) PVRSRV_UNDEFINED_HEAP_ID;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCreateDeviceMemContextKM(void *hDevCookie,
+ PVRSRV_PER_PROCESS_DATA * psPerProc,
+ void **phDevMemContext,
+ u32 * pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO * psHeapInfo,
+ int *pbCreated, int *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ u32 ui32HeapCount, ui32ClientHeapCount = 0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ void *hDevMemContext;
+ void *hDevMemHeap;
+ IMG_DEV_PHYADDR sPDDevPAddr;
+ u32 i;
+
+ if (hDevCookie == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDeviceMemContextKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+ hDevMemContext = BM_CreateContext(psDeviceNode,
+ &sPDDevPAddr, psPerProc, pbCreated);
+ if (hDevMemContext == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateDeviceMemContextKM: Failed BM_CreateContext"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (i = 0; i < ui32HeapCount; i++) {
+ switch (psDeviceMemoryHeap[i].DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID =
+ psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
+ psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
+ psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].
+ ui32HeapByteSize =
+ psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs =
+ psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = 1;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap
+ [i]);
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID =
+ psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
+ hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
+ psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].
+ ui32HeapByteSize =
+ psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs =
+ psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = 0;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+ *phDevMemContext = hDevMemContext;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVDestroyDeviceMemContextKM(void *hDevCookie,
+ void *hDevMemContext,
+ int *pbDestroyed)
+{
+ return BM_DestroyContext(hDevMemContext, pbDestroyed);
+}
+
+PVRSRV_ERROR PVRSRVGetDeviceMemHeapInfoKM(void *hDevCookie,
+ void *hDevMemContext,
+ u32 * pui32ClientHeapCount,
+ PVRSRV_HEAP_INFO * psHeapInfo,
+ int *pbShared)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ u32 ui32HeapCount, ui32ClientHeapCount = 0;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ void *hDevMemHeap;
+ u32 i;
+
+ if (hDevCookie == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetDeviceMemHeapInfoKM: hDevCookie invalid"));
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+
+ PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
+
+ for (i = 0; i < ui32HeapCount; i++) {
+ switch (psDeviceMemoryHeap[i].DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID =
+ psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
+ psDeviceMemoryHeap[i].hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
+ psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].
+ ui32HeapByteSize =
+ psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs =
+ psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = 1;
+#endif
+ ui32ClientHeapCount++;
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap
+ [i]);
+
+ psHeapInfo[ui32ClientHeapCount].ui32HeapID =
+ psDeviceMemoryHeap[i].ui32HeapID;
+ psHeapInfo[ui32ClientHeapCount].hDevMemHeap =
+ hDevMemHeap;
+ psHeapInfo[ui32ClientHeapCount].sDevVAddrBase =
+ psDeviceMemoryHeap[i].sDevVAddrBase;
+ psHeapInfo[ui32ClientHeapCount].
+ ui32HeapByteSize =
+ psDeviceMemoryHeap[i].ui32HeapSize;
+ psHeapInfo[ui32ClientHeapCount].ui32Attribs =
+ psDeviceMemoryHeap[i].ui32Attribs;
+#if defined(PVR_SECURE_HANDLES)
+ pbShared[ui32ClientHeapCount] = 0;
+#endif
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ }
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR AllocDeviceMem(void *hDevCookie,
+ void *hDevMemHeap,
+ u32 ui32Flags,
+ u32 ui32Size,
+ u32 ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO ** ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ BM_HANDLE hBuffer;
+
+ PVRSRV_MEMBLK *psMemBlock;
+ int bBMError;
+
+ *ppsMemInfo = NULL;
+
+#ifdef INTEL_D3_PAD
+ while (ui32Alignment % 64) {
+ ui32Alignment <<= 1;
+ }
+#endif
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (void **)&psMemInfo, NULL,
+ "Kernel Memory Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocDeviceMem: Failed to alloc memory for block"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ memset(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+ bBMError = BM_Alloc(hDevMemHeap,
+ NULL,
+ ui32Size,
+ &psMemInfo->ui32Flags,
+ IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment), &hBuffer);
+
+ if (!bBMError) {
+ PVR_DPF((PVR_DBG_ERROR, "AllocDeviceMem: BM_Alloc Failed"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+ psMemBlock->hBuffer = (void *)hBuffer;
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+
+ psMemInfo->ui32AllocSize = ui32Size;
+
+ psMemInfo->pvSysBackupBuffer = NULL;
+
+ *ppsMemInfo = psMemInfo;
+
+ return (PVRSRV_OK);
+}
+
+static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO * psMemInfo)
+{
+ BM_HANDLE hBuffer;
+
+ if (!psMemInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ hBuffer = psMemInfo->sMemBlk.hBuffer;
+
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+
+ if (psMemInfo->pvSysBackupBuffer) {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->ui32AllocSize,
+ psMemInfo->pvSysBackupBuffer, NULL);
+ psMemInfo->pvSysBackupBuffer = NULL;
+ }
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psMemInfo, NULL);
+
+ return (PVRSRV_OK);
+}
+
+PVRSRV_ERROR PVRSRVAllocSyncInfoKM(void *hDevCookie,
+ void *hDevMemContext,
+ PVRSRV_KERNEL_SYNC_INFO ** ppsKernelSyncInfo)
+{
+ void *hSyncDevMemHeap;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ BM_CONTEXT *pBMContext;
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_SYNC_DATA *psSyncData;
+
+ eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO),
+ (void **)&psKernelSyncInfo, NULL,
+ "Kernel Synchronization Info");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psKernelSyncInfo->ui32RefCount = 0;
+
+ pBMContext = (BM_CONTEXT *) hDevMemContext;
+ psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+ hSyncDevMemHeap =
+ psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
+ ui32SyncHeapID].hDevMemHeap;
+
+ eError = AllocDeviceMem(hDevCookie,
+ hSyncDevMemHeap,
+ PVRSRV_MEM_CACHE_CONSISTENT,
+ sizeof(PVRSRV_SYNC_DATA),
+ sizeof(u32),
+ &psKernelSyncInfo->psSyncDataMemInfoKM);
+
+ if (eError != PVRSRV_OK) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo,
+ NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psKernelSyncInfo->psSyncData =
+ psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
+ psSyncData = psKernelSyncInfo->psSyncData;
+
+ psSyncData->ui32WriteOpsPending = 0;
+ psSyncData->ui32WriteOpsComplete = 0;
+ psSyncData->ui32ReadOpsPending = 0;
+ psSyncData->ui32ReadOpsComplete = 0;
+ psSyncData->ui32LastOpDumpVal = 0;
+ psSyncData->ui32LastReadOpDumpVal = 0;
+
+#if defined(PDUMP)
+ PDUMPMEM(psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM,
+ psKernelSyncInfo->psSyncDataMemInfoKM,
+ 0,
+ psKernelSyncInfo->psSyncDataMemInfoKM->ui32AllocSize,
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+ psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr =
+ psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr +
+ offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr =
+ psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr +
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+
+ psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = NULL;
+
+ psKernelSyncInfo->hResItem = NULL;
+
+ *ppsKernelSyncInfo = psKernelSyncInfo;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO * psKernelSyncInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if (psKernelSyncInfo->ui32RefCount != 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "oops: sync info ref count not zero at destruction"));
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+ (void)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO),
+ psKernelSyncInfo, NULL);
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeDeviceMemCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+ psMemInfo->ui32RefCount--;
+
+ if (psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) {
+ void *hMemInfo = NULL;
+
+ if (psMemInfo->ui32RefCount != 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeDeviceMemCallBack: mappings are open in other processes"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &hMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeDeviceMemCallBack: can't find exported meminfo in the global handle list"));
+ return eError;
+ }
+
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeDeviceMemCallBack: PVRSRVReleaseHandle failed for exported meminfo"));
+ return eError;
+ }
+ }
+
+ PVR_ASSERT(psMemInfo->ui32RefCount == 0);
+
+ if (psMemInfo->psKernelSyncInfo) {
+ psMemInfo->psKernelSyncInfo->ui32RefCount--;
+
+ if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0) {
+ eError =
+ PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+ }
+ }
+
+ if (eError == PVRSRV_OK) {
+ eError = FreeDeviceMem(psMemInfo);
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVFreeDeviceMemKM(void *hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO * psMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if (!psMemInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (psMemInfo->sMemBlk.hResItem != NULL) {
+ eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+ } else {
+
+ eError = FreeDeviceMemCallBack(psMemInfo, 0);
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR _PVRSRVAllocDeviceMemKM(void *hDevCookie,
+ PVRSRV_PER_PROCESS_DATA * psPerProc,
+ void *hDevMemHeap,
+ u32 ui32Flags,
+ u32 ui32Size,
+ u32 ui32Alignment,
+ PVRSRV_KERNEL_MEM_INFO ** ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_ERROR eError;
+ BM_HEAP *psBMHeap;
+ void *hDevMemContext;
+
+ if (!hDevMemHeap || (ui32Size == 0)) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK) {
+ if (((ui32Size % HOST_PAGESIZE()) != 0) ||
+ ((ui32Alignment % HOST_PAGESIZE()) != 0)) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ eError = AllocDeviceMem(hDevCookie,
+ hDevMemHeap,
+ ui32Flags, ui32Size, ui32Alignment, &psMemInfo);
+
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ if (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ) {
+ psMemInfo->psKernelSyncInfo = NULL;
+ } else {
+
+ psBMHeap = (BM_HEAP *) hDevMemHeap;
+ hDevMemContext = (void *)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if (eError != PVRSRV_OK) {
+ goto free_mainalloc;
+ }
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+ }
+
+ *ppsMemInfo = psMemInfo;
+
+ if (ui32Flags & PVRSRV_MEM_NO_RESMAN) {
+ psMemInfo->sMemBlk.hResItem = NULL;
+ } else {
+
+ psMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ psMemInfo, 0, FreeDeviceMemCallBack);
+ if (psMemInfo->sMemBlk.hResItem == NULL) {
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto free_mainalloc;
+ }
+ }
+
+ psMemInfo->ui32RefCount++;
+
+ return (PVRSRV_OK);
+
+free_mainalloc:
+ FreeDeviceMem(psMemInfo);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVDissociateDeviceMemKM(void *hDevCookie,
+ PVRSRV_KERNEL_MEM_INFO * psMemInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode = hDevCookie;
+
+ if (!psMemInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError =
+ ResManDissociateRes(psMemInfo->sMemBlk.hResItem,
+ psDeviceNode->hResManContext);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVGetFreeDeviceMemKM(u32 ui32Flags,
+ u32 * pui32Total,
+ u32 * pui32Free, u32 * pui32LargestBlock)
+{
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVUnwrapExtMemoryKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo)
+{
+ if (!psMemInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+static PVRSRV_ERROR UnwrapExtMemoryCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+ void *hOSWrapMem;
+
+ hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+ if (psMemInfo->psKernelSyncInfo) {
+ psMemInfo->psKernelSyncInfo->ui32RefCount--;
+ if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0) {
+ eError =
+ PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+ }
+ }
+
+ if (psMemInfo->sMemBlk.psIntSysPAddr) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR),
+ psMemInfo->sMemBlk.psIntSysPAddr, NULL);
+ psMemInfo->sMemBlk.psIntSysPAddr = NULL;
+ }
+
+ if (eError == PVRSRV_OK) {
+
+ psMemInfo->ui32RefCount--;
+
+ eError = FreeDeviceMem(psMemInfo);
+ }
+
+ if (hOSWrapMem) {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVWrapExtMemoryKM(void *hDevCookie,
+ PVRSRV_PER_PROCESS_DATA * psPerProc,
+ void *hDevMemContext,
+ u32 ui32ByteSize,
+ u32 ui32PageOffset,
+ int bPhysContig,
+ IMG_SYS_PHYADDR * psExtSysPAddr,
+ void *pvLinAddr,
+ u32 ui32Flags,
+ PVRSRV_KERNEL_MEM_INFO ** ppsMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ u32 ui32HostPageSize = HOST_PAGESIZE();
+ void *hDevMemHeap = NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ int bBMError;
+ BM_HEAP *psBMHeap;
+ PVRSRV_ERROR eError;
+ void *pvPageAlignedCPUVAddr;
+ IMG_SYS_PHYADDR *psIntSysPAddr = NULL;
+ void *hOSWrapMem = NULL;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ u32 ui32PageCount = 0;
+ u32 i;
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *) hDevCookie;
+ PVR_ASSERT(psDeviceNode != NULL);
+
+ if (psDeviceNode == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#ifdef INTEL_D3_CHANGES
+ if (pvLinAddr && psExtSysPAddr == NULL)
+#else
+ if (pvLinAddr)
+#endif
+ {
+
+ ui32PageOffset = (u32) pvLinAddr & (ui32HostPageSize - 1);
+
+ ui32PageCount =
+ HOST_PAGEALIGN(ui32ByteSize +
+ ui32PageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr =
+ (void *)((u32) pvLinAddr - ui32PageOffset);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+ (void **)&psIntSysPAddr, NULL,
+ "Array of Page Addresses") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+ ui32PageCount * ui32HostPageSize,
+ psIntSysPAddr,
+ &hOSWrapMem,
+ (ui32Flags != 0) ? 1 : 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase1;
+ }
+
+ psExtSysPAddr = psIntSysPAddr;
+
+ bPhysContig = 0;
+ } else {
+
+ }
+
+ psDevMemoryInfo =
+ &((BM_CONTEXT *) hDevMemContext)->psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for (i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++) {
+ if (HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) ==
+ psDevMemoryInfo->ui32MappingHeapID) {
+ if (psDeviceMemoryHeap[i].DevMemHeapType ==
+ DEVICE_MEMORY_HEAP_PERCONTEXT) {
+
+ hDevMemHeap =
+ BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+ } else {
+ hDevMemHeap =
+ psDevMemoryInfo->psDeviceMemoryHeap[i].
+ hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if (hDevMemHeap == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: unable to find mapping heap"));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto ErrorExitPhase2;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (void **)&psMemInfo, NULL,
+ "Kernel Memory Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase2;
+ }
+
+ memset(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ ui32ByteSize,
+ ui32PageOffset,
+ bPhysContig,
+ psExtSysPAddr,
+ NULL, &psMemInfo->ui32Flags, &hBuffer);
+ if (!bBMError) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExitPhase3;
+ }
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+ psMemBlock->hOSWrapMem = hOSWrapMem;
+ psMemBlock->psIntSysPAddr = psIntSysPAddr;
+
+ psMemBlock->hBuffer = (void *)hBuffer;
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = ui32ByteSize;
+
+ psMemInfo->pvSysBackupBuffer = NULL;
+
+ psBMHeap = (BM_HEAP *) hDevMemHeap;
+ hDevMemContext = (void *)psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExitPhase4;
+ }
+
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+ psMemInfo->ui32RefCount++;
+
+ psMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0,
+ UnwrapExtMemoryCallBack);
+
+ *ppsMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+ErrorExitPhase4:
+ if (psMemInfo) {
+ FreeDeviceMem(psMemInfo);
+
+ psMemInfo = NULL;
+ }
+
+ErrorExitPhase3:
+ if (psMemInfo) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL);
+
+ }
+
+ErrorExitPhase2:
+ if (psIntSysPAddr) {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+
+ErrorExitPhase1:
+ if (psIntSysPAddr) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+ psIntSysPAddr, NULL);
+
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVUnmapDeviceMemoryKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo)
+{
+ if (!psMemInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+static PVRSRV_ERROR UnmapDeviceMemoryCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_ERROR eError;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = pvParam;
+
+ if (psMapData->psMemInfo->sMemBlk.psIntSysPAddr) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR),
+ psMapData->psMemInfo->sMemBlk.psIntSysPAddr, NULL);
+ psMapData->psMemInfo->sMemBlk.psIntSysPAddr = NULL;
+ }
+
+ psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--;
+ if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0) {
+ eError =
+ PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->
+ psKernelSyncInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "UnmapDeviceMemoryCallBack: Failed to free sync info"));
+ return eError;
+ }
+ }
+
+ eError = FreeDeviceMem(psMapData->psMemInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "UnmapDeviceMemoryCallBack: Failed to free DST meminfo"));
+ return eError;
+ }
+
+ psMapData->psSrcMemInfo->ui32RefCount--;
+
+ if (psMapData->psSrcMemInfo->ui32RefCount == 1 &&
+ psMapData->psSrcMemInfo->bPendingFree == 1) {
+
+ if (psMapData->psSrcMemInfo->sMemBlk.hResItem != NULL) {
+
+ eError =
+ ResManFreeResByPtr(psMapData->psSrcMemInfo->sMemBlk.
+ hResItem);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "UnmapDeviceMemoryCallBack: Failed to free SRC meminfo"));
+ PVR_DBG_BREAK;
+ }
+ } else {
+
+ eError =
+ FreeDeviceMemCallBack(psMapData->psSrcMemInfo, 0);
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+ psMapData, NULL);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ PVRSRV_KERNEL_MEM_INFO * psSrcMemInfo,
+ void *hDstDevMemHeap,
+ PVRSRV_KERNEL_MEM_INFO ** ppsDstMemInfo)
+{
+ PVRSRV_ERROR eError;
+ u32 i;
+ u32 ui32PageCount, ui32PageOffset;
+ u32 ui32HostPageSize = HOST_PAGESIZE();
+ IMG_SYS_PHYADDR *psSysPAddr = NULL;
+ IMG_DEV_PHYADDR sDevPAddr;
+ BM_BUF *psBuf;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL;
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ int bBMError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ void *pvPageAlignedCPUVAddr;
+ RESMAN_MAP_DEVICE_MEM_DATA *psMapData = NULL;
+
+ if (!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ *ppsDstMemInfo = NULL;
+
+ ui32PageOffset =
+ psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
+ ui32PageCount =
+ HOST_PAGEALIGN(psSrcMemInfo->ui32AllocSize +
+ ui32PageOffset) / ui32HostPageSize;
+ pvPageAlignedCPUVAddr =
+ (void *)((u32) psSrcMemInfo->pvLinAddrKM - ui32PageOffset);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageCount * sizeof(IMG_SYS_PHYADDR),
+ (void **)&psSysPAddr, NULL,
+ "Array of Page Addresses") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psBuf = psSrcMemInfo->sMemBlk.hBuffer;
+
+ psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ sDevVAddr.uiAddr =
+ psSrcMemInfo->sDevVAddr.uiAddr -
+ IMG_CAST_TO_DEVVADDR_UINT(ui32PageOffset);
+ for (i = 0; i < ui32PageCount; i++) {
+ BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+
+ psSysPAddr[i] =
+ SysDevPAddrToSysPAddr(psDeviceNode->sDevId.eDeviceType,
+ sDevPAddr);
+
+ sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
+ (void **)&psMapData, NULL,
+ "Resource Manager Map Data") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceMemoryKM: Failed to alloc resman map data"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (void **)&psMemInfo, NULL,
+ "Kernel Memory Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceMemoryKM: Failed to alloc memory for block"));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ memset(psMemInfo, 0, sizeof(*psMemInfo));
+ psMemInfo->ui32Flags = psSrcMemInfo->ui32Flags;
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDstDevMemHeap,
+ psSrcMemInfo->ui32AllocSize,
+ ui32PageOffset,
+ 0,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags, &hBuffer);
+
+ if (!bBMError) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceMemoryKM: BM_Wrap Failed"));
+ eError = PVRSRV_ERROR_BAD_MAPPING;
+ goto ErrorExit;
+ }
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+ psMemBlock->hBuffer = (void *)hBuffer;
+
+ psMemBlock->psIntSysPAddr = psSysPAddr;
+
+ psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = psSrcMemInfo->ui32AllocSize;
+ psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
+
+ psMemInfo->psKernelSyncInfo->ui32RefCount++;
+
+ psMemInfo->pvSysBackupBuffer = NULL;
+
+ psSrcMemInfo->ui32RefCount++;
+
+ psMapData->psMemInfo = psMemInfo;
+ psMapData->psSrcMemInfo = psSrcMemInfo;
+
+ psMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_MAPPING, psMapData, 0,
+ UnmapDeviceMemoryCallBack);
+
+ *ppsDstMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psSysPAddr) {
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR),
+ psSysPAddr, NULL);
+
+ }
+
+ if (psMemInfo) {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL);
+
+ }
+
+ if (psMapData) {
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, NULL);
+
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo)
+{
+ if (!psMemInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+}
+
+static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+ return FreeDeviceMem(psMemInfo);
+}
+
+PVRSRV_ERROR PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ void *hDevMemContext,
+ void *hDeviceClassBuffer,
+ PVRSRV_KERNEL_MEM_INFO ** ppsMemInfo,
+ void **phOSMapInfo)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+ IMG_SYS_PHYADDR *psSysPAddr;
+ void *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+ int bPhysContig;
+ BM_CONTEXT *psBMContext;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ void *hDevMemHeap = NULL;
+ u32 ui32ByteSize;
+ u32 ui32Offset;
+ u32 ui32PageSize = HOST_PAGESIZE();
+ BM_HANDLE hBuffer;
+ PVRSRV_MEMBLK *psMemBlock;
+ int bBMError;
+ u32 i;
+
+ if (!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo
+ || !hDevMemContext) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceClassMemoryKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER *) hDeviceClassBuffer;
+
+ eError =
+ psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->
+ hExtDevice,
+ psDeviceClassBuffer->
+ hExtBuffer, &psSysPAddr,
+ &ui32ByteSize, &pvCPUVAddr,
+ phOSMapInfo, &bPhysContig);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceClassMemoryKM: unable to get buffer address"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psBMContext = (BM_CONTEXT *) psDeviceClassBuffer->hDevMemContext;
+ psDevMemoryInfo = &psBMContext->psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+ for (i = 0; i < PVRSRV_MAX_CLIENT_HEAPS; i++) {
+ if (HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) ==
+ psDevMemoryInfo->ui32MappingHeapID) {
+ if (psDeviceMemoryHeap[i].DevMemHeapType ==
+ DEVICE_MEMORY_HEAP_PERCONTEXT) {
+
+ hDevMemHeap =
+ BM_CreateHeap(hDevMemContext,
+ &psDeviceMemoryHeap[i]);
+ } else {
+ hDevMemHeap =
+ psDevMemoryInfo->psDeviceMemoryHeap[i].
+ hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if (hDevMemHeap == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceClassMemoryKM: unable to find mapping heap"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ ui32Offset = ((u32) pvCPUVAddr) & (ui32PageSize - 1);
+ pvPageAlignedCPUVAddr = (void *)((u32) pvCPUVAddr - ui32Offset);
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (void **)&psMemInfo, NULL,
+ "Kernel Memory Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceClassMemoryKM: Failed to alloc memory for block"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ memset(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDevMemHeap,
+ ui32ByteSize,
+ ui32Offset,
+ bPhysContig,
+ psSysPAddr,
+ pvPageAlignedCPUVAddr,
+ &psMemInfo->ui32Flags, &hBuffer);
+
+ if (!bBMError) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, NULL);
+
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+
+ psMemBlock->hBuffer = (void *)hBuffer;
+
+ psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
+
+ psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psMemInfo->ui32AllocSize = ui32ByteSize;
+ psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
+
+ psMemInfo->pvSysBackupBuffer = NULL;
+
+ psMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING, psMemInfo, 0,
+ UnmapDeviceClassMemoryCallBack);
+
+ *ppsMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/staging/ice4100/sgx535/common/handle.c b/drivers/staging/ice4100/sgx535/common/handle.c
new file mode 100755
index 00000000000..f35f0d0be74
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/handle.c
@@ -0,0 +1,1521 @@
+/**********************************************************************
+ *
+ * Copyright (c) 2010 Intel Corporation.
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifdef PVR_SECURE_HANDLES
+#include <stddef.h>
+
+#include "services_headers.h"
+#include "handle.h"
+
+#ifdef DEBUG
+#define HANDLE_BLOCK_SIZE 1
+#else
+#define HANDLE_BLOCK_SIZE 256
+#endif
+
+#define HANDLE_HASH_TAB_INIT_SIZE 32
+
+#define DEFAULT_MAX_INDEX_PLUS_ONE 0xfffffffful
+#define DEFAULT_MAX_HANDLE DEFAULT_MAX_INDEX_PLUS_ONE
+
+#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+
+#define INDEX_TO_HANDLE(psBase, idx) ((void *)((idx) + 1))
+#define HANDLE_TO_INDEX(psBase, hand) ((u32)(hand) - 1)
+
+#define INDEX_TO_HANDLE_PTR(psBase, i) (((psBase)->psHandleArray) + (i))
+#define HANDLE_TO_HANDLE_PTR(psBase, h) (INDEX_TO_HANDLE_PTR(psBase, HANDLE_TO_INDEX(psBase, h)))
+
+#define HANDLE_PTR_TO_INDEX(psBase, psHandle) (u32)((psHandle) - ((psBase)->psHandleArray))
+#define HANDLE_PTR_TO_HANDLE(psBase, psHandle) \
+ INDEX_TO_HANDLE(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle))
+
+#define ROUND_UP_TO_MULTIPLE(a, b) ((((a) + (b) - 1) / (b)) * (b))
+
+#define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
+
+#define SET_FLAG(v, f) ((void)((v) |= (f)))
+#define CLEAR_FLAG(v, f) ((void)((v) &= ~(f)))
+#define TEST_FLAG(v, f) ((int)(((v) & (f)) != 0))
+
+#define TEST_ALLOC_FLAG(psHandle, f) TEST_FLAG((psHandle)->eFlag, f)
+
+#define SET_INTERNAL_FLAG(psHandle, f) SET_FLAG((psHandle)->eInternalFlag, f)
+#define CLEAR_INTERNAL_FLAG(psHandle, f) CLEAR_FLAG((psHandle)->eInternalFlag, f)
+#define TEST_INTERNAL_FLAG(psHandle, f) TEST_FLAG((psHandle)->eInternalFlag, f)
+
+#define BATCHED_HANDLE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_BATCHED_HANDLE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define SET_UNBATCHED_HANDLE(psHandle) CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
+
+#define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
+
+#define HANDLE_STRUCT_IS_FREE(psHandle) ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
+
+#ifdef MIN
+#undef MIN
+#endif
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+
+struct sHandleList {
+ u32 ui32Prev;
+ u32 ui32Next;
+ void *hParent;
+};
+
+enum ePVRSRVInternalHandleFlag {
+ INTERNAL_HANDLE_FLAG_NONE = 0x00,
+ INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
+ INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
+};
+
+struct sHandle {
+
+ PVRSRV_HANDLE_TYPE eType;
+
+ void *pvData;
+
+ u32 ui32NextIndexPlusOne;
+
+ enum ePVRSRVInternalHandleFlag eInternalFlag;
+
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+ u32 ui32Index;
+
+ struct sHandleList sChildren;
+
+ struct sHandleList sSiblings;
+};
+
+struct _PVRSRV_HANDLE_BASE_ {
+
+ void *hBaseBlockAlloc;
+
+ void *hHandBlockAlloc;
+
+ struct sHandle *psHandleArray;
+
+ HASH_TABLE *psHashTab;
+
+ u32 ui32FreeHandCount;
+
+ u32 ui32FirstFreeIndex;
+
+ u32 ui32MaxIndexPlusOne;
+
+ u32 ui32TotalHandCount;
+
+ u32 ui32LastFreeIndexPlusOne;
+
+ u32 ui32HandBatchSize;
+
+ u32 ui32TotalHandCountPreBatch;
+
+ u32 ui32FirstBatchIndexPlusOne;
+
+ u32 ui32BatchHandAllocFailures;
+
+ int bPurgingEnabled;
+};
+
+enum eHandKey {
+ HAND_KEY_DATA = 0,
+ HAND_KEY_TYPE,
+ HAND_KEY_PARENT,
+ HAND_KEY_LEN
+};
+
+PVRSRV_HANDLE_BASE *gpsKernelHandleBase = NULL;
+
+typedef u32 HAND_KEY[HAND_KEY_LEN];
+
+static
+void HandleListInit(u32 ui32Index, struct sHandleList *psList, void *hParent)
+{
+ psList->ui32Next = ui32Index;
+ psList->ui32Prev = ui32Index;
+ psList->hParent = hParent;
+}
+
+static
+void InitParentList(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psHandle)
+{
+ u32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+
+ HandleListInit(ui32Parent, &psHandle->sChildren,
+ INDEX_TO_HANDLE(psBase, ui32Parent));
+}
+
+static
+void InitChildEntry(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psHandle)
+{
+ HandleListInit(HANDLE_PTR_TO_INDEX(psBase, psHandle),
+ &psHandle->sSiblings, NULL);
+}
+
+static
+int HandleListIsEmpty(u32 ui32Index, struct sHandleList *psList)
+{
+ int bIsEmpty;
+
+ bIsEmpty = (int)(psList->ui32Next == ui32Index);
+
+#ifdef DEBUG
+ {
+ int bIsEmpty2;
+
+ bIsEmpty2 = (int)(psList->ui32Prev == ui32Index);
+ PVR_ASSERT(bIsEmpty == bIsEmpty2);
+ }
+#endif
+
+ return bIsEmpty;
+}
+
+#ifdef DEBUG
+static
+int NoChildren(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psHandle)
+{
+ PVR_ASSERT(psHandle->sChildren.hParent ==
+ HANDLE_PTR_TO_HANDLE(psBase, psHandle));
+
+ return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle),
+ &psHandle->sChildren);
+}
+
+static
+int NoParent(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psHandle)
+{
+ if (HandleListIsEmpty
+ (HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings)) {
+ PVR_ASSERT(psHandle->sSiblings.hParent == NULL);
+
+ return 1;
+ } else {
+ PVR_ASSERT(psHandle->sSiblings.hParent != NULL);
+ }
+ return 0;
+}
+#endif
+
+static
+void *ParentHandle(struct sHandle *psHandle)
+{
+ return psHandle->sSiblings.hParent;
+}
+
+#define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
+ ((struct sHandleList *)((char *)(INDEX_TO_HANDLE_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+
+static
+void HandleListInsertBefore(PVRSRV_HANDLE_BASE * psBase, u32 ui32InsIndex,
+ struct sHandleList *psIns, u32 uiParentOffset,
+ u32 ui32EntryIndex, struct sHandleList *psEntry,
+ u32 uiEntryOffset, u32 ui32ParentIndex)
+{
+
+ struct sHandleList *psPrevIns =
+ LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev,
+ ui32ParentIndex, uiParentOffset,
+ uiEntryOffset);
+
+ PVR_ASSERT(psEntry->hParent == NULL);
+ PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+ PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET
+ (psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset,
+ uiParentOffset)->hParent == INDEX_TO_HANDLE(psBase,
+ ui32ParentIndex));
+
+ psEntry->ui32Prev = psIns->ui32Prev;
+ psIns->ui32Prev = ui32EntryIndex;
+ psEntry->ui32Next = ui32InsIndex;
+ psPrevIns->ui32Next = ui32EntryIndex;
+
+ psEntry->hParent = INDEX_TO_HANDLE(psBase, ui32ParentIndex);
+}
+
+static
+void AdoptChild(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psParent,
+ struct sHandle *psChild)
+{
+ u32 ui32Parent = HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent);
+
+ PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psBase, psParent));
+
+ HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren,
+ offsetof(struct sHandle, sChildren),
+ HANDLE_PTR_TO_INDEX(psBase, psChild),
+ &psChild->sSiblings, offsetof(struct sHandle,
+ sSiblings),
+ ui32Parent);
+
+}
+
+static
+void HandleListRemove(PVRSRV_HANDLE_BASE * psBase, u32 ui32EntryIndex,
+ struct sHandleList *psEntry, u32 uiEntryOffset,
+ u32 uiParentOffset)
+{
+ if (!HandleListIsEmpty(ui32EntryIndex, psEntry)) {
+
+ struct sHandleList *psPrev =
+ LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev,
+ HANDLE_TO_INDEX(psBase,
+ psEntry->
+ hParent),
+ uiParentOffset,
+ uiEntryOffset);
+ struct sHandleList *psNext =
+ LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next,
+ HANDLE_TO_INDEX(psBase,
+ psEntry->
+ hParent),
+ uiParentOffset,
+ uiEntryOffset);
+
+ PVR_ASSERT(psEntry->hParent != NULL);
+
+ psPrev->ui32Next = psEntry->ui32Next;
+ psNext->ui32Prev = psEntry->ui32Prev;
+
+ HandleListInit(ui32EntryIndex, psEntry, NULL);
+ }
+}
+
+static
+void UnlinkFromParent(PVRSRV_HANDLE_BASE * psBase, struct sHandle *psHandle)
+{
+ HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle),
+ &psHandle->sSiblings, offsetof(struct sHandle,
+ sSiblings),
+ offsetof(struct sHandle, sChildren));
+}
+
+static
+PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE * psBase,
+ struct sHandleList *psHead, u32 uiParentOffset,
+ u32 uiEntryOffset,
+ PVRSRV_ERROR(*pfnIterFunc) (PVRSRV_HANDLE_BASE *,
+ struct sHandle *))
+{
+ u32 ui32Index;
+ u32 ui32Parent = HANDLE_TO_INDEX(psBase, psHead->hParent);
+
+ PVR_ASSERT(psHead->hParent != NULL);
+
+ for (ui32Index = psHead->ui32Next; ui32Index != ui32Parent;) {
+ struct sHandle *psHandle =
+ INDEX_TO_HANDLE_PTR(psBase, ui32Index);
+
+ struct sHandleList *psEntry =
+ LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index,
+ ui32Parent, uiParentOffset,
+ uiEntryOffset);
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psEntry->hParent == psHead->hParent);
+
+ ui32Index = psEntry->ui32Next;
+
+ eError = (*pfnIterFunc) (psBase, psHandle);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE * psBase,
+ struct sHandle *psParent,
+ PVRSRV_ERROR(*pfnIterFunc) (PVRSRV_HANDLE_BASE
+ *,
+ struct sHandle *))
+{
+ return HandleListIterate(psBase, &psParent->sChildren,
+ offsetof(struct sHandle, sChildren),
+ offsetof(struct sHandle, sSiblings),
+ pfnIterFunc);
+}
+
+static
+PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE * psBase,
+ struct sHandle **ppsHandle, void *hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ u32 ui32Index = HANDLE_TO_INDEX(psBase, hHandle);
+ struct sHandle *psHandle;
+
+ if (!INDEX_IS_VALID(psBase, ui32Index)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "GetHandleStructure: Handle index out of range (%u >= %u)",
+ ui32Index, psBase->ui32TotalHandCount));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32Index);
+ if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "GetHandleStructure: Handle not allocated (index: %u)",
+ ui32Index));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "GetHandleStructure: Handle type mismatch (%d != %d)",
+ eType, psHandle->eType));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *ppsHandle = psHandle;
+
+ return PVRSRV_OK;
+}
+
+static
+void *ParentIfPrivate(struct sHandle *psHandle)
+{
+ return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ ParentHandle(psHandle) : NULL;
+}
+
+static
+void InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE * psBase, void *pvData,
+ PVRSRV_HANDLE_TYPE eType, void *hParent)
+{
+ aKey[HAND_KEY_DATA] = (u32) pvData;
+ aKey[HAND_KEY_TYPE] = (u32) eType;
+ aKey[HAND_KEY_PARENT] = (u32) hParent;
+}
+
+static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE * psBase)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psBase->psHandleArray != NULL) {
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psBase->ui32TotalHandCount *
+ sizeof(struct sHandle),
+ psBase->psHandleArray,
+ psBase->hHandBlockAlloc);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeHandleArray: Error freeing memory (%d)",
+ eError));
+ } else {
+ psBase->psHandleArray = NULL;
+ }
+ }
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE * psBase,
+ struct sHandle *psHandle)
+{
+ HAND_KEY aKey;
+ u32 ui32Index = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+ PVRSRV_ERROR eError;
+
+ InitKey(aKey, psBase, psHandle->pvData, psHandle->eType,
+ ParentIfPrivate(psHandle));
+
+ if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)
+ && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
+ void *hHandle;
+ hHandle = (void *)HASH_Remove_Extended(psBase->psHashTab, aKey);
+
+ PVR_ASSERT(hHandle != NULL);
+ PVR_ASSERT(hHandle == INDEX_TO_HANDLE(psBase, ui32Index));
+ }
+
+ UnlinkFromParent(psBase, psHandle);
+
+ eError = IterateOverChildren(psBase, psHandle, FreeHandle);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeHandle: Error whilst freeing subhandles (%d)",
+ eError));
+ return eError;
+ }
+
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+
+ if (BATCHED_HANDLE(psHandle)
+ && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
+
+ SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
+
+ return PVRSRV_OK;
+ }
+
+ if (!psBase->bPurgingEnabled) {
+ if (psBase->ui32FreeHandCount == 0) {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+ psBase->ui32FirstFreeIndex = ui32Index;
+ } else {
+
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_PTR
+ (psBase,
+ psBase->ui32LastFreeIndexPlusOne -
+ 1)->ui32NextIndexPlusOne == 0);
+ INDEX_TO_HANDLE_PTR(psBase,
+ psBase->ui32LastFreeIndexPlusOne -
+ 1)->ui32NextIndexPlusOne =
+ ui32Index + 1;
+ }
+
+ PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
+
+ psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
+ }
+
+ psBase->ui32FreeHandCount++;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE * psBase)
+{
+ u32 i;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount) {
+ return eError;
+ }
+
+ for (i = 0; i < psBase->ui32TotalHandCount; i++) {
+ struct sHandle *psHandle;
+
+ psHandle = INDEX_TO_HANDLE_PTR(psBase, i);
+
+ if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE) {
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeAllHandles: FreeHandle failed (%d)",
+ eError));
+ break;
+ }
+
+ if (psBase->ui32FreeHandCount ==
+ psBase->ui32TotalHandCount) {
+ break;
+ }
+ }
+ }
+
+ return eError;
+}
+
+static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE * psBase)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase)) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "FreeHandleBase: Uncommitted/Unreleased handle batch"));
+ PVRSRVReleaseHandleBatch(psBase);
+ }
+
+ eError = FreeAllHandles(psBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeHandleBase: Couldn't free handles (%d)", eError));
+ return eError;
+ }
+
+ eError = FreeHandleArray(psBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeHandleBase: Couldn't free handle array (%d)",
+ eError));
+ return eError;
+ }
+
+ if (psBase->psHashTab != NULL) {
+
+ HASH_Delete(psBase->psHashTab);
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase), psBase, psBase->hBaseBlockAlloc);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeHandleBase: Couldn't free handle base (%d)",
+ eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+static
+void *FindHandle(PVRSRV_HANDLE_BASE * psBase, void *pvData,
+ PVRSRV_HANDLE_TYPE eType, void *hParent)
+{
+ HAND_KEY aKey;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+ return (void *)HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+static PVRSRV_ERROR ReallocMem(void **ppvMem, void **phBlockAlloc,
+ u32 ui32NewSize, u32 ui32OldSize)
+{
+ void *pvOldMem = *ppvMem;
+ void *hOldBlockAlloc = *phBlockAlloc;
+ u32 ui32CopySize = MIN(ui32NewSize, ui32OldSize);
+ void *pvNewMem = NULL;
+ void *hNewBlockAlloc = NULL;
+ PVRSRV_ERROR eError;
+
+ if (ui32NewSize == ui32OldSize) {
+ return (PVRSRV_OK);
+ }
+
+ if (ui32NewSize != 0) {
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NewSize,
+ &pvNewMem, &hNewBlockAlloc, "Memory Area");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "ReallocMem: Couldn't allocate new memory area (%d)",
+ eError));
+ return eError;
+ }
+ }
+
+ if (ui32CopySize != 0) {
+
+ memcpy(pvNewMem, pvOldMem, ui32CopySize);
+ }
+
+ if (ui32OldSize != 0) {
+
+ eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32OldSize, pvOldMem, hOldBlockAlloc);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "ReallocMem: Couldn't free old memory area (%d)",
+ eError));
+ }
+ }
+
+ *ppvMem = pvNewMem;
+ *phBlockAlloc = hNewBlockAlloc;
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE * psBase, u32 ui32NewCount,
+ u32 ui32OldCount)
+{
+ return ReallocMem((void **)&psBase->psHandleArray,
+ &psBase->hHandBlockAlloc,
+ ui32NewCount * sizeof(struct sHandle),
+ ui32OldCount * sizeof(struct sHandle));
+}
+
+static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE * psBase,
+ u32 ui32Delta)
+{
+ PVRSRV_ERROR eError;
+ struct sHandle *psHandle;
+ u32 ui32DeltaAdjusted =
+ ROUND_UP_TO_MULTIPLE(ui32Delta, HANDLE_BLOCK_SIZE);
+ u32 ui32NewTotalHandCount =
+ psBase->ui32TotalHandCount + ui32DeltaAdjusted;
+ ;
+
+ PVR_ASSERT(ui32Delta != 0);
+
+ if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne
+ || ui32NewTotalHandCount <= psBase->ui32TotalHandCount) {
+ ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
+
+ ui32DeltaAdjusted =
+ ui32NewTotalHandCount - psBase->ui32TotalHandCount;
+
+ if (ui32DeltaAdjusted < ui32Delta) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "IncreaseHandleArraySize: Maximum handle limit reached (%d)",
+ psBase->ui32MaxIndexPlusOne));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
+
+ eError =
+ ReallocHandleArray(psBase, ui32NewTotalHandCount,
+ psBase->ui32TotalHandCount);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "IncreaseHandleArraySize: ReallocHandleArray failed (%d)",
+ eError));
+ return eError;
+ }
+
+ for (psHandle = psBase->psHandleArray + psBase->ui32TotalHandCount;
+ psHandle < psBase->psHandleArray + ui32NewTotalHandCount;
+ psHandle++) {
+ psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
+ psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psHandle->ui32NextIndexPlusOne = 0;
+ }
+
+ psBase->ui32FreeHandCount += ui32DeltaAdjusted;
+
+ if (psBase->ui32FirstFreeIndex == 0) {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
+
+ psBase->ui32FirstFreeIndex = psBase->ui32TotalHandCount;
+ } else {
+ if (!psBase->bPurgingEnabled) {
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
+ PVR_ASSERT(INDEX_TO_HANDLE_PTR
+ (psBase,
+ psBase->ui32LastFreeIndexPlusOne -
+ 1)->ui32NextIndexPlusOne == 0);
+
+ INDEX_TO_HANDLE_PTR(psBase,
+ psBase->ui32LastFreeIndexPlusOne -
+ 1)->ui32NextIndexPlusOne =
+ psBase->ui32TotalHandCount + 1;
+ }
+ }
+
+ if (!psBase->bPurgingEnabled) {
+ psBase->ui32LastFreeIndexPlusOne = ui32NewTotalHandCount;
+ }
+
+ psBase->ui32TotalHandCount = ui32NewTotalHandCount;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE * psBase, u32 ui32Free)
+{
+ PVRSRV_ERROR eError;
+
+ if (ui32Free > psBase->ui32FreeHandCount) {
+ u32 ui32FreeHandDelta = ui32Free - psBase->ui32FreeHandCount;
+ eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "EnsureFreeHandles: Couldn't allocate %u handles to ensure %u free handles (IncreaseHandleArraySize failed with error %d)",
+ ui32FreeHandDelta, ui32Free, eError));
+
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE * psBase, void **phHandle,
+ void *pvData, PVRSRV_HANDLE_TYPE eType,
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag, void *hParent)
+{
+ u32 ui32NewIndex;
+ struct sHandle *psNewHandle = NULL;
+ void *hHandle;
+ HAND_KEY aKey;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ PVR_ASSERT(psBase->psHashTab != NULL);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
+
+ PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == NULL);
+ }
+
+ if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase)) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "AllocHandle: Handle batch size (%u) was too small, allocating additional space",
+ psBase->ui32HandBatchSize));
+ }
+
+ eError = EnsureFreeHandles(psBase, 1);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocHandle: EnsureFreeHandles failed (%d)", eError));
+ return eError;
+ }
+ PVR_ASSERT(psBase->ui32FreeHandCount != 0)
+
+ if (!psBase->bPurgingEnabled) {
+
+ ui32NewIndex = psBase->ui32FirstFreeIndex;
+
+ psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
+ } else {
+
+ for (ui32NewIndex = psBase->ui32FirstFreeIndex;
+ ui32NewIndex < psBase->ui32TotalHandCount;
+ ui32NewIndex++) {
+ psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
+ if (HANDLE_STRUCT_IS_FREE(psNewHandle)) {
+ break;
+ }
+
+ }
+ psBase->ui32FirstFreeIndex = 0;
+ PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
+ }
+ PVR_ASSERT(psNewHandle != NULL);
+#ifdef INTEL_D3_P_CHANGES
+ if (NULL == psNewHandle) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocHandle: New handle pointer is NULL"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+#endif
+
+ hHandle = INDEX_TO_HANDLE(psBase, ui32NewIndex);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+ if (!HASH_Insert_Extended
+ (psBase->psHashTab, aKey, (u32) hHandle)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocHandle: Couldn't add handle to hash table"));
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ psBase->ui32FreeHandCount--;
+
+ if (!psBase->bPurgingEnabled) {
+
+ if (psBase->ui32FreeHandCount == 0) {
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne ==
+ (ui32NewIndex + 1));
+
+ psBase->ui32LastFreeIndexPlusOne = 0;
+ psBase->ui32FirstFreeIndex = 0;
+ } else {
+
+ psBase->ui32FirstFreeIndex =
+ (psNewHandle->ui32NextIndexPlusOne ==
+ 0) ? ui32NewIndex +
+ 1 : psNewHandle->ui32NextIndexPlusOne - 1;
+ }
+ }
+
+ psNewHandle->eType = eType;
+ psNewHandle->pvData = pvData;
+ psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
+ psNewHandle->eFlag = eFlag;
+ psNewHandle->ui32Index = ui32NewIndex;
+
+ InitParentList(psBase, psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoChildren(psBase, psNewHandle));
+#endif
+
+ InitChildEntry(psBase, psNewHandle);
+#if defined(DEBUG)
+ PVR_ASSERT(NoParent(psBase, psNewHandle));
+#endif
+
+ if (HANDLES_BATCHED(psBase)) {
+
+ psNewHandle->ui32NextIndexPlusOne =
+ psBase->ui32FirstBatchIndexPlusOne;
+
+ psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
+
+ SET_BATCHED_HANDLE(psNewHandle);
+ } else {
+ psNewHandle->ui32NextIndexPlusOne = 0;
+ }
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE * psBase, void **phHandle,
+ void *pvData, PVRSRV_HANDLE_TYPE eType,
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ void *hHandle;
+ PVRSRV_ERROR eError;
+
+ *phHandle = NULL;
+
+ if (HANDLES_BATCHED(psBase)) {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
+
+ hHandle = FindHandle(psBase, pvData, eType, NULL);
+ if (hHandle != NULL) {
+ struct sHandle *psHandle;
+
+ eError =
+ GetHandleStructure(psBase, &psHandle, hHandle,
+ eType);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocHandle: Lookup of existing handle failed"));
+ return eError;
+ }
+
+ if (TEST_FLAG
+ (psHandle->eFlag & eFlag,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED)) {
+ *phHandle = hHandle;
+ eError = PVRSRV_OK;
+ goto exit_ok;
+ }
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, NULL);
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK)) {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE * psBase, void **phHandle,
+ void *pvData, PVRSRV_HANDLE_TYPE eType,
+ PVRSRV_HANDLE_ALLOC_FLAG eFlag, void *hParent)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+ void *hParentKey;
+ void *hHandle;
+
+ *phHandle = NULL;
+
+ if (HANDLES_BATCHED(psBase)) {
+
+ psBase->ui32BatchHandAllocFailures++;
+ }
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ hParent : NULL;
+
+ eError =
+ GetHandleStructure(psBase, &psPHand, hParent,
+ PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
+
+ hHandle = FindHandle(psBase, pvData, eType, hParentKey);
+ if (hHandle != NULL) {
+ struct sHandle *psCHandle;
+ PVRSRV_ERROR eErr;
+
+ eErr =
+ GetHandleStructure(psBase, &psCHandle, hHandle,
+ eType);
+ if (eErr != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocSubHandle: Lookup of existing handle failed"));
+ return eErr;
+ }
+
+ PVR_ASSERT(hParentKey != NULL
+ &&
+ ParentHandle(HANDLE_TO_HANDLE_PTR
+ (psBase, hHandle)) == hParent);
+
+ if (TEST_FLAG
+ (psCHandle->eFlag & eFlag,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED)
+ &&
+ ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle))
+ == hParent) {
+ *phHandle = hHandle;
+ goto exit_ok;
+ }
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ eError =
+ AllocHandle(psBase, &hHandle, pvData, eType, eFlag, hParentKey);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ psPHand = HANDLE_TO_HANDLE_PTR(psBase, hParent);
+
+ psCHand = HANDLE_TO_HANDLE_PTR(psBase, hHandle);
+
+ AdoptChild(psBase, psPHand, psCHand);
+
+ *phHandle = hHandle;
+
+exit_ok:
+ if (HANDLES_BATCHED(psBase)) {
+ psBase->ui32BatchHandAllocFailures--;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE * psBase, void **phHandle,
+ void *pvData, PVRSRV_HANDLE_TYPE eType)
+{
+ void *hHandle;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ hHandle = (void *)FindHandle(psBase, pvData, eType, NULL);
+ if (hHandle == NULL) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phHandle = hHandle;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE * psBase,
+ void **ppvData,
+ PVRSRV_HANDLE_TYPE * peType,
+ void *hHandle)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ eError =
+ GetHandleStructure(psBase, &psHandle, hHandle,
+ PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupHandleAnyType: Error looking up handle (%d)",
+ eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+ *peType = psHandle->eType;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE * psBase, void **ppvData,
+ void *hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupHandle: Error looking up handle (%d)",
+ eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE * psBase, void **ppvData,
+ void *hHandle, PVRSRV_HANDLE_TYPE eType,
+ void *hAncestor)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupSubHandle: Error looking up subhandle (%d)",
+ eError));
+ return eError;
+ }
+
+ for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor;) {
+ eError =
+ GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand),
+ PVRSRV_HANDLE_TYPE_NONE);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupSubHandle: Subhandle doesn't belong to given ancestor"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ *ppvData = psCHand->pvData;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE * psBase, void **phParent,
+ void *hHandle, PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetParentHandle: Error looking up subhandle (%d)",
+ eError));
+ return eError;
+ }
+
+ *phParent = ParentHandle(psHandle);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE * psBase,
+ void **ppvData, void *hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVLookupAndReleaseHandle: Error looking up handle (%d)",
+ eError));
+ return eError;
+ }
+
+ *ppvData = psHandle->pvData;
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE * psBase, void *hHandle,
+ PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVReleaseHandle: Error looking up handle (%d)",
+ eError));
+ return eError;
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE * psBase,
+ u32 ui32BatchSize)
+{
+ PVRSRV_ERROR eError;
+
+ if (HANDLES_BATCHED(psBase)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVNewHandleBatch: There is a handle batch already in use (size %u)",
+ psBase->ui32HandBatchSize));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (ui32BatchSize == 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVNewHandleBatch: Invalid batch size (%u)",
+ ui32BatchSize));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = EnsureFreeHandles(psBase, ui32BatchSize);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVNewHandleBatch: EnsureFreeHandles failed (error %d)",
+ eError));
+ return eError;
+ }
+
+ psBase->ui32HandBatchSize = ui32BatchSize;
+
+ psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
+
+ PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
+
+ PVR_ASSERT(HANDLES_BATCHED(psBase));
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *
+ psBase, int bCommit)
+{
+
+ u32 ui32IndexPlusOne;
+ int bCommitBatch = bCommit;
+
+ if (!HANDLES_BATCHED(psBase)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleBatchCommitOrRelease: There is no handle batch"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ }
+
+ if (psBase->ui32BatchHandAllocFailures != 0) {
+ if (bCommit) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleBatchCommitOrRelease: Attempting to commit batch with handle allocation failures."));
+ }
+ bCommitBatch = 0;
+ }
+
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
+
+ ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
+ while (ui32IndexPlusOne != 0) {
+ struct sHandle *psHandle =
+ INDEX_TO_HANDLE_PTR(psBase, ui32IndexPlusOne - 1);
+ u32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
+ PVR_ASSERT(BATCHED_HANDLE(psHandle));
+
+ psHandle->ui32NextIndexPlusOne = 0;
+
+ if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
+ PVRSRV_ERROR eError;
+
+ if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ eError = FreeHandle(psBase, psHandle);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)",
+ eError));
+ }
+ PVR_ASSERT(eError == PVRSRV_OK);
+ } else {
+ SET_UNBATCHED_HANDLE(psHandle);
+ }
+
+ ui32IndexPlusOne = ui32NextIndexPlusOne;
+ }
+
+#ifdef DEBUG
+ if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount) {
+ u32 ui32Delta =
+ psBase->ui32TotalHandCount -
+ psBase->ui32TotalHandCountPreBatch;
+
+ PVR_ASSERT(psBase->ui32TotalHandCount >
+ psBase->ui32TotalHandCountPreBatch);
+
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVHandleBatchCommitOrRelease: The batch size was too small. Batch size was %u, but needs to be %u",
+ psBase->ui32HandBatchSize,
+ psBase->ui32HandBatchSize + ui32Delta));
+
+ }
+#endif
+
+ psBase->ui32HandBatchSize = 0;
+ psBase->ui32FirstBatchIndexPlusOne = 0;
+ psBase->ui32TotalHandCountPreBatch = 0;
+ psBase->ui32BatchHandAllocFailures = 0;
+
+ if (psBase->ui32BatchHandAllocFailures != 0 && bCommit) {
+ PVR_ASSERT(!bCommitBatch);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE * psBase)
+{
+ return PVRSRVHandleBatchCommitOrRelease(psBase, 1);
+}
+
+void PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE * psBase)
+{
+ (void)PVRSRVHandleBatchCommitOrRelease(psBase, 0);
+}
+
+PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE * psBase, u32 ui32MaxHandle)
+{
+ if (HANDLES_BATCHED(psBase)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetMaxHandle: Limit cannot be set whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32MaxHandle == 0 || ui32MaxHandle >= DEFAULT_MAX_HANDLE) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive",
+ 0, DEFAULT_MAX_HANDLE));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (psBase->ui32TotalHandCount != 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetMaxHandle: Limit cannot be set becuase handles have already been allocated"));
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBase->ui32MaxIndexPlusOne = ui32MaxHandle;
+
+ return PVRSRV_OK;
+}
+
+u32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE * psBase)
+{
+ return psBase->ui32MaxIndexPlusOne;
+}
+
+PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE * psBase)
+{
+ if (psBase->bPurgingEnabled) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVEnableHandlePurging: Purging already enabled"));
+ return PVRSRV_OK;
+ }
+
+ if (psBase->ui32TotalHandCount != 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVEnableHandlePurging: Handles have already been allocated"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psBase->bPurgingEnabled = 1;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE * psBase)
+{
+ u32 ui32Handle;
+ u32 ui32NewHandCount;
+
+ if (!psBase->bPurgingEnabled) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPurgeHandles: Purging not enabled for this handle base"));
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+ }
+
+ if (HANDLES_BATCHED(psBase)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPurgeHandles: Purging not allowed whilst in batch mode"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ for (ui32Handle = psBase->ui32TotalHandCount; ui32Handle != 0;
+ ui32Handle--) {
+ struct sHandle *psHandle =
+ HANDLE_TO_HANDLE_PTR(psBase, ui32Handle);
+ if (!HANDLE_STRUCT_IS_FREE(psHandle)) {
+ break;
+ }
+ }
+
+ ui32NewHandCount = ROUND_UP_TO_MULTIPLE(ui32Handle, HANDLE_BLOCK_SIZE);
+
+ if (ui32NewHandCount >= ui32Handle
+ && ui32NewHandCount <= (psBase->ui32TotalHandCount / 2)) {
+ u32 ui32Delta = psBase->ui32TotalHandCount - ui32NewHandCount;
+ PVRSRV_ERROR eError;
+
+ eError =
+ ReallocHandleArray(psBase, ui32NewHandCount,
+ psBase->ui32TotalHandCount);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ psBase->ui32TotalHandCount = ui32NewHandCount;
+ psBase->ui32FreeHandCount -= ui32Delta;
+ psBase->ui32FirstFreeIndex = 0;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE ** ppsBase)
+{
+ PVRSRV_HANDLE_BASE *psBase;
+ void *hBlockAlloc;
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase),
+ (void **)&psBase, &hBlockAlloc, "Handle Base");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocHandleBase: Couldn't allocate handle base (%d)",
+ eError));
+ return eError;
+ }
+ memset(psBase, 0, sizeof(*psBase));
+
+ psBase->psHashTab =
+ HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY),
+ HASH_Func_Default, HASH_Key_Comp_Default);
+ if (psBase->psHashTab == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocHandleBase: Couldn't create data pointer hash table\n"));
+ goto failure;
+ }
+
+ psBase->hBaseBlockAlloc = hBlockAlloc;
+
+ psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
+
+ *ppsBase = psBase;
+
+ return PVRSRV_OK;
+failure:
+ (void)PVRSRVFreeHandleBase(psBase);
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE * psBase)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(psBase != gpsKernelHandleBase);
+
+ eError = FreeHandleBase(psBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)",
+ eError));
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleInit(void)
+{
+ PVRSRV_ERROR eError;
+
+ PVR_ASSERT(gpsKernelHandleBase == NULL);
+
+ eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)",
+ eError));
+ goto error;
+ }
+
+ eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleInit: PVRSRVEnableHandlePurging failed (%d)",
+ eError));
+ goto error;
+ }
+
+ return PVRSRV_OK;
+error:
+ (void)PVRSRVHandleDeInit();
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVHandleDeInit(void)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (gpsKernelHandleBase != NULL) {
+ eError = FreeHandleBase(gpsKernelHandleBase);
+ if (eError == PVRSRV_OK) {
+ gpsKernelHandleBase = NULL;
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVHandleDeInit: FreeHandleBase failed (%d)",
+ eError));
+ }
+ }
+
+ return eError;
+}
+#else
+#endif
diff --git a/drivers/staging/ice4100/sgx535/common/hash.c b/drivers/staging/ice4100/sgx535/common/hash.c
new file mode 100755
index 00000000000..3485434c95a
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/hash.c
@@ -0,0 +1,434 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "pvr_debug.h"
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "hash.h"
+#include "osfunc.h"
+
+#define PRIVATE_MAX(a,b) ((a)>(b)?(a):(b))
+
+#define KEY_TO_INDEX(pHash, key, uSize) \
+ ((pHash)->pfnHashFunc((pHash)->uKeySize, key, uSize) % uSize)
+
+#define KEY_COMPARE(pHash, pKey1, pKey2) \
+ ((pHash)->pfnKeyComp((pHash)->uKeySize, pKey1, pKey2))
+
+struct _BUCKET_ {
+
+ struct _BUCKET_ *pNext;
+
+ u32 v;
+
+ u32 k[];
+};
+typedef struct _BUCKET_ BUCKET;
+
+struct _HASH_TABLE_ {
+
+ BUCKET **ppBucketTable;
+
+ u32 uSize;
+
+ u32 uCount;
+
+ u32 uMinimumSize;
+
+ u32 uKeySize;
+
+ HASH_FUNC *pfnHashFunc;
+
+ HASH_KEY_COMP *pfnKeyComp;
+};
+
+u32 HASH_Func_Default(u32 uKeySize, void *pKey, u32 uHashTabLen)
+{
+ u32 *p = (u32 *) pKey;
+ u32 uKeyLen = uKeySize / sizeof(u32);
+ u32 ui;
+ u32 uHashKey = 0;
+
+ PVR_ASSERT((uKeySize % sizeof(u32)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++) {
+ u32 uHashPart = (u32) * p++;
+
+ uHashPart += (uHashPart << 12);
+ uHashPart ^= (uHashPart >> 22);
+ uHashPart += (uHashPart << 4);
+ uHashPart ^= (uHashPart >> 9);
+ uHashPart += (uHashPart << 10);
+ uHashPart ^= (uHashPart >> 2);
+ uHashPart += (uHashPart << 7);
+ uHashPart ^= (uHashPart >> 12);
+
+ uHashKey += uHashPart;
+ }
+
+ return uHashKey;
+}
+
+int HASH_Key_Comp_Default(u32 uKeySize, void *pKey1, void *pKey2)
+{
+ u32 *p1 = (u32 *) pKey1;
+ u32 *p2 = (u32 *) pKey2;
+ u32 uKeyLen = uKeySize / sizeof(u32);
+ u32 ui;
+
+ PVR_ASSERT((uKeySize % sizeof(u32)) == 0);
+
+ for (ui = 0; ui < uKeyLen; ui++) {
+ if (*p1++ != *p2++)
+ return 0;
+ }
+
+ return 1;
+}
+
+static PVRSRV_ERROR
+_ChainInsert(HASH_TABLE * pHash, BUCKET * pBucket, BUCKET ** ppBucketTable,
+ u32 uSize)
+{
+ u32 uIndex;
+
+ PVR_ASSERT(pBucket != NULL);
+ PVR_ASSERT(ppBucketTable != NULL);
+ PVR_ASSERT(uSize != 0);
+
+ if ((pBucket == NULL) || (ppBucketTable == NULL) || (uSize == 0)) {
+ PVR_DPF((PVR_DBG_ERROR, "_ChainInsert: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+ pBucket->pNext = ppBucketTable[uIndex];
+ ppBucketTable[uIndex] = pBucket;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+_Rehash(HASH_TABLE * pHash,
+ BUCKET ** ppOldTable, u32 uOldSize, BUCKET ** ppNewTable, u32 uNewSize)
+{
+ u32 uIndex;
+ for (uIndex = 0; uIndex < uOldSize; uIndex++) {
+ BUCKET *pBucket;
+ pBucket = ppOldTable[uIndex];
+ while (pBucket != NULL) {
+ BUCKET *pNextBucket = pBucket->pNext;
+ if (_ChainInsert(pHash, pBucket, ppNewTable, uNewSize)
+ != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_Rehash: call to _ChainInsert failed"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+ pBucket = pNextBucket;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static int _Resize(HASH_TABLE * pHash, u32 uNewSize)
+{
+ if (uNewSize != pHash->uSize) {
+ BUCKET **ppNewTable;
+ u32 uIndex;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Resize: oldsize=0x%x newsize=0x%x count=0x%x",
+ pHash->uSize, uNewSize, pHash->uCount));
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET *) * uNewSize,
+ (void **)&ppNewTable, NULL, "Hash Table Buckets");
+ if (ppNewTable == NULL)
+ return 0;
+
+ for (uIndex = 0; uIndex < uNewSize; uIndex++)
+ ppNewTable[uIndex] = NULL;
+
+ if (_Rehash
+ (pHash, pHash->ppBucketTable, pHash->uSize, ppNewTable,
+ uNewSize) != PVRSRV_OK) {
+ return 0;
+ }
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET *) * pHash->uSize, pHash->ppBucketTable,
+ NULL);
+
+ pHash->ppBucketTable = ppNewTable;
+ pHash->uSize = uNewSize;
+ }
+ return 1;
+}
+
+HASH_TABLE *HASH_Create_Extended(u32 uInitialLen, u32 uKeySize,
+ HASH_FUNC * pfnHashFunc,
+ HASH_KEY_COMP * pfnKeyComp)
+{
+ HASH_TABLE *pHash;
+ u32 uIndex;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x",
+ uInitialLen));
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(HASH_TABLE),
+ (void **)&pHash, NULL, "Hash Table") != PVRSRV_OK) {
+ return NULL;
+ }
+
+ pHash->uCount = 0;
+ pHash->uSize = uInitialLen;
+ pHash->uMinimumSize = uInitialLen;
+ pHash->uKeySize = uKeySize;
+ pHash->pfnHashFunc = pfnHashFunc;
+ pHash->pfnKeyComp = pfnKeyComp;
+
+ OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET *) * pHash->uSize,
+ (void **)&pHash->ppBucketTable, NULL, "Hash Table Buckets");
+
+ if (pHash->ppBucketTable == NULL) {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash,
+ NULL);
+
+ return NULL;
+ }
+
+ for (uIndex = 0; uIndex < pHash->uSize; uIndex++)
+ pHash->ppBucketTable[uIndex] = NULL;
+ return pHash;
+}
+
+HASH_TABLE *HASH_Create(u32 uInitialLen)
+{
+ return HASH_Create_Extended(uInitialLen, sizeof(u32),
+ &HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+void HASH_Delete(HASH_TABLE * pHash)
+{
+ if (pHash != NULL) {
+ PVR_DPF((PVR_DBG_MESSAGE, "HASH_Delete"));
+
+ PVR_ASSERT(pHash->uCount == 0);
+ if (pHash->uCount != 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "HASH_Delete: leak detected in hash table!"));
+ PVR_DPF((PVR_DBG_ERROR,
+ "Likely Cause: client drivers not freeing alocations before destroying devmemcontext"));
+ }
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET *) * pHash->uSize, pHash->ppBucketTable,
+ NULL);
+ pHash->ppBucketTable = NULL;
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash,
+ NULL);
+
+ }
+}
+
+int HASH_Insert_Extended(HASH_TABLE * pHash, void *pKey, u32 v)
+{
+ BUCKET *pBucket;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Insert_Extended: Hash=%08X, pKey=%08X, v=0x%x", pHash,
+ pKey, v));
+
+ PVR_ASSERT(pHash != NULL);
+
+ if (pHash == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "HASH_Insert_Extended: invalid parameter"));
+ return 0;
+ }
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET) + pHash->uKeySize,
+ (void **)&pBucket, NULL,
+ "Hash Table entry") != PVRSRV_OK) {
+ return 0;
+ }
+
+ pBucket->v = v;
+
+ memcpy(pBucket->k, pKey, pHash->uKeySize);
+ if (_ChainInsert(pHash, pBucket, pHash->ppBucketTable, pHash->uSize) !=
+ PVRSRV_OK) {
+ return 0;
+ }
+
+ pHash->uCount++;
+
+ if (pHash->uCount << 1 > pHash->uSize) {
+
+ _Resize(pHash, pHash->uSize << 1);
+ }
+
+ return 1;
+}
+
+int HASH_Insert(HASH_TABLE * pHash, u32 k, u32 v)
+{
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Insert: Hash=%08X, k=0x%x, v=0x%x", pHash, k, v));
+
+ return HASH_Insert_Extended(pHash, &k, v);
+}
+
+u32 HASH_Remove_Extended(HASH_TABLE * pHash, void *pKey)
+{
+ BUCKET **ppBucket;
+ u32 uIndex;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "HASH_Remove_Extended: Hash=%08X, pKey=%08X",
+ pHash, pKey));
+
+ PVR_ASSERT(pHash != NULL);
+
+ if (pHash == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "HASH_Remove_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != NULL;
+ ppBucket = &((*ppBucket)->pNext)) {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey)) {
+ BUCKET *pBucket = *ppBucket;
+ u32 v = pBucket->v;
+ (*ppBucket) = pBucket->pNext;
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(BUCKET) + pHash->uKeySize, pBucket,
+ NULL);
+
+ pHash->uCount--;
+
+ if (pHash->uSize > (pHash->uCount << 2) &&
+ pHash->uSize > pHash->uMinimumSize) {
+
+ _Resize(pHash,
+ PRIVATE_MAX(pHash->uSize >> 1,
+ pHash->uMinimumSize));
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=%08X, pKey=%08X = 0x%x",
+ pHash, pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Remove_Extended: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash,
+ pKey));
+ return 0;
+}
+
+u32 HASH_Remove(HASH_TABLE * pHash, u32 k)
+{
+ PVR_DPF((PVR_DBG_MESSAGE, "HASH_Remove: Hash=%08X, k=0x%x", pHash, k));
+
+ return HASH_Remove_Extended(pHash, &k);
+}
+
+u32 HASH_Retrieve_Extended(HASH_TABLE * pHash, void *pKey)
+{
+ BUCKET **ppBucket;
+ u32 uIndex;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Retrieve_Extended: Hash=%08X, pKey=%08X", pHash, pKey));
+
+ PVR_ASSERT(pHash != NULL);
+
+ if (pHash == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "HASH_Retrieve_Extended: Null hash table"));
+ return 0;
+ }
+
+ uIndex = KEY_TO_INDEX(pHash, pKey, pHash->uSize);
+
+ for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != NULL;
+ ppBucket = &((*ppBucket)->pNext)) {
+
+ if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey)) {
+ BUCKET *pBucket = *ppBucket;
+ u32 v = pBucket->v;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=%08X, pKey=%08X = 0x%x",
+ pHash, pKey, v));
+ return v;
+ }
+ }
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "HASH_Retrieve: Hash=%08X, pKey=%08X = 0x0 !!!!", pHash,
+ pKey));
+ return 0;
+}
+
+u32 HASH_Retrieve(HASH_TABLE * pHash, u32 k)
+{
+ PVR_DPF((PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=%08X, k=0x%x", pHash,
+ k));
+ return HASH_Retrieve_Extended(pHash, &k);
+}
+
+#ifdef HASH_TRACE
+void HASH_Dump(HASH_TABLE * pHash)
+{
+ u32 uIndex;
+ u32 uMaxLength = 0;
+ u32 uEmptyCount = 0;
+
+ PVR_ASSERT(pHash != NULL);
+ for (uIndex = 0; uIndex < pHash->uSize; uIndex++) {
+ BUCKET *pBucket;
+ u32 uLength = 0;
+ if (pHash->ppBucketTable[uIndex] == NULL)
+ uEmptyCount++;
+ for (pBucket = pHash->ppBucketTable[uIndex];
+ pBucket != NULL; pBucket = pBucket->pNext)
+ uLength++;
+ uMaxLength = PRIVATE_MAX(uMaxLength, uLength);
+ }
+
+ PVR_TRACE(("hash table: uMinimumSize=%d size=%d count=%d",
+ pHash->uMinimumSize, pHash->uSize, pHash->uCount));
+ PVR_TRACE((" empty=%d max=%d", uEmptyCount, uMaxLength));
+}
+#endif
diff --git a/drivers/staging/ice4100/sgx535/common/lists.c b/drivers/staging/ice4100/sgx535/common/lists.c
new file mode 100755
index 00000000000..0b34671c070
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/lists.c
@@ -0,0 +1,92 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "lists.h"
+#include "services_headers.h"
+
+IMPLEMENT_LIST_ANY_VA(BM_HEAP)
+ IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+ IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
+ IMPLEMENT_LIST_FOR_EACH_VA(BM_HEAP)
+ IMPLEMENT_LIST_REMOVE(BM_HEAP)
+ IMPLEMENT_LIST_INSERT(BM_HEAP)
+
+/* FIXME MLD */
+typedef void *mldhack;
+IMPLEMENT_LIST_ANY_VA(BM_CONTEXT)
+ IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, mldhack, NULL)
+ IMPLEMENT_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK)
+ IMPLEMENT_LIST_FOR_EACH(BM_CONTEXT)
+ IMPLEMENT_LIST_REMOVE(BM_CONTEXT)
+ IMPLEMENT_LIST_INSERT(BM_CONTEXT)
+
+ IMPLEMENT_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+ IMPLEMENT_LIST_ANY_VA(PVRSRV_DEVICE_NODE)
+ IMPLEMENT_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK)
+ IMPLEMENT_LIST_FOR_EACH(PVRSRV_DEVICE_NODE)
+ IMPLEMENT_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE)
+ IMPLEMENT_LIST_INSERT(PVRSRV_DEVICE_NODE)
+ IMPLEMENT_LIST_REMOVE(PVRSRV_DEVICE_NODE)
+
+ IMPLEMENT_LIST_ANY_VA(PVRSRV_POWER_DEV)
+ IMPLEMENT_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK)
+ IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
+ IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+
+void *MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE * psDeviceNode, va_list va)
+{
+ u32 ui32DevIndex;
+ int bIgnoreClass;
+ PVRSRV_DEVICE_CLASS eDevClass;
+
+ ui32DevIndex = va_arg(va, u32);
+ bIgnoreClass = va_arg(va, int);
+ if (!bIgnoreClass) {
+ eDevClass = va_arg(va, PVRSRV_DEVICE_CLASS);
+ } else {
+
+ eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
+ }
+
+ if ((bIgnoreClass || psDeviceNode->sDevId.eDeviceClass == eDevClass) &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex) {
+ return psDeviceNode;
+ }
+ return NULL;
+}
+
+void *MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV * psPowerDev, va_list va)
+{
+ u32 ui32DeviceIndex;
+
+ ui32DeviceIndex = va_arg(va, u32);
+
+ if (psPowerDev->ui32DeviceIndex == ui32DeviceIndex) {
+ return psPowerDev;
+ } else {
+ return NULL;
+ }
+}
diff --git a/drivers/staging/ice4100/sgx535/common/mem.c b/drivers/staging/ice4100/sgx535/common/mem.c
new file mode 100755
index 00000000000..2dc34e92ca3
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/mem.c
@@ -0,0 +1,131 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pvr_bridge_km.h"
+
+static PVRSRV_ERROR FreeSharedSysMemCallBack(void *pvParam, u32 ui32Param)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+ OSFreePages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->ui32AllocSize,
+ psKernelMemInfo->pvLinAddrKM,
+ psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psKernelMemInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ u32 ui32Flags,
+ u32 ui32Size,
+ PVRSRV_KERNEL_MEM_INFO ** ppsKernelMemInfo)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (void **)&psKernelMemInfo, NULL,
+ "Kernel Memory Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for meminfo"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(psKernelMemInfo, 0, sizeof(*psKernelMemInfo));
+
+ ui32Flags &= ~PVRSRV_HAP_MAPTYPE_MASK;
+ ui32Flags |= PVRSRV_HAP_MULTI_PROCESS;
+ psKernelMemInfo->ui32Flags = ui32Flags;
+ psKernelMemInfo->ui32AllocSize = ui32Size;
+
+ if (OSAllocPages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->ui32AllocSize,
+ HOST_PAGESIZE(),
+ &psKernelMemInfo->pvLinAddrKM,
+ &psKernelMemInfo->sMemBlk.hOSMemHandle)
+ != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAllocSharedSysMemoryKM: Failed to alloc memory for block"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_MEM_INFO), psKernelMemInfo, 0);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psKernelMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+ psKernelMemInfo, 0, FreeSharedSysMemCallBack);
+
+ *ppsKernelMemInfo = psKernelMemInfo;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR
+PVRSRVFreeSharedSysMemoryKM(PVRSRV_KERNEL_MEM_INFO * psKernelMemInfo)
+{
+ PVRSRV_ERROR eError;
+
+ if (psKernelMemInfo->sMemBlk.hResItem) {
+ eError = ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem);
+ } else {
+ eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0);
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR
+PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO * psKernelMemInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (!psKernelMemInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (psKernelMemInfo->sMemBlk.hResItem) {
+ eError =
+ ResManDissociateRes(psKernelMemInfo->sMemBlk.hResItem,
+ NULL);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDissociateMemFromResmanKM: ResManDissociateRes failed"));
+ PVR_DBG_BREAK;
+ return eError;
+ }
+
+ psKernelMemInfo->sMemBlk.hResItem = NULL;
+ }
+
+ return eError;
+}
diff --git a/drivers/staging/ice4100/sgx535/common/mem_debug.c b/drivers/staging/ice4100/sgx535/common/mem_debug.c
new file mode 100755
index 00000000000..49eda5e3e3d
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/mem_debug.c
@@ -0,0 +1,228 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#ifndef MEM_DEBUG_C
+#define MEM_DEBUG_C
+
+#if defined(PVRSRV_DEBUG_OS_MEMORY)
+
+#include "img_types.h"
+#include "services_headers.h"
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define STOP_ON_ERROR 0
+
+ int MemCheck(const void *pvAddr, const u8 ui8Pattern, u32 uSize) {
+ u8 *pui8Addr;
+ for (pui8Addr = (u8 *) pvAddr; uSize > 0; uSize--, pui8Addr++) {
+ if (*pui8Addr != ui8Pattern) {
+ return 0;
+ }
+ } return 1;
+ }
+
+ void OSCheckMemDebug(void *pvCpuVAddr, u32 uSize,
+ const char *pszFileName, const u32 uLine) {
+ OSMEM_DEBUG_INFO const *psInfo =
+ (OSMEM_DEBUG_INFO *) ((u32) pvCpuVAddr -
+ TEST_BUFFER_PADDING_STATUS);
+
+ if (pvCpuVAddr == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr,
+ pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR) ;
+ }
+
+ if (((u32) pvCpuVAddr & 3) != 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Pointer 0x%X : invalid alignment"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR) ;
+ }
+
+ if (!MemCheck
+ ((void *)psInfo->sGuardRegionBefore, 0xB1,
+ sizeof(psInfo->sGuardRegionBefore))) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Pointer 0x%X : guard region before overwritten"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR) ;
+ }
+
+ if (uSize != psInfo->uSize) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, uSize, psInfo->uSize, pszFileName,
+ uLine, psInfo->sFileName, psInfo->uLineNo));
+ while (STOP_ON_ERROR) ;
+ }
+
+ if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
+ " - referenced %s:%d - allocated %s:%d",
+ pvCpuVAddr, psInfo->uSize,
+ 0x01234567 ^ psInfo->uSizeParityCheck,
+ pszFileName, uLine, psInfo->sFileName,
+ psInfo->uLineNo));
+ while (STOP_ON_ERROR) ;
+ } else {
+
+ uSize = psInfo->uSize;
+ }
+
+ if (uSize) {
+ if (!MemCheck
+ ((void *)((u32) pvCpuVAddr + uSize), 0xB2,
+ TEST_BUFFER_PADDING_AFTER)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Pointer 0x%X : guard region after overwritten"
+ " - referenced from %s:%d - allocated from %s:%d",
+ pvCpuVAddr, pszFileName, uLine,
+ psInfo->sFileName, psInfo->uLineNo));
+ }
+ }
+
+ if (psInfo->eValid != isAllocated) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "Pointer 0x%X : not allocated (freed? %d)"
+ " - referenced %s:%d - freed %s:%d",
+ pvCpuVAddr, psInfo->eValid == isFree,
+ pszFileName, uLine, psInfo->sFileName,
+ psInfo->uLineNo));
+ while (STOP_ON_ERROR) ;
+ }
+ }
+
+ void debug_strcpy(char *pDest, const char *pSrc) {
+ u32 i = 0;
+
+ for (; i < 128; i++) {
+ *pDest = *pSrc;
+ if (*pSrc == '\0')
+ break;
+ pDest++;
+ pSrc++;
+ }
+ }
+
+ PVRSRV_ERROR OSAllocMem_Debug_Wrapper(u32 ui32Flags,
+ u32 ui32Size,
+ void **ppvCpuVAddr,
+ void **phBlockAlloc,
+ char *pszFilename, u32 ui32Line) {
+ OSMEM_DEBUG_INFO *psInfo;
+
+ PVRSRV_ERROR eError;
+
+ eError = OSAllocMem_Debug_Linux_Memory_Allocations(ui32Flags,
+ ui32Size +
+ TEST_BUFFER_PADDING,
+ ppvCpuVAddr,
+ phBlockAlloc,
+ pszFilename,
+ ui32Line);
+
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ memset((char *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS,
+ 0xBB, ui32Size);
+ memset((char *)(*ppvCpuVAddr) + ui32Size +
+ TEST_BUFFER_PADDING_STATUS, 0xB2,
+ TEST_BUFFER_PADDING_AFTER);
+
+ psInfo = (OSMEM_DEBUG_INFO *) (*ppvCpuVAddr);
+
+ memset(psInfo->sGuardRegionBefore, 0xB1,
+ sizeof(psInfo->sGuardRegionBefore));
+ debug_strcpy(psInfo->sFileName, pszFilename);
+ psInfo->uLineNo = ui32Line;
+ psInfo->eValid = isAllocated;
+ psInfo->uSize = ui32Size;
+ psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
+
+ *ppvCpuVAddr =
+ (void *)((u32) * ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS;
+
+#ifdef PVRSRV_LOG_MEMORY_ALLOCS
+
+ PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
+#endif
+
+ return PVRSRV_OK;
+ }
+
+ PVRSRV_ERROR OSFreeMem_Debug_Wrapper(u32 ui32Flags,
+ u32 ui32Size,
+ void *pvCpuVAddr,
+ void *hBlockAlloc,
+ char *pszFilename, u32 ui32Line) {
+ OSMEM_DEBUG_INFO *psInfo;
+
+ OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
+
+ memset(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+
+ psInfo =
+ (OSMEM_DEBUG_INFO *) ((u32) pvCpuVAddr -
+ TEST_BUFFER_PADDING_STATUS);
+
+ psInfo->uSize = 0;
+ psInfo->uSizeParityCheck = 0;
+ psInfo->eValid = isFree;
+ psInfo->uLineNo = ui32Line;
+ debug_strcpy(psInfo->sFileName, pszFilename);
+
+ return OSFreeMem_Debug_Linux_Memory_Allocations(ui32Flags,
+ ui32Size +
+ TEST_BUFFER_PADDING,
+ psInfo,
+ hBlockAlloc,
+ pszFilename,
+ ui32Line);
+ }
+
+#if defined (__cplusplus)
+
+}
+#endif
+
+#endif
+
+#endif
diff --git a/drivers/staging/ice4100/sgx535/common/metrics.c b/drivers/staging/ice4100/sgx535/common/metrics.c
new file mode 100755
index 00000000000..aa74ad4d869
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/metrics.c
@@ -0,0 +1,149 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "metrics.h"
+
+#if defined(SUPPORT_VGX)
+#include "vgxapi_km.h"
+#endif
+
+#if defined(SUPPORT_SGX)
+#include "sgxapi_km.h"
+#endif
+
+#if defined(DEBUG) || defined(TIMING)
+
+static volatile u32 *pui32TimerRegister = 0;
+
+#define PVRSRV_TIMER_TOTAL_IN_TICKS(X) asTimers[X].ui32Total
+#define PVRSRV_TIMER_TOTAL_IN_MS(X) ((1000*asTimers[X].ui32Total)/ui32TicksPerMS)
+#define PVRSRV_TIMER_COUNT(X) asTimers[X].ui32Count
+
+Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+
+u32 PVRSRVTimeNow(void)
+{
+ if (!pui32TimerRegister) {
+ static int bFirstTime = 1;
+
+ if (bFirstTime) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVTimeNow: No timer register set up"));
+
+ bFirstTime = 0;
+ }
+
+ return 0;
+ }
+#if defined(__sh__)
+
+ return (0xffffffff - *pui32TimerRegister);
+
+#else
+
+ return 0;
+
+#endif
+}
+
+static u32 PVRSRVGetCPUFreq(void)
+{
+ u32 ui32Time1, ui32Time2;
+
+ ui32Time1 = PVRSRVTimeNow();
+
+ OSWaitus(1000000);
+
+ ui32Time2 = PVRSRVTimeNow();
+
+ PVR_DPF((PVR_DBG_WARNING, "PVRSRVGetCPUFreq: timer frequency = %d Hz",
+ ui32Time2 - ui32Time1));
+
+ return (ui32Time2 - ui32Time1);
+}
+
+void PVRSRVSetupMetricTimers(void *pvDevInfo)
+{
+ u32 ui32Loop;
+
+ for (ui32Loop = 0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++) {
+ asTimers[ui32Loop].ui32Total = 0;
+ asTimers[ui32Loop].ui32Count = 0;
+ }
+
+#if defined(__sh__)
+
+ *TCR_2 = TIMER_DIVISOR;
+
+ *TCOR_2 = *TCNT_2 = (u32) 0xffffffff;
+
+ *TST_REG |= (u8) 0x04;
+
+ pui32TimerRegister = (u32 *) TCNT_2;
+
+#else
+
+ pui32TimerRegister = 0;
+
+#endif
+
+}
+
+void PVRSRVOutputMetricTotals(void)
+{
+ u32 ui32TicksPerMS, ui32Loop;
+
+ ui32TicksPerMS = PVRSRVGetCPUFreq();
+
+ if (!ui32TicksPerMS) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVOutputMetricTotals: Failed to get CPU Freq"));
+ return;
+ }
+
+ for (ui32Loop = 0; ui32Loop < (PVRSRV_NUM_TIMERS); ui32Loop++) {
+ if (asTimers[ui32Loop].ui32Count & 0x80000000L) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVOutputMetricTotals: Timer %u is still ON",
+ ui32Loop));
+ }
+ }
+#if 0
+
+ PVR_DPF((PVR_DBG_ERROR, " Timer(%u): Total = %u",
+ PVRSRV_TIMER_EXAMPLE_1,
+ PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR, " Timer(%u): Time = %ums",
+ PVRSRV_TIMER_EXAMPLE_1,
+ PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
+ PVR_DPF((PVR_DBG_ERROR, " Timer(%u): Count = %u",
+ PVRSRV_TIMER_EXAMPLE_1,
+ PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
+#endif
+}
+
+#endif
diff --git a/drivers/staging/ice4100/sgx535/common/pdump_common.c b/drivers/staging/ice4100/sgx535/common/pdump_common.c
new file mode 100755
index 00000000000..d5a50b768f2
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/pdump_common.c
@@ -0,0 +1,1558 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#if defined(PDUMP)
+#include <stdarg.h>
+
+#include "services_headers.h"
+#if defined(SUPPORT_SGX)
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#endif
+#include "pdump_km.h"
+
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024L)
+#endif
+
+#if 1
+#define PDUMP_DBG(a) PDumpOSDebugPrintf a
+#else
+#define PDUMP_DBG(a)
+#endif
+
+#define PDUMP_DATAMASTER_PIXEL (1)
+#define PDUMP_DATAMASTER_EDM (3)
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define PTR_PLUS(t, p, x) ((t *)(((char *)(p)) + (x)))
+#define VPTR_PLUS(p, x) PTR_PLUS(void, p, x)
+#define VPTR_INC(p, x) (p = VPTR_PLUS(p, x))
+#define MAX_PDUMP_MMU_CONTEXTS (32)
+static void *gpvTempBuffer = NULL;
+static void *ghTempBufferBlockAlloc;
+static u16 gui16MMUContextUsage = 0;
+
+static void *GetTempBuffer(void)
+{
+
+ if (gpvTempBuffer == NULL) {
+ PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ &gpvTempBuffer,
+ &ghTempBufferBlockAlloc,
+ "PDUMP Temporary Buffer");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "GetTempBuffer: OSAllocMem failed: %d",
+ eError));
+ }
+ }
+
+ return gpvTempBuffer;
+}
+
+static void FreeTempBuffer(void)
+{
+
+ if (gpvTempBuffer != NULL) {
+ PVRSRV_ERROR eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ gpvTempBuffer,
+ ghTempBufferBlockAlloc);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeTempBuffer: OSFreeMem failed: %d",
+ eError));
+ } else {
+ gpvTempBuffer = NULL;
+ }
+ }
+}
+
+void PDumpInitCommon(void)
+{
+
+ (void)GetTempBuffer();
+
+ PDumpInit();
+}
+
+void PDumpDeInitCommon(void)
+{
+
+ FreeTempBuffer();
+
+ PDumpDeInit();
+}
+
+#if defined(SGX_SUPPORT_COMMON_PDUMP)
+
+int PDumpIsSuspended(void)
+{
+ return PDumpOSIsSuspended();
+}
+
+PVRSRV_ERROR PDumpRegWithFlagsKM(u32 ui32Reg, u32 ui32Data, u32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+ PDUMP_DBG(("PDumpRegWithFlagsKM"));
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :SGXREG:0x%8.8lX 0x%8.8lX\r\n", ui32Reg,
+ ui32Data);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegKM(u32 ui32Reg, u32 ui32Data)
+{
+ return PDumpRegWithFlagsKM(ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpRegPolWithFlagsKM(u32 ui32RegAddr, u32 ui32RegValue,
+ u32 ui32Mask, u32 ui32Flags)
+{
+
+#define POLL_DELAY 1000UL
+#define POLL_COUNT_LONG (2000000000UL / POLL_DELAY)
+#define POLL_COUNT_SHORT (1000000UL / POLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ u32 ui32PollCount;
+
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
+
+ if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) !=
+ 0) || ((ui32RegAddr == EUR_CR_EVENT_STATUS)
+ && (ui32RegValue & ui32Mask &
+ EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0)
+ || ((ui32RegAddr == EUR_CR_EVENT_STATUS)
+ && (ui32RegValue & ui32Mask &
+ EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0)) {
+ ui32PollCount = POLL_COUNT_LONG;
+ } else {
+ ui32PollCount = POLL_COUNT_SHORT;
+ }
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "POL :SGXREG:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %lu %d\r\n",
+ ui32RegAddr, ui32RegValue, ui32Mask, 0,
+ ui32PollCount, POLL_DELAY);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegPolKM(u32 ui32RegAddr, u32 ui32RegValue, u32 ui32Mask)
+{
+ return PDumpRegPolWithFlagsKM(ui32RegAddr, ui32RegValue, ui32Mask,
+ PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpMallocPages(PVRSRV_DEVICE_TYPE eDeviceType,
+ u32 ui32DevVAddr,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ void *hOSMemHandle,
+ u32 ui32NumBytes,
+ u32 ui32PageSize, void *hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ u8 *pui8LinAddr;
+ u32 ui32Offset;
+ u32 ui32NumPages;
+ IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32Page;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+#if defined(LINUX)
+ PVR_ASSERT(hOSMemHandle);
+#else
+ PVR_ASSERT(((u32) pvLinAddr & (SGX_MMU_PAGE_MASK)) == 0);
+#endif
+
+ PVR_ASSERT(((u32) ui32DevVAddr & (SGX_MMU_PAGE_MASK)) == 0);
+ PVR_ASSERT(((u32) ui32NumBytes & (SGX_MMU_PAGE_MASK)) == 0);
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "-- MALLOC :SGXMEM:VA_%8.8lX 0x%8.8lX %lu\r\n",
+ ui32DevVAddr, ui32NumBytes, ui32PageSize);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ pui8LinAddr = (u8 *) pvLinAddr;
+ ui32Offset = 0;
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ while (ui32NumPages) {
+ ui32NumPages--;
+
+ PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+ hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr,
+ ui32PageSize, &sDevPAddr);
+ ui32Page = sDevPAddr.uiAddr / ui32PageSize;
+
+ pui8LinAddr += ui32PageSize;
+ ui32Offset += ui32PageSize;
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "MALLOC :SGXMEM:PA_%8.8lX%8.8lX %lu %lu 0x%8.8lX\r\n",
+ (u32) hUniqueTag, ui32Page * ui32PageSize,
+ ui32PageSize, ui32PageSize,
+ ui32Page * ui32PageSize);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMallocPageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ u32 ui32PTSize, void *hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32Page;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((u32) pvLinAddr & (ui32PTSize - 1)) == 0);
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "-- MALLOC :SGXMEM:PAGE_TABLE 0x%8.8lX %lu\r\n",
+ ui32PTSize, SGX_MMU_PAGE_SIZE);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ {
+
+ PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+ NULL,
+ 0,
+ (u8 *) pvLinAddr,
+ SGX_MMU_PAGE_SIZE, &sDevPAddr);
+ ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "MALLOC :SGXMEM:PA_%8.8lX%8.8lX 0x%lX %lu 0x%8.8lX\r\n",
+ (u32) hUniqueTag,
+ ui32Page * SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE,
+ ui32Page * SGX_MMU_PAGE_SIZE);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePages(BM_HEAP * psBMHeap,
+ IMG_DEV_VIRTADDR sDevVAddr,
+ u32 ui32NumBytes,
+ u32 ui32PageSize,
+ void *hUniqueTag, int bInterleaved)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32NumPages, ui32PageCounter;
+ IMG_DEV_PHYADDR sDevPAddr;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((u32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+ PVR_ASSERT(((u32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "-- FREE :SGXMEM:VA_%8.8lX\r\n", sDevVAddr.uiAddr);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
+ for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages;
+ ui32PageCounter++) {
+ if (!bInterleaved || (ui32PageCounter % 2) == 0) {
+ sDevPAddr =
+ psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->
+ pMMUHeap,
+ sDevVAddr);
+ {
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "FREE :SGXMEM:PA_%8.8lX%8.8lX\r\n",
+ (u32) hUniqueTag,
+ sDevPAddr.uiAddr);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript,
+ PDUMP_FLAGS_CONTINUOUS);
+ }
+ } else {
+
+ }
+
+ sDevVAddr.uiAddr += ui32PageSize;
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ u32 ui32PTSize, void *hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32Page;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((u32) pvLinAddr & (ui32PTSize - 1UL)) == 0);
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "-- FREE :SGXMEM:PAGE_TABLE\r\n");
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ {
+ PDumpOSCPUVAddrToDevPAddr(eDeviceType,
+ NULL,
+ 0,
+ (u8 *) pvLinAddr,
+ SGX_MMU_PAGE_SIZE, &sDevPAddr);
+ ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+ {
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "FREE :SGXMEM:PA_%8.8lX%8.8lX\r\n",
+ (u32) hUniqueTag,
+ ui32Page * SGX_MMU_PAGE_SIZE);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDRegWithFlags(u32 ui32Reg,
+ u32 ui32Data, u32 ui32Flags, void *hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING()
+
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+ (u32) hUniqueTag,
+ (ui32Data & SGX_MMU_PDE_ADDR_MASK) <<
+ SGX_MMU_PDE_ADDR_ALIGNSHIFT);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "SHR :SGXMEM:$1 :SGXMEM:$1 0x4\r\n");
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+ "WRW :SGXREG:0x%8.8lX: SGXMEM:$1\r\n", ui32Reg);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXREG:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+ ui32Reg,
+ (u32) hUniqueTag,
+ (ui32Data & SGX_MMU_PDE_ADDR_MASK) <<
+ SGX_MMU_PDE_ADDR_ALIGNSHIFT,
+ ui32Data & ~SGX_MMU_PDE_ADDR_MASK);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+#endif
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDReg(u32 ui32Reg, u32 ui32Data, void *hUniqueTag)
+{
+ return PDumpPDRegWithFlags(ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS,
+ hUniqueTag);
+}
+
+PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo,
+ u32 ui32Offset,
+ u32 ui32Value,
+ u32 ui32Mask,
+ PDUMP_POLL_OPERATOR eOperator,
+ u32 ui32Flags, void *hUniqueTag)
+{
+#define MEMPOLL_DELAY (1000)
+#define MEMPOLL_COUNT (2000000000 / MEMPOLL_DELAY)
+
+ PVRSRV_ERROR eErr;
+ u32 ui32PageOffset;
+ u8 *pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT((ui32Offset + sizeof(u32)) <= psMemInfo->ui32AllocSize);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "-- POL :SGXMEM:VA_%8.8lX 0x%8.8lX 0x%8.8lX %d %d %d\r\n",
+ psMemInfo->sDevVAddr.uiAddr + ui32Offset,
+ ui32Value,
+ ui32Mask,
+ eOperator, MEMPOLL_COUNT, MEMPOLL_DELAY);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ pui8LinAddr = psMemInfo->pvLinAddrKM;
+
+ pui8LinAddr += ui32Offset;
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset, pui8LinAddr, &ui32PageOffset);
+
+ sDevVPageAddr.uiAddr =
+ psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "POL :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %d %d %d\r\n",
+ (u32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32Value,
+ ui32Mask,
+ eOperator, MEMPOLL_COUNT, MEMPOLL_DELAY);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMemKM(void *pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO * psMemInfo,
+ u32 ui32Offset,
+ u32 ui32Bytes, u32 ui32Flags, void *hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32NumPages;
+ u32 ui32PageByteOffset;
+ u32 ui32BlockBytes;
+ u8 *pui8LinAddr;
+ u8 *pui8DataLinAddr = NULL;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32ParamOutPos;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
+
+ if (!PDumpOSJTInitialised()) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (ui32Bytes == 0 || PDumpOSIsSuspended()) {
+ return PVRSRV_OK;
+ }
+
+ if (pvAltLinAddr) {
+ pui8DataLinAddr = pvAltLinAddr;
+ } else if (psMemInfo->pvLinAddrKM) {
+ pui8DataLinAddr = (u8 *) psMemInfo->pvLinAddrKM + ui32Offset;
+ }
+ pui8LinAddr = (u8 *) psMemInfo->pvLinAddrKM;
+ sDevVAddr = psMemInfo->sDevVAddr;
+
+ sDevVAddr.uiAddr += ui32Offset;
+ pui8LinAddr += ui32Offset;
+
+ PVR_ASSERT(pui8DataLinAddr);
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pui8DataLinAddr, ui32Bytes, ui32Flags)) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0) {
+ eErr =
+ PDumpOSSprintf(pszFileName, ui32MaxLenFileName,
+ "%%0%%.prm");
+ } else {
+ eErr =
+ PDumpOSSprintf(pszFileName, ui32MaxLenFileName,
+ "%%0%%%lu.prm", PDumpOSGetParamFileNum());
+ }
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "-- LDB :SGXMEM:VA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+ (u32) hUniqueTag,
+ psMemInfo->sDevVAddr.uiAddr,
+ ui32Offset,
+ ui32Bytes, ui32ParamOutPos, pszFileName);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32Offset,
+ pui8LinAddr, &ui32PageByteOffset);
+ ui32NumPages =
+ (ui32PageByteOffset + ui32Bytes + HOST_PAGESIZE() -
+ 1) / HOST_PAGESIZE();
+
+ while (ui32NumPages) {
+#if 0
+ u32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE);
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32CurrentOffset);
+#endif
+ ui32NumPages--;
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+ sDevPAddr.uiAddr += ui32PageByteOffset;
+#if 0
+ if (ui32PageByteOffset) {
+ ui32BlockBytes =
+ MIN(ui32BytesRemaining,
+ PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
+
+ ui32PageByteOffset = 0;
+ }
+#endif
+
+ if (ui32PageByteOffset + ui32Bytes > HOST_PAGESIZE()) {
+
+ ui32BlockBytes = HOST_PAGESIZE() - ui32PageByteOffset;
+ } else {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+ (u32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32BlockBytes,
+ ui32ParamOutPos, pszFileName);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+
+ ui32PageByteOffset = 0;
+
+ ui32Bytes -= ui32BlockBytes;
+
+ sDevVAddr.uiAddr += ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpMem2KM(PVRSRV_DEVICE_TYPE eDeviceType,
+ IMG_CPU_VIRTADDR pvLinAddr,
+ u32 ui32Bytes,
+ u32 ui32Flags,
+ int bInitialisePages,
+ void *hUniqueTag1, void *hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32NumPages;
+ u32 ui32PageOffset;
+ u32 ui32BlockBytes;
+ u8 *pui8LinAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ u32 ui32Offset;
+ u32 ui32ParamOutPos;
+
+ PDUMP_GET_SCRIPT_AND_FILE_STRING();
+
+ if (!pvLinAddr || !PDumpOSJTInitialised()) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (PDumpOSIsSuspended()) {
+ return PVRSRV_OK;
+ }
+
+ PDumpOSCheckForSplitting(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ ui32Bytes, ui32Flags);
+
+ ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
+
+ if (bInitialisePages) {
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ pvLinAddr,
+ ui32Bytes, PDUMP_FLAGS_CONTINUOUS)) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (PDumpOSGetParamFileNum() == 0) {
+ eErr =
+ PDumpOSSprintf(pszFileName, ui32MaxLenFileName,
+ "%%0%%.prm");
+ } else {
+ eErr =
+ PDumpOSSprintf(pszFileName, ui32MaxLenFileName,
+ "%%0%%%lu.prm",
+ PDumpOSGetParamFileNum());
+ }
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ }
+
+ ui32PageOffset = (u32) pvLinAddr & (HOST_PAGESIZE() - 1);
+ ui32NumPages =
+ (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() -
+ 1) / HOST_PAGESIZE();
+ pui8LinAddr = (u8 *) pvLinAddr;
+
+ while (ui32NumPages) {
+ ui32NumPages--;
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+ if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE()) {
+
+ ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset;
+ } else {
+
+ ui32BlockBytes = ui32Bytes;
+ }
+
+ if (bInitialisePages) {
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "LDB :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX %s\r\n",
+ (u32) hUniqueTag1,
+ sDevPAddr.
+ uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.
+ uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32BlockBytes, ui32ParamOutPos,
+ pszFileName);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+ } else {
+ for (ui32Offset = 0; ui32Offset < ui32BlockBytes;
+ ui32Offset += sizeof(u32)) {
+ u32 ui32PTE =
+ *((u32 *) (pui8LinAddr + ui32Offset));
+
+ if ((ui32PTE & SGX_MMU_PDE_ADDR_MASK) != 0) {
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+ (u32)
+ hUniqueTag2,
+ (ui32PTE &
+ SGX_MMU_PDE_ADDR_MASK)
+ <<
+ SGX_MMU_PTE_ADDR_ALIGNSHIFT);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript,
+ PDUMP_FLAGS_CONTINUOUS);
+ eErr =
+ PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "SHR :SGXMEM:$1 :SGXMEM:$1 0x4\r\n");
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript,
+ PDUMP_FLAGS_CONTINUOUS);
+ eErr =
+ PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "OR :SGXMEM:$1 :SGXMEM:$1 0x%8.8lX\r\n",
+ ui32PTE &
+ ~SGX_MMU_PDE_ADDR_MASK);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript,
+ PDUMP_FLAGS_CONTINUOUS);
+ eErr =
+ PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$1\r\n",
+ (u32) hUniqueTag1,
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ ~
+ (SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ (SGX_MMU_PAGE_MASK));
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript,
+ PDUMP_FLAGS_CONTINUOUS);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+ (u32)
+ hUniqueTag1,
+ (sDevPAddr.
+ uiAddr +
+ ui32Offset) &
+ ~
+ (SGX_MMU_PAGE_MASK),
+ (sDevPAddr.
+ uiAddr +
+ ui32Offset) &
+ (SGX_MMU_PAGE_MASK),
+ (u32)
+ hUniqueTag2,
+ (ui32PTE &
+ SGX_MMU_PDE_ADDR_MASK)
+ <<
+ SGX_MMU_PTE_ADDR_ALIGNSHIFT,
+ ui32PTE &
+ ~SGX_MMU_PDE_ADDR_MASK);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+#endif
+ } else {
+ PVR_ASSERT((ui32PTE & SGX_MMU_PTE_VALID)
+ == 0UL);
+ eErr =
+ PDumpOSBufprintf(hScript,
+ ui32MaxLenScript,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX%8.8lX\r\n",
+ (u32) hUniqueTag1,
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ ~
+ (SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ (SGX_MMU_PAGE_MASK),
+ (ui32PTE <<
+ SGX_MMU_PTE_ADDR_ALIGNSHIFT),
+ (u32) hUniqueTag2);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ }
+ PDumpOSWriteString2(hScript,
+ PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+
+ ui32PageOffset = 0;
+
+ ui32Bytes -= ui32BlockBytes;
+
+ pui8LinAddr += ui32BlockBytes;
+
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO * psMemInfo,
+ u32 ui32Offset,
+ IMG_DEV_PHYADDR sPDDevPAddr,
+ void *hUniqueTag1, void *hUniqueTag2)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32PageByteOffset;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
+ (u8 *) & sPDDevPAddr,
+ sizeof(IMG_DEV_PHYADDR),
+ PDUMP_FLAGS_CONTINUOUS)) {
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ sDevVAddr = psMemInfo->sDevVAddr;
+ ui32PageByteOffset = sDevVAddr.uiAddr & (SGX_MMU_PAGE_MASK);
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+ sDevPAddr.uiAddr += ui32PageByteOffset + ui32Offset;
+
+ if ((sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK) != 0UL) {
+#if defined(SGX_FEATURE_36BIT_MMU)
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:$1 :SGXMEM:PA_%8.8lX%8.8lX:0x0\r\n",
+ (u32) hUniqueTag2, sPDDevPAddr.uiAddr);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "AND :SGXMEM:$2 :SGXMEM:$1 0xFFFFFFFF\r\n");
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$2\r\n",
+ (u32) hUniqueTag1,
+ (sDevPAddr.
+ uiAddr) & ~(SGX_MMU_PAGE_MASK),
+ (sDevPAddr.
+ uiAddr) & (SGX_MMU_PAGE_MASK));
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen,
+ "SHR :SGXMEM:$2 :SGXMEM:$1 0x20\r\n");
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:$2\r\n",
+ (u32) hUniqueTag1,
+ (sDevPAddr.uiAddr +
+ 4) & ~(SGX_MMU_PAGE_MASK),
+ (sDevPAddr.uiAddr +
+ 4) & (SGX_MMU_PAGE_MASK));
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX\r\n",
+ (u32) hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ (u32) hUniqueTag2,
+ sPDDevPAddr.
+ uiAddr & SGX_MMU_PDE_ADDR_MASK,
+ sPDDevPAddr.
+ uiAddr & ~SGX_MMU_PDE_ADDR_MASK);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+#endif
+ } else {
+ PVR_ASSERT(!(sDevPAddr.uiAddr & SGX_MMU_PTE_VALID));
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "WRW :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX\r\n",
+ (u32) hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ sPDDevPAddr.uiAddr);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ }
+ PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentKM(char *pszComment, u32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_MSG_STRING();
+ PDUMP_DBG(("PDumpCommentKM"));
+
+ if (!PDumpOSWriteString2("-- ", ui32Flags)) {
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS) {
+ return PVRSRV_ERROR_GENERIC;
+ } else {
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ }
+
+ eErr = PDumpOSBufprintf(hMsg, ui32MaxLen, "%s", pszComment);
+ if ((eErr != PVRSRV_OK) && (eErr != PVRSRV_ERROR_PDUMP_BUF_OVERFLOW)) {
+ return eErr;
+ }
+
+ PDumpOSVerifyLineEnding(hMsg, ui32MaxLen);
+ PDumpOSWriteString2(hMsg, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCommentWithFlags(u32 ui32Flags, char *pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(hMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ return PDumpCommentKM(hMsg, ui32Flags);
+}
+
+PVRSRV_ERROR PDumpComment(char *pszFormat, ...)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_va_list ap;
+ PDUMP_GET_MSG_STRING();
+
+ PDUMP_va_start(ap, pszFormat);
+ eErr = PDumpOSVSprintf(hMsg, ui32MaxLen, pszFormat, ap);
+ PDUMP_va_end(ap);
+
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ return PDumpCommentKM(hMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+PVRSRV_ERROR PDumpDriverInfoKM(char *pszString, u32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32MsgLen;
+ PDUMP_GET_MSG_STRING();
+
+ eErr = PDumpOSBufprintf(hMsg, ui32MaxLen, "%s", pszString);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpOSVerifyLineEnding(hMsg, ui32MaxLen);
+ ui32MsgLen = PDumpOSBuflen(hMsg, ui32MaxLen);
+
+ if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_DRIVERINFO),
+ (u8 *) hMsg, ui32MsgLen, ui32Flags)) {
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS) {
+ return PVRSRV_ERROR_GENERIC;
+ } else {
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpBitmapKM(char *pszFileName,
+ u32 ui32FileOffset,
+ u32 ui32Width,
+ u32 ui32Height,
+ u32 ui32StrideInBytes,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ u32 ui32Size,
+ PDUMP_PIXEL_FORMAT ePixelFormat,
+ PDUMP_MEM_FORMAT eMemFormat, u32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDumpCommentWithFlags(ui32PDumpFlags,
+ "\r\n-- Dump bitmap of render\r\n");
+
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :SGXMEM:v%x:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+ pszFileName,
+ pszFileName,
+ PDUMP_DATAMASTER_PIXEL,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ ePixelFormat,
+ ui32Width,
+ ui32Height, ui32StrideInBytes, eMemFormat);
+#else
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SII %s %s.bin :SGXMEM:v:0x%08lX 0x%08lX 0x%08lX 0x%08X 0x%08lX 0x%08lX 0x%08lX 0x%08X\r\n",
+ pszFileName,
+ pszFileName,
+ sDevBaseAddr.uiAddr,
+ ui32Size,
+ ui32FileOffset,
+ ePixelFormat,
+ ui32Width,
+ ui32Height, ui32StrideInBytes, eMemFormat);
+#endif
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpReadRegKM(char *pszFileName,
+ u32 ui32FileOffset,
+ u32 ui32Address, u32 ui32Size, u32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :SGXREG:0x%08lX 0x%08lX %s\r\n",
+ ui32Address, ui32FileOffset, pszFileName);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+int PDumpTestNextFrame(u32 ui32CurrentFrame)
+{
+ int bFrameDumped;
+
+ (void)PDumpSetFrameKM(ui32CurrentFrame + 1);
+ bFrameDumped = PDumpIsCaptureFrameKM();
+ (void)PDumpSetFrameKM(ui32CurrentFrame);
+
+ return bFrameDumped;
+}
+
+static PVRSRV_ERROR PDumpSignatureRegister(char *pszFileName,
+ u32 ui32Address,
+ u32 ui32Size,
+ u32 * pui32FileOffset, u32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "SAB :SGXREG:0x%08X 0x%08X %s\r\n",
+ ui32Address, *pui32FileOffset, pszFileName);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32Flags);
+ *pui32FileOffset += ui32Size;
+ return PVRSRV_OK;
+}
+
+static void PDumpRegisterRange(char *pszFileName,
+ u32 * pui32Registers,
+ u32 ui32NumRegisters,
+ u32 * pui32FileOffset,
+ u32 ui32Size, u32 ui32Flags)
+{
+ u32 i;
+ for (i = 0; i < ui32NumRegisters; i++) {
+ PDumpSignatureRegister(pszFileName, pui32Registers[i], ui32Size,
+ pui32FileOffset, ui32Flags);
+ }
+}
+
+PVRSRV_ERROR PDump3DSignatureRegisters(u32 ui32DumpFrameNum,
+ int bLastFrame,
+ u32 * pui32Registers,
+ u32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = 0;
+
+ PDumpCommentWithFlags(ui32Flags,
+ "\r\n-- Dump 3D signature registers\r\n");
+ eErr =
+ PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu_3d.sig",
+ ui32DumpFrameNum);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters,
+ &ui32FileOffset, sizeof(u32), ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpTASignatureRegisters(u32 ui32DumpFrameNum,
+ u32 ui32TAKickCount,
+ int bLastFrame,
+ u32 * pui32Registers,
+ u32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(u32);
+
+ PDumpCommentWithFlags(ui32Flags,
+ "\r\n-- Dump TA signature registers\r\n");
+ eErr =
+ PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu_ta.sig",
+ ui32DumpFrameNum);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters,
+ &ui32FileOffset, sizeof(u32), ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCounterRegisters(u32 ui32DumpFrameNum,
+ int bLastFrame,
+ u32 * pui32Registers, u32 ui32NumRegisters)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32FileOffset, ui32Flags;
+
+ PDUMP_GET_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0UL;
+ ui32FileOffset = 0UL;
+
+ PDumpCommentWithFlags(ui32Flags, "\r\n-- Dump counter registers\r\n");
+ eErr =
+ PDumpOSSprintf(pszFileName, ui32MaxLen, "out%lu.perf",
+ ui32DumpFrameNum);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpRegisterRange(pszFileName, pui32Registers, ui32NumRegisters,
+ &ui32FileOffset, sizeof(u32), ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpRegRead(const u32 ui32RegOffset, u32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :SGXREG:0x%lX\r\n",
+ ui32RegOffset);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCycleCountRegRead(const u32 ui32RegOffset, int bLastFrame)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+
+ eErr =
+ PDumpOSBufprintf(hScript, ui32MaxLen, "RDW :SGXREG:0x%lX\r\n",
+ ui32RegOffset);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpHWPerfCBKM(char *pszFileName,
+ u32 ui32FileOffset,
+ IMG_DEV_VIRTADDR sDevBaseAddr,
+ u32 ui32Size, u32 ui32PDumpFlags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDumpCommentWithFlags(ui32PDumpFlags,
+ "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
+#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
+ "SAB :SGXMEM:v%x:0x%08lX 0x%08lX 0x%08lX %s.bin\r\n",
+ PDUMP_DATAMASTER_EDM,
+#else
+ "SAB :SGXMEM:v:0x%08lX 0x%08lX 0x%08lX %s.bin\r\n",
+#endif
+ sDevBaseAddr.uiAddr,
+ ui32Size, ui32FileOffset, pszFileName);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+
+ PDumpOSWriteString2(hScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
+ u32 ui32ROffOffset,
+ u32 ui32WPosVal,
+ u32 ui32PacketSize,
+ u32 ui32BufferSize, u32 ui32Flags, void *hUniqueTag)
+{
+ PVRSRV_ERROR eErr;
+ u32 ui32PageOffset;
+ u8 *pui8LinAddr;
+ IMG_DEV_VIRTADDR sDevVAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ IMG_DEV_VIRTADDR sDevVPageAddr;
+
+ PDUMP_GET_SCRIPT_STRING();
+
+ PVR_ASSERT((ui32ROffOffset + sizeof(u32)) <=
+ psROffMemInfo->ui32AllocSize);
+
+ pui8LinAddr = psROffMemInfo->pvLinAddrKM;
+ sDevVAddr = psROffMemInfo->sDevVAddr;
+
+ pui8LinAddr += ui32ROffOffset;
+ sDevVAddr.uiAddr += ui32ROffOffset;
+
+ PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
+ ui32ROffOffset,
+ pui8LinAddr, &ui32PageOffset);
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ eErr = PDumpOSBufprintf(hScript,
+ ui32MaxLen,
+ "CBP :SGXMEM:PA_%8.8lX%8.8lX:0x%8.8lX 0x%8.8lX 0x%8.8lX 0x%8.8lX\r\n",
+ (u32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_MASK),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_MASK),
+ ui32WPosVal, ui32PacketSize, ui32BufferSize);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpIDLWithFlags(u32 ui32Clocks, u32 ui32Flags)
+{
+ PVRSRV_ERROR eErr;
+ PDUMP_GET_SCRIPT_STRING();
+ PDUMP_DBG(("PDumpIDLWithFlags"));
+
+ eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "IDL %lu\r\n", ui32Clocks);
+ if (eErr != PVRSRV_OK) {
+ return eErr;
+ }
+ PDumpOSWriteString2(hScript, ui32Flags);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpIDL(u32 ui32Clocks)
+{
+ return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+#endif
+
+PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA * psPerProc,
+ void *pvAltLinAddrUM,
+ void *pvLinAddrUM,
+ PVRSRV_KERNEL_MEM_INFO * psMemInfo,
+ u32 ui32Offset,
+ u32 ui32Bytes, u32 ui32Flags, void *hUniqueTag)
+{
+ void *pvAddrUM;
+ void *pvAddrKM;
+ u32 ui32BytesDumped;
+ u32 ui32CurrentOffset;
+
+ if (psMemInfo->pvLinAddrKM != NULL && pvAltLinAddrUM == NULL) {
+
+ return PDumpMemKM(NULL,
+ psMemInfo,
+ ui32Offset, ui32Bytes, ui32Flags, hUniqueTag);
+ }
+
+ pvAddrUM =
+ (pvAltLinAddrUM !=
+ NULL) ? pvAltLinAddrUM : ((pvLinAddrUM !=
+ NULL) ? VPTR_PLUS(pvLinAddrUM,
+ ui32Offset) : NULL);
+
+ pvAddrKM = GetTempBuffer();
+
+ PVR_ASSERT(pvAddrUM != NULL && pvAddrKM != NULL);
+ if (pvAddrUM == NULL || pvAddrKM == NULL) {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: Nothing to dump"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (ui32Bytes > PDUMP_TEMP_BUFFER_SIZE) {
+ PDumpCommentWithFlags(ui32Flags,
+ "Dumping 0x%8.8lx bytes of memory, in blocks of 0x%8.8lx bytes",
+ ui32Bytes, (u32) PDUMP_TEMP_BUFFER_SIZE);
+ }
+
+ ui32CurrentOffset = ui32Offset;
+ for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;) {
+ PVRSRV_ERROR eError;
+ u32 ui32BytesToDump =
+ MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM, pvAddrUM, ui32BytesToDump);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PDumpMemUM: OSCopyFromUser failed (%d), eError"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ eError = PDumpMemKM(pvAddrKM,
+ psMemInfo,
+ ui32CurrentOffset,
+ ui32BytesToDump, ui32Flags, hUniqueTag);
+
+ if (eError != PVRSRV_OK) {
+
+ if (ui32BytesDumped != 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PDumpMemUM: PDumpMemKM failed (%d)",
+ eError));
+ }
+ PVR_ASSERT(ui32BytesDumped == 0);
+ return eError;
+ }
+
+ VPTR_INC(pvAddrUM, ui32BytesToDump);
+ ui32CurrentOffset += ui32BytesToDump;
+ ui32BytesDumped += ui32BytesToDump;
+ }
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _PdumpAllocMMUContext(u32 * pui32MMUContextID)
+{
+ u32 i;
+
+ for (i = 0; i < MAX_PDUMP_MMU_CONTEXTS; i++) {
+ if ((gui16MMUContextUsage & (1U << i)) == 0) {
+
+ gui16MMUContextUsage |= 1U << i;
+ *pui32MMUContextID = i;
+ return PVRSRV_OK;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "_PdumpAllocMMUContext: no free MMU context ids"));
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+static PVRSRV_ERROR _PdumpFreeMMUContext(u32 ui32MMUContextID)
+{
+ if (ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS) {
+
+ gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "_PdumpFreeMMUContext: MMU context ids invalid"));
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ char *pszMemSpace,
+ u32 * pui32MMUContextID,
+ u32 ui32MMUType,
+ void *hUniqueTag1, void *pvPDCPUAddr)
+{
+ u8 *pui8LinAddr = (u8 *) pvPDCPUAddr;
+ IMG_CPU_PHYADDR sCpuPAddr;
+ IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32MMUContextID;
+ PVRSRV_ERROR eError;
+
+ eError = _PdumpAllocMMUContext(&ui32MMUContextID);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PDumpSetMMUContext: _PdumpAllocMMUContext failed: %d",
+ eError));
+ return eError;
+ }
+
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+ sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) - 1);
+
+ PDumpComment("Set MMU Context\r\n");
+
+ PDumpComment("MMU :%s:v%d %d :%s:PA_%8.8lX%8.8lX\r\n",
+ pszMemSpace,
+ ui32MMUContextID,
+ ui32MMUType, pszMemSpace, hUniqueTag1, sDevPAddr.uiAddr);
+
+ *pui32MMUContextID = ui32MMUContextID;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
+ char *pszMemSpace,
+ u32 ui32MMUContextID, u32 ui32MMUType)
+{
+ PVRSRV_ERROR eError;
+
+ PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
+
+ PDumpComment("MMU :%s:v%d %d\r\n",
+ pszMemSpace, ui32MMUContextID, ui32MMUType);
+
+ eError = _PdumpFreeMMUContext(ui32MMUContextID);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PDumpClearMMUContext: _PdumpFreeMMUContext failed: %d",
+ eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+#else
+#endif
diff --git a/drivers/staging/ice4100/sgx535/common/perproc.c b/drivers/staging/ice4100/sgx535/common/perproc.c
new file mode 100755
index 00000000000..b5162cc97d8
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/perproc.c
@@ -0,0 +1,276 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "resman.h"
+#include "handle.h"
+#include "perproc.h"
+#include "osperproc.h"
+
+#define HASH_TAB_INIT_SIZE 32
+
+static HASH_TABLE *psHashTab = NULL;
+
+static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA * psPerProc)
+{
+ PVRSRV_ERROR eError;
+ u32 uiPerProc;
+
+ PVR_ASSERT(psPerProc != NULL);
+
+ if (psPerProc == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreePerProcessData: invalid parameter"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ uiPerProc = HASH_Remove(psHashTab, (u32) psPerProc->ui32PID);
+ if (uiPerProc == 0) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreePerProcessData: Couldn't find process in per-process data hash table"));
+
+ PVR_ASSERT(psPerProc->ui32PID == 0);
+ } else {
+ PVR_ASSERT((PVRSRV_PER_PROCESS_DATA *) uiPerProc == psPerProc);
+ PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *) uiPerProc)->ui32PID ==
+ psPerProc->ui32PID);
+ }
+
+ if (psPerProc->psHandleBase != NULL) {
+ eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreePerProcessData: Couldn't free handle base for process (%d)",
+ eError));
+ return eError;
+ }
+ }
+
+ if (psPerProc->hPerProcData != NULL) {
+ eError =
+ PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ psPerProc->hPerProcData,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreePerProcessData: Couldn't release per-process data handle (%d)",
+ eError));
+ return eError;
+ }
+ }
+
+ eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreePerProcessData: OSPerProcessPrivateDataDeInit failed (%d)",
+ eError));
+ return eError;
+ }
+
+ eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ psPerProc, psPerProc->hBlockAlloc);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreePerProcessData: Couldn't free per-process data (%d)",
+ eError));
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(u32 ui32PID)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != NULL);
+
+ psPerProc =
+ (PVRSRV_PER_PROCESS_DATA *) HASH_Retrieve(psHashTab, (u32) ui32PID);
+ return psPerProc;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataConnect(u32 ui32PID)
+{
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+ void *hBlockAlloc;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psHashTab != NULL);
+
+ psPerProc =
+ (PVRSRV_PER_PROCESS_DATA *) HASH_Retrieve(psHashTab, (u32) ui32PID);
+
+ if (psPerProc == NULL) {
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc),
+ (void **)&psPerProc,
+ &hBlockAlloc, "Per Process Data");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataConnect: Couldn't allocate per-process data (%d)",
+ eError));
+ return eError;
+ }
+ memset(psPerProc, 0, sizeof(*psPerProc));
+ psPerProc->hBlockAlloc = hBlockAlloc;
+
+ if (!HASH_Insert(psHashTab, (u32) ui32PID, (u32) psPerProc)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataConnect: Couldn't insert per-process data into hash table"));
+ eError = PVRSRV_ERROR_GENERIC;
+ goto failure;
+ }
+
+ psPerProc->ui32PID = ui32PID;
+ psPerProc->ui32RefCount = 0;
+
+ eError =
+ OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataConnect: OSPerProcessPrivateDataInit failed (%d)",
+ eError));
+ goto failure;
+ }
+
+ eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
+ &psPerProc->hPerProcData,
+ psPerProc,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataConnect: Couldn't allocate handle for per-process data (%d)",
+ eError));
+ goto failure;
+ }
+
+ eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataConnect: Couldn't allocate handle base for process (%d)",
+ eError));
+ goto failure;
+ }
+
+ eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataConnect: Couldn't set handle options (%d)",
+ eError));
+ goto failure;
+ }
+
+ eError =
+ PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataConnect: Couldn't register with the resource manager"));
+ goto failure;
+ }
+ }
+
+ psPerProc->ui32RefCount++;
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVPerProcessDataConnect: Process 0x%x has ref-count %d",
+ ui32PID, psPerProc->ui32RefCount));
+
+ return eError;
+
+failure:
+ (void)FreePerProcessData(psPerProc);
+ return eError;
+}
+
+void PVRSRVPerProcessDataDisconnect(u32 ui32PID)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != NULL);
+
+ psPerProc =
+ (PVRSRV_PER_PROCESS_DATA *) HASH_Retrieve(psHashTab, (u32) ui32PID);
+ if (psPerProc == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataDealloc: Couldn't locate per-process data for PID %u",
+ ui32PID));
+ } else {
+ psPerProc->ui32RefCount--;
+ if (psPerProc->ui32RefCount == 0) {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVPerProcessDataDisconnect: "
+ "Last close from process 0x%x received",
+ ui32PID));
+
+ PVRSRVResManDisconnect(psPerProc->hResManContext, 0);
+
+ eError = FreePerProcessData(psPerProc);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataDisconnect: Error freeing per-process data"));
+ }
+ }
+ }
+
+ eError = PVRSRVPurgeHandles(KERNEL_HANDLE_BASE);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataDisconnect: Purge of global handle pool failed (%d)",
+ eError));
+ }
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataInit(void)
+{
+ PVR_ASSERT(psHashTab == NULL);
+
+ psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
+ if (psHashTab == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVPerProcessDataInit: Couldn't create per-process data hash table"));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVPerProcessDataDeInit(void)
+{
+
+ if (psHashTab != NULL) {
+
+ HASH_Delete(psHashTab);
+ psHashTab = NULL;
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/staging/ice4100/sgx535/common/power.c b/drivers/staging/ice4100/sgx535/common/power.c
new file mode 100755
index 00000000000..0537a16f83a
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/power.c
@@ -0,0 +1,686 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "pdump_km.h"
+
+#include "lists.h"
+
+DECLARE_LIST_ANY_VA(PVRSRV_POWER_DEV);
+DECLARE_LIST_ANY_VA_2(PVRSRV_POWER_DEV, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_INSERT(PVRSRV_POWER_DEV);
+DECLARE_LIST_REMOVE(PVRSRV_POWER_DEV);
+
+void *MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV * psPowerDev, va_list va);
+
+static int gbInitServerRunning = 0;
+static int gbInitServerRan = 0;
+static int gbInitSuccessful = 0;
+
+PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState,
+ int bState)
+{
+
+ switch (eInitServerState) {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ gbInitServerRunning = bState;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ gbInitServerRan = bState;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ gbInitSuccessful = bState;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetInitServerState : Unknown state %lx",
+ eInitServerState));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+int PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+ int bReturnVal;
+
+ switch (eInitServerState) {
+ case PVRSRV_INIT_SERVER_RUNNING:
+ bReturnVal = gbInitServerRunning;
+ break;
+ case PVRSRV_INIT_SERVER_RAN:
+ bReturnVal = gbInitServerRan;
+ break;
+ case PVRSRV_INIT_SERVER_SUCCESSFUL:
+ bReturnVal = gbInitSuccessful;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetInitServerState : Unknown state %lx",
+ eInitServerState));
+ bReturnVal = 0;
+ }
+
+ return bReturnVal;
+}
+
+static int _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
+{
+ return (int)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
+}
+
+PVRSRV_ERROR PVRSRVPowerLock(u32 ui32CallerID, int bSystemPowerEvent)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ u32 ui32Timeout = 1000000;
+
+#if defined(SUPPORT_LMA)
+
+ ui32Timeout *= 60;
+#endif
+
+ SysAcquireData(&psSysData);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ eError = SysPowerLockWrap(psSysData);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+#endif
+ do {
+ eError = OSLockResource(&psSysData->sPowerStateChangeResource,
+ ui32CallerID);
+ if (eError == PVRSRV_OK) {
+ break;
+ } else if (ui32CallerID == ISR_ID) {
+
+ eError = PVRSRV_ERROR_RETRY;
+ break;
+ }
+
+ OSWaitus(1);
+ ui32Timeout--;
+ } while (ui32Timeout > 0);
+
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ if (eError != PVRSRV_OK) {
+ SysPowerLockUnwrap(psSysData);
+ }
+#endif
+ if ((eError == PVRSRV_OK) &&
+ !bSystemPowerEvent &&
+ !_IsSystemStatePowered(psSysData->eCurrentPowerState)) {
+
+ PVRSRVPowerUnlock(ui32CallerID);
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
+void PVRSRVPowerUnlock(u32 ui32CallerID)
+{
+ OSUnlockResource(&gpsSysData->sPowerStateChangeResource, ui32CallerID);
+#if defined(SYS_CUSTOM_POWERLOCK_WRAP)
+ SysPowerLockUnwrap(gpsSysData);
+#endif
+}
+
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *
+ psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+ int bAllDevices;
+ u32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+ bAllDevices = va_arg(va, int);
+ ui32DeviceIndex = va_arg(va, u32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)) {
+ eNewDevicePowerState =
+ (eNewPowerState ==
+ PVRSRV_DEV_POWER_STATE_DEFAULT) ? psPowerDevice->
+ eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState) {
+ if (psPowerDevice->pfnPrePower != NULL) {
+
+ eError =
+ psPowerDevice->pfnPrePower(psPowerDevice->
+ hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+
+ eError =
+ SysDevicePrePowerState(psPowerDevice->
+ ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(int bAllDevices,
+ u32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError =
+ List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->
+ psPowerDeviceList,
+ PVRSRVDevicePrePowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *
+ psPowerDevice, va_list va)
+{
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+ PVRSRV_ERROR eError;
+
+ int bAllDevices;
+ u32 ui32DeviceIndex;
+ PVRSRV_DEV_POWER_STATE eNewPowerState;
+
+ bAllDevices = va_arg(va, int);
+ ui32DeviceIndex = va_arg(va, u32);
+ eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
+
+ if (bAllDevices || (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)) {
+ eNewDevicePowerState =
+ (eNewPowerState ==
+ PVRSRV_DEV_POWER_STATE_DEFAULT) ? psPowerDevice->
+ eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState) {
+
+ eError =
+ SysDevicePostPowerState(psPowerDevice->
+ ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ if (psPowerDevice->pfnPostPower != NULL) {
+
+ eError =
+ psPowerDevice->pfnPostPower(psPowerDevice->
+ hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+
+ psPowerDevice->eCurrentPowerState =
+ eNewDevicePowerState;
+ }
+ }
+ return PVRSRV_OK;
+}
+
+static
+PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(int bAllDevices,
+ u32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError =
+ List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->
+ psPowerDeviceList,
+ PVRSRVDevicePostPowerStateKM_AnyVaCb,
+ bAllDevices,
+ ui32DeviceIndex,
+ eNewPowerState);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSetDevicePowerStateCoreKM(u32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE
+ eNewPowerState)
+{
+ PVRSRV_ERROR eError;
+ eError =
+ PVRSRVDevicePrePowerStateKM(0, ui32DeviceIndex, eNewPowerState);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ eError =
+ PVRSRVDevicePostPowerStateKM(0, ui32DeviceIndex, eNewPowerState);
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(u32 ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE eNewPowerState,
+ u32 ui32CallerID, int bRetainMutex)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVPowerLock(ui32CallerID, 0);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+#if defined(PDUMP)
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) {
+
+ eError =
+ PVRSRVDevicePrePowerStateKM(0, ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON);
+ if (eError != PVRSRV_OK) {
+ goto Exit;
+ }
+
+ eError =
+ PVRSRVDevicePostPowerStateKM(0, ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_ON);
+
+ if (eError != PVRSRV_OK) {
+ goto Exit;
+ }
+
+ PDUMPSUSPEND();
+ }
+#endif
+
+ eError =
+ PVRSRVDevicePrePowerStateKM(0, ui32DeviceIndex, eNewPowerState);
+ if (eError != PVRSRV_OK) {
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) {
+ PDUMPRESUME();
+ }
+ goto Exit;
+ }
+
+ eError =
+ PVRSRVDevicePostPowerStateKM(0, ui32DeviceIndex, eNewPowerState);
+
+ if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT) {
+ PDUMPRESUME();
+ }
+
+Exit:
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x",
+ eNewPowerState, eError));
+ }
+
+ if (!bRetainMutex || (eError != PVRSRV_OK)) {
+ PVRSRVPowerUnlock(ui32CallerID);
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE
+ eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVPowerLock(KERNEL_ID, 1);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState)) {
+ if (_IsSystemStatePowered(eNewSysPowerState)) {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ } else {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+ eError =
+ PVRSRVDevicePrePowerStateKM(1, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+ }
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState) {
+
+ eError = SysSystemPrePowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+ }
+
+ return eError;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE
+ eNewSysPowerState)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
+
+ SysAcquireData(&psSysData);
+
+ if (eNewSysPowerState != psSysData->eCurrentPowerState) {
+
+ eError = SysSystemPostPowerState(eNewSysPowerState);
+ if (eError != PVRSRV_OK) {
+ goto Exit;
+ }
+ }
+
+ if (_IsSystemStatePowered(eNewSysPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState)) {
+ if (_IsSystemStatePowered(eNewSysPowerState)) {
+
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
+ } else {
+ eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
+ }
+
+ eError =
+ PVRSRVDevicePostPowerStateKM(1, 0, eNewDevicePowerState);
+ if (eError != PVRSRV_OK) {
+ goto Exit;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVSystemPostPowerStateKM: System Power Transition from %d to %d OK",
+ psSysData->eCurrentPowerState, eNewSysPowerState));
+
+ psSysData->eCurrentPowerState = eNewSysPowerState;
+
+Exit:
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+
+ if (_IsSystemStatePowered(eNewSysPowerState) &&
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL)) {
+
+ PVRSRVCommandCompleteCallbacks();
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ eError = PVRSRVSystemPrePowerStateKM(eNewSysPowerState);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+
+ eError = PVRSRVSystemPostPowerStateKM(eNewSysPowerState);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewSysPowerState, eError));
+
+ psSysData->eFailedPowerState = eNewSysPowerState;
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRegisterPowerDevice(u32 ui32DeviceIndex,
+ PFN_PRE_POWER pfnPrePower,
+ PFN_POST_POWER pfnPostPower,
+ PFN_PRE_CLOCKSPEED_CHANGE
+ pfnPreClockSpeedChange,
+ PFN_POST_CLOCKSPEED_CHANGE
+ pfnPostClockSpeedChange,
+ void *hDevCookie,
+ PVRSRV_DEV_POWER_STATE
+ eCurrentPowerState,
+ PVRSRV_DEV_POWER_STATE
+ eDefaultPowerState)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ if (pfnPrePower == NULL && pfnPostPower == NULL) {
+ return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+ }
+
+ SysAcquireData(&psSysData);
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_POWER_DEV),
+ (void **)&psPowerDevice, NULL, "Power Device");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterPowerDevice: Failed to alloc PVRSRV_POWER_DEV"));
+ return eError;
+ }
+
+ psPowerDevice->pfnPrePower = pfnPrePower;
+ psPowerDevice->pfnPostPower = pfnPostPower;
+ psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
+ psPowerDevice->pfnPostClockSpeedChange = pfnPostClockSpeedChange;
+ psPowerDevice->hDevCookie = hDevCookie;
+ psPowerDevice->ui32DeviceIndex = ui32DeviceIndex;
+ psPowerDevice->eCurrentPowerState = eCurrentPowerState;
+ psPowerDevice->eDefaultPowerState = eDefaultPowerState;
+
+ List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList),
+ psPowerDevice);
+
+ return (PVRSRV_OK);
+}
+
+PVRSRV_ERROR PVRSRVRemovePowerDevice(u32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDev;
+
+ SysAcquireData(&psSysData);
+
+ psPowerDev = (PVRSRV_POWER_DEV *)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDev) {
+ List_PVRSRV_POWER_DEV_Remove(psPowerDev);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV),
+ psPowerDev, NULL);
+
+ }
+
+ return (PVRSRV_OK);
+}
+
+int PVRSRVIsDevicePowered(u32 ui32DeviceIndex)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ SysAcquireData(&psSysData);
+
+ if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID)
+ || OSIsResourceLocked(&psSysData->sPowerStateChangeResource,
+ ISR_ID)) {
+ return 0;
+ }
+
+ psPowerDevice = (PVRSRV_POWER_DEV *)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+ return (psPowerDevice
+ && (psPowerDevice->eCurrentPowerState ==
+ PVRSRV_DEV_POWER_STATE_ON))
+ ? 1 : 0;
+}
+
+PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(u32 ui32DeviceIndex,
+ int bIdleDevice, void *pvInfo)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ SysAcquireData(&psSysData);
+
+ if (bIdleDevice) {
+
+ eError = PVRSRVPowerLock(KERNEL_ID, 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePreClockSpeedChange : failed to acquire lock, error:0x%lx",
+ eError));
+ return eError;
+ }
+ }
+
+ psPowerDevice = (PVRSRV_POWER_DEV *)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange) {
+ eError =
+ psPowerDevice->pfnPreClockSpeedChange(psPowerDevice->
+ hDevCookie,
+ bIdleDevice,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePreClockSpeedChange : Device %lu failed, error:0x%lx",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+ if (bIdleDevice && eError != PVRSRV_OK) {
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+
+ return eError;
+}
+
+void PVRSRVDevicePostClockSpeedChange(u32 ui32DeviceIndex,
+ int bIdleDevice, void *pvInfo)
+{
+ PVRSRV_ERROR eError;
+ SYS_DATA *psSysData;
+ PVRSRV_POWER_DEV *psPowerDevice;
+
+ SysAcquireData(&psSysData);
+
+ psPowerDevice = (PVRSRV_POWER_DEV *)
+ List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
+ MatchPowerDeviceIndex_AnyVaCb,
+ ui32DeviceIndex);
+
+ if (psPowerDevice && psPowerDevice->pfnPostClockSpeedChange) {
+ eError =
+ psPowerDevice->pfnPostClockSpeedChange(psPowerDevice->
+ hDevCookie,
+ bIdleDevice,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDevicePostClockSpeedChange : Device %lu failed, error:0x%lx",
+ ui32DeviceIndex, eError));
+ }
+ }
+
+ if (bIdleDevice) {
+
+ PVRSRVPowerUnlock(KERNEL_ID);
+ }
+}
diff --git a/drivers/staging/ice4100/sgx535/common/pvrsrv.c b/drivers/staging/ice4100/sgx535/common/pvrsrv.c
new file mode 100755
index 00000000000..bb486f9f0ef
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/pvrsrv.c
@@ -0,0 +1,1108 @@
+/**********************************************************************
+ *
+ * Copyright (c) 2009-2010 Intel Corporation.
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "ra.h"
+
+#include "pvrversion.h"
+
+#include "lists.h"
+
+#ifdef INTEL_D3_CHANGES
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+
+/* FIXME MLD */
+/* #include "pal.h" */
+
+#define GFX_MS_TO_JIFFIES(time_ms) msecs_to_jiffies((time_ms))
+#define WAIT_FOR_WRITE_OP_SYNC_TIMEOUT 10000
+
+DECLARE_WAIT_QUEUE_HEAD(render_wait_queue);
+
+static void WakeWriteOpSyncs(void)
+{
+ wake_up(&render_wait_queue);
+}
+
+PVRSRV_ERROR PVRSRVWaitForWriteOpSyncKM(PVRSRV_KERNEL_SYNC_INFO *
+ psKernelSyncInfo)
+{
+ int rc = 0;
+
+ if (NULL == psKernelSyncInfo) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ rc = wait_event_interruptible_timeout(render_wait_queue,
+ (psKernelSyncInfo->psSyncData->
+ ui32WriteOpsComplete >=
+ psKernelSyncInfo->psSyncData->
+ ui32WriteOpsPending),
+ GFX_MS_TO_JIFFIES
+ (WAIT_FOR_WRITE_OP_SYNC_TIMEOUT));
+
+ if (rc == 0) {
+ return PVRSRV_ERROR_TIMEOUT;
+ } else if (rc == -ERESTARTSYS) {
+ return PVRSRV_ERROR_RETRY;
+ }
+
+ return PVRSRV_OK;
+}
+
+#endif
+
+DECLARE_LIST_ANY_VA_2(BM_CONTEXT, PVRSRV_ERROR, PVRSRV_OK);
+
+DECLARE_LIST_FOR_EACH_VA(BM_HEAP);
+
+DECLARE_LIST_ANY_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_ANY_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_ANY_VA_2(PVRSRV_DEVICE_NODE, PVRSRV_ERROR, PVRSRV_OK);
+DECLARE_LIST_FOR_EACH_VA(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_INSERT(PVRSRV_DEVICE_NODE);
+DECLARE_LIST_REMOVE(PVRSRV_DEVICE_NODE);
+
+void *MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE * psDeviceNode, va_list va);
+
+PVRSRV_ERROR AllocateDeviceID(SYS_DATA * psSysData, u32 * pui32DevID)
+{
+ SYS_DEVICE_ID *psDeviceWalker;
+ SYS_DEVICE_ID *psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+ while (psDeviceWalker < psDeviceEnd) {
+ if (!psDeviceWalker->bInUse) {
+ psDeviceWalker->bInUse = 1;
+ *pui32DevID = psDeviceWalker->uiID;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocateDeviceID: No free and valid device IDs available!"));
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR FreeDeviceID(SYS_DATA * psSysData, u32 ui32DevID)
+{
+ SYS_DEVICE_ID *psDeviceWalker;
+ SYS_DEVICE_ID *psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+ while (psDeviceWalker < psDeviceEnd) {
+
+ if ((psDeviceWalker->uiID == ui32DevID) &&
+ (psDeviceWalker->bInUse)
+ ) {
+ psDeviceWalker->bInUse = 0;
+ return PVRSRV_OK;
+ }
+ psDeviceWalker++;
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "FreeDeviceID: no matching dev ID that is in use!"));
+
+ PVR_ASSERT(psDeviceWalker < psDeviceEnd);
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+#ifndef ReadHWReg
+
+u32 ReadHWReg(void *pvLinRegBaseAddr, u32 ui32Offset)
+{
+ return *(volatile u32 *)((u32) pvLinRegBaseAddr + ui32Offset);
+}
+#endif
+
+#ifndef WriteHWReg
+
+void WriteHWReg(void *pvLinRegBaseAddr, u32 ui32Offset, u32 ui32Value)
+{
+ PVR_DPF((PVR_DBG_MESSAGE, "WriteHWReg Base:%x, Offset: %x, Value %x",
+ pvLinRegBaseAddr, ui32Offset, ui32Value));
+
+ *(u32 *) ((u32) pvLinRegBaseAddr + ui32Offset) = ui32Value;
+}
+#endif
+
+#ifndef WriteHWRegs
+
+void WriteHWRegs(void *pvLinRegBaseAddr, u32 ui32Count, PVRSRV_HWREG * psHWRegs)
+{
+ while (ui32Count) {
+ WriteHWReg(pvLinRegBaseAddr, psHWRegs->ui32RegAddr,
+ psHWRegs->ui32RegVal);
+ psHWRegs++;
+ ui32Count--;
+ }
+}
+#endif
+
+void PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE * psDeviceNode,
+ va_list va)
+{
+ u32 *pui32DevCount;
+ PVRSRV_DEVICE_IDENTIFIER **ppsDevIdList;
+
+ pui32DevCount = va_arg(va, u32 *);
+ ppsDevIdList = va_arg(va, PVRSRV_DEVICE_IDENTIFIER **);
+
+ if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_EXT) {
+ *(*ppsDevIdList) = psDeviceNode->sDevId;
+ (*ppsDevIdList)++;
+ (*pui32DevCount)++;
+ }
+}
+
+PVRSRV_ERROR PVRSRVEnumerateDevicesKM(u32 * pui32NumDevices,
+ PVRSRV_DEVICE_IDENTIFIER * psDevIdList)
+{
+ SYS_DATA *psSysData;
+ u32 i;
+
+ if (!pui32NumDevices || !psDevIdList) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVEnumerateDevicesKM: Invalid params"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+ for (i = 0; i < PVRSRV_MAX_DEVICES; i++) {
+ psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+ }
+
+ *pui32NumDevices = 0;
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
+ PVRSRVEnumerateDevicesKM_ForEachVaCb,
+ pui32NumDevices, &psDevIdList);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+ eError = ResManInit();
+ if (eError != PVRSRV_OK) {
+ goto Error;
+ }
+
+ eError = PVRSRVPerProcessDataInit();
+ if (eError != PVRSRV_OK) {
+ goto Error;
+ }
+
+ eError = PVRSRVHandleInit();
+ if (eError != PVRSRV_OK) {
+ goto Error;
+ }
+
+ eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
+ if (eError != PVRSRV_OK) {
+ goto Error;
+ }
+
+ psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
+ psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT),
+ (void **)&psSysData->psGlobalEventObject, 0,
+ "Event Object") != PVRSRV_OK) {
+
+ goto Error;
+ }
+
+ if (OSEventObjectCreate
+ ("PVRSRV_GLOBAL_EVENTOBJECT",
+ psSysData->psGlobalEventObject) != PVRSRV_OK) {
+ goto Error;
+ }
+
+ return eError;
+
+Error:
+ PVRSRVDeInit(psSysData);
+ return eError;
+}
+
+void PVRSRVDeInit(PSYS_DATA psSysData)
+{
+ PVRSRV_ERROR eError;
+
+ if (psSysData == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
+ return;
+ }
+
+ if (psSysData->psGlobalEventObject) {
+ OSEventObjectDestroy(psSysData->psGlobalEventObject);
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_EVENTOBJECT),
+ psSysData->psGlobalEventObject, 0);
+ psSysData->psGlobalEventObject = NULL;
+ }
+
+ eError = PVRSRVHandleDeInit();
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDeInit: PVRSRVHandleDeInit failed"));
+ }
+
+ eError = PVRSRVPerProcessDataDeInit();
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDeInit: PVRSRVPerProcessDataDeInit failed"));
+ }
+
+ ResManDeInit();
+}
+
+PVRSRV_ERROR PVRSRVRegisterDevice(PSYS_DATA psSysData,
+ PVRSRV_ERROR(*pfnRegisterDevice)
+ (PVRSRV_DEVICE_NODE *),
+ u32 ui32SOCInterruptBit,
+ u32 * pui32DeviceIndex)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE),
+ (void **)&psDeviceNode, NULL,
+ "Device Node") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterDevice : Failed to alloc memory for psDeviceNode"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+ memset(psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE));
+
+ eError = pfnRegisterDevice(psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, NULL);
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterDevice : Failed to register device"));
+ return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
+ }
+
+ psDeviceNode->ui32RefCount = 1;
+ psDeviceNode->psSysData = psSysData;
+ psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
+
+ AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+
+ List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList,
+ psDeviceNode);
+
+ *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVInitialiseDevice(u32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice"));
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex, 1);
+ if (!psDeviceNode) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVInitialiseDevice: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+ PVR_ASSERT(psDeviceNode->ui32RefCount > 0);
+
+ eError = PVRSRVResManConnect(NULL, &psDeviceNode->hResManContext);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVInitialiseDevice: Failed PVRSRVResManConnect call"));
+ return eError;
+ }
+
+ if (psDeviceNode->pfnInitDevice != NULL) {
+ eError = psDeviceNode->pfnInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVInitialiseDevice: Failed InitDevice call"));
+ return eError;
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *
+ psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError =
+ PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_DEV_POWER_STATE_DEFAULT,
+ KERNEL_ID, 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)",
+ psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *
+ psDeviceNode)
+{
+ PVRSRV_ERROR eError;
+ eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVFinaliseSystem: Failed PVRSRVDevInitCompatCheck call (device index: %d)",
+ psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVFinaliseSystem(int bInitSuccessful)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem"));
+
+ SysAcquireData(&psSysData);
+
+ if (bInitSuccessful) {
+ eError = SysFinalise();
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVFinaliseSystem: SysFinalise failed (%d)",
+ eError));
+ return eError;
+ }
+
+ eError =
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->
+ psDeviceNodeList,
+ PVRSRVFinaliseSystem_SetPowerState_AnyCb);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ eError =
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->
+ psDeviceNodeList,
+ PVRSRVFinaliseSystem_CompatCheck_AnyCb);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+
+#if !defined(SUPPORT_PDUMP_DELAYED_INITPHASE_TERMINATION)
+ PDUMPENDINITPHASE();
+#endif
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+
+ if (psDeviceNode->pfnInitDeviceCompatCheck)
+ return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+ else
+ return PVRSRV_OK;
+}
+
+void *PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE * psDeviceNode,
+ va_list va)
+{
+ PVRSRV_DEVICE_TYPE eDeviceType;
+ u32 ui32DevIndex;
+
+ eDeviceType = va_arg(va, PVRSRV_DEVICE_TYPE);
+ ui32DevIndex = va_arg(va, u32);
+
+ if ((eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.eDeviceType == eDeviceType) ||
+ (eDeviceType == PVRSRV_DEVICE_TYPE_UNKNOWN &&
+ psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)) {
+ return psDeviceNode;
+ } else {
+ return NULL;
+ }
+}
+
+PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(u32 ui32DevIndex,
+ PVRSRV_DEVICE_TYPE eDeviceType,
+ void **phDevCookie)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+
+ PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM"));
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode =
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
+ eDeviceType, ui32DevIndex);
+
+ if (!psDeviceNode) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVAcquireDeviceDataKM: requested device is not present"));
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ PVR_ASSERT(psDeviceNode->ui32RefCount > 0);
+
+ if (phDevCookie) {
+ *phDevCookie = (void *)psDeviceNode;
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVDeinitialiseDevice(u32 ui32DevIndex)
+{
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+
+ SysAcquireData(&psSysData);
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)
+ List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
+ MatchDeviceKM_AnyVaCb,
+ ui32DevIndex, 1);
+
+ if (!psDeviceNode) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDeinitialiseDevice: requested device %d is not present",
+ ui32DevIndex));
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+ PVRSRV_DEV_POWER_STATE_OFF,
+ KERNEL_ID, 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
+ return eError;
+ }
+
+ eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
+ RESMAN_CRITERIA_RESTYPE,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ NULL, 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDeinitialiseDevice: Failed ResManFreeResByCriteria call"));
+ return eError;
+ }
+
+ if (psDeviceNode->pfnDeInitDevice != NULL) {
+ eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDeinitialiseDevice: Failed DeInitDevice call"));
+ return eError;
+ }
+ }
+
+ PVRSRVResManDisconnect(psDeviceNode->hResManContext, 1);
+ psDeviceNode->hResManContext = NULL;
+
+ List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
+
+ (void)FreeDeviceID(psSysData, ui32DevIndex);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, NULL);
+
+ return (PVRSRV_OK);
+}
+
+PVRSRV_ERROR PollForValueKM(volatile u32 * pui32LinMemAddr,
+ u32 ui32Value,
+ u32 ui32Mask, u32 ui32Waitus, u32 ui32Tries)
+{
+ {
+ u32 uiMaxTime = ui32Tries * ui32Waitus;
+
+ LOOP_UNTIL_TIMEOUT(uiMaxTime) {
+ if ((*pui32LinMemAddr & ui32Mask) == ui32Value) {
+ return PVRSRV_OK;
+ }
+ OSWaitus(ui32Waitus);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+#if defined (USING_ISR_INTERRUPTS)
+
+extern u32 gui32EventStatusServicesByISR;
+
+PVRSRV_ERROR PollForInterruptKM(u32 ui32Value,
+ u32 ui32Mask, u32 ui32Waitus, u32 ui32Tries)
+{
+ u32 uiMaxTime;
+
+ uiMaxTime = ui32Tries * ui32Waitus;
+
+ LOOP_UNTIL_TIMEOUT(uiMaxTime) {
+ if ((gui32EventStatusServicesByISR & ui32Mask) == ui32Value) {
+ gui32EventStatusServicesByISR = 0;
+ return PVRSRV_OK;
+ }
+ OSWaitus(ui32Waitus);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ return PVRSRV_ERROR_GENERIC;
+}
+#endif
+
+void PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP * psBMHeap, va_list va)
+{
+ char **ppszStr;
+ u32 *pui32StrLen;
+
+ ppszStr = va_arg(va, char **);
+ pui32StrLen = va_arg(va, u32 *);
+
+ if (psBMHeap->pImportArena) {
+ RA_GetStats(psBMHeap->pImportArena, ppszStr, pui32StrLen);
+ }
+
+ if (psBMHeap->pVMArena) {
+ RA_GetStats(psBMHeap->pVMArena, ppszStr, pui32StrLen);
+ }
+}
+
+PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT * psBMContext,
+ va_list va)
+{
+
+ u32 *pui32StrLen;
+ s32 *pi32Count;
+ char **ppszStr;
+
+ pui32StrLen = va_arg(va, u32 *);
+ pi32Count = va_arg(va, s32 *);
+ ppszStr = va_arg(va, char **);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count =
+ snprintf(*ppszStr, 100,
+ "\nApplication Context (hDevMemContext) 0x%08X:\n",
+ (void *)psBMContext);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ List_BM_HEAP_ForEach_va(psBMContext->psBMHeap,
+ PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr, pui32StrLen);
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *
+ psDeviceNode, va_list va)
+{
+ u32 *pui32StrLen;
+ s32 *pi32Count;
+ char **ppszStr;
+
+ pui32StrLen = va_arg(va, u32 *);
+ pi32Count = va_arg(va, s32 *);
+ ppszStr = va_arg(va, char **);
+
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count =
+ snprintf(*ppszStr, 100, "\n\nDevice Type %d:\n",
+ psDeviceNode->sDevId.eDeviceType);
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ if (psDeviceNode->sDevMemoryInfo.pBMKernelContext) {
+ CHECK_SPACE(*pui32StrLen);
+ *pi32Count = snprintf(*ppszStr, 100, "\nKernel Context:\n");
+ UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
+
+ List_BM_HEAP_ForEach_va(psDeviceNode->sDevMemoryInfo.
+ pBMKernelContext->psBMHeap,
+ PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb,
+ ppszStr, pui32StrLen);
+ }
+
+ return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.
+ pBMContext,
+ PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
+ pui32StrLen, pi32Count,
+ ppszStr);
+}
+
+PVRSRV_ERROR PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO * psMiscInfo)
+{
+ SYS_DATA *psSysData;
+
+ if (!psMiscInfo) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetMiscInfoKM: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psMiscInfo->ui32StatePresent = 0;
+
+ if (psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
+ |
+ PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
+ | PVRSRV_MISC_INFO_MEMSTATS_PRESENT
+ |
+ PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT
+ |
+ PVRSRV_MISC_INFO_DDKVERSION_PRESENT
+ |
+ PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT
+ | PVRSRV_MISC_INFO_RESET_PRESENT))
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVGetMiscInfoKM: invalid state request flags"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+ if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) !=
+ 0UL) && (psSysData->pvSOCTimerRegisterKM != NULL)) {
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_TIMER_PRESENT;
+ psMiscInfo->pvSOCTimerRegisterKM =
+ psSysData->pvSOCTimerRegisterKM;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle =
+ psSysData->hSOCTimerRegisterOSMemHandle;
+ } else {
+ psMiscInfo->pvSOCTimerRegisterKM = NULL;
+ psMiscInfo->hSOCTimerRegisterOSMemHandle = NULL;
+ }
+
+ if (((psMiscInfo->
+ ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL)
+ && (psSysData->pvSOCClockGateRegsBase != NULL)) {
+ psMiscInfo->ui32StatePresent |=
+ PVRSRV_MISC_INFO_CLOCKGATE_PRESENT;
+ psMiscInfo->pvSOCClockGateRegs =
+ psSysData->pvSOCClockGateRegsBase;
+ psMiscInfo->ui32SOCClockGateRegsSize =
+ psSysData->ui32SOCClockGateRegsSize;
+ }
+
+ if (((psMiscInfo->
+ ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL)
+ && (psMiscInfo->pszMemoryStr != NULL)) {
+ RA_ARENA **ppArena;
+ char *pszStr;
+ u32 ui32StrLen;
+ s32 i32Count;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ psMiscInfo->ui32StatePresent |=
+ PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
+
+ ppArena = &psSysData->apsLocalDevMemArena[0];
+ while (*ppArena) {
+ CHECK_SPACE(ui32StrLen);
+ i32Count =
+ snprintf(pszStr, 100, "\nLocal Backing Store:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ RA_GetStats(*ppArena, &pszStr, &ui32StrLen);
+
+ ppArena++;
+ }
+
+ List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->
+ psDeviceNodeList,
+ PVRSRVGetMiscInfoKM_Device_AnyVaCb,
+ &ui32StrLen,
+ &i32Count, &pszStr);
+
+ i32Count = snprintf(pszStr, 100, "\n\0");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if (((psMiscInfo->
+ ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT) !=
+ 0UL) && (psSysData->psGlobalEventObject != NULL)) {
+ psMiscInfo->ui32StatePresent |=
+ PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT;
+ psMiscInfo->sGlobalEventObject =
+ *psSysData->psGlobalEventObject;
+ }
+
+ if (((psMiscInfo->
+ ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
+ &&
+ ((psMiscInfo->
+ ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
+ && (psMiscInfo->pszMemoryStr != NULL)) {
+ char *pszStr;
+ u32 ui32StrLen;
+ u32 ui32LenStrPerNum = 12;
+ s32 i32Count;
+ int i;
+ psMiscInfo->ui32StatePresent |=
+ PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
+
+ psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
+ psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
+ psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
+ psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;
+
+ pszStr = psMiscInfo->pszMemoryStr;
+ ui32StrLen = psMiscInfo->ui32MemoryStrLen;
+
+ for (i = 0; i < 4; i++) {
+ if (ui32StrLen < ui32LenStrPerNum) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ i32Count =
+ snprintf(pszStr, ui32LenStrPerNum, "%d",
+ (s32) psMiscInfo->aui32DDKVersion[i]);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ if (i != 3) {
+ i32Count = snprintf(pszStr, 2, ".");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+ }
+ }
+#if defined(SUPPORT_CPU_CACHED_BUFFERS)
+ if ((psMiscInfo->
+ ui32StateRequest & PVRSRV_MISC_INFO_CPUCACHEFLUSH_PRESENT) !=
+ 0UL) {
+ if (psMiscInfo->bDeferCPUCacheFlush) {
+
+ if (!psMiscInfo->bCPUCacheFlushAll) {
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVGetMiscInfoKM: don't support deferred range flushes"));
+ PVR_DPF((PVR_DBG_MESSAGE,
+ " using deferred flush all instead"));
+ }
+
+ psSysData->bFlushAll = 1;
+ } else {
+
+ if (psMiscInfo->bCPUCacheFlushAll) {
+
+ OSFlushCPUCacheKM();
+
+ psSysData->bFlushAll = 0;
+ } else {
+
+ OSFlushCPUCacheRangeKM(psMiscInfo->
+ pvRangeAddrStart,
+ psMiscInfo->
+ pvRangeAddrEnd);
+ }
+ }
+ }
+#endif
+
+#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
+ if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) !=
+ 0UL) {
+ PVR_LOG(("User requested OS reset"));
+ OSPanic();
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVGetFBStatsKM(u32 * pui32Total, u32 * pui32Available)
+{
+ u32 ui32Total = 0, i = 0;
+ u32 ui32Available = 0;
+
+ *pui32Total = 0;
+ *pui32Available = 0;
+
+ while (BM_ContiguousStatistics(i, &ui32Total, &ui32Available) == 1) {
+ *pui32Total += ui32Total;
+ *pui32Available += ui32Available;
+
+ i++;
+ }
+
+ return PVRSRV_OK;
+}
+
+int PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+ SYS_DATA *psSysData;
+ int bStatus = 0;
+ u32 ui32InterruptSource;
+
+ if (!psDeviceNode) {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDeviceLISR: Invalid params\n"));
+ goto out;
+ }
+ psSysData = psDeviceNode->psSysData;
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
+ if (ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) {
+ if (psDeviceNode->pfnDeviceISR != NULL) {
+ bStatus =
+ (*psDeviceNode->pfnDeviceISR) (psDeviceNode->
+ pvISRData);
+ }
+
+ SysClearInterrupts(psSysData,
+ psDeviceNode->ui32SOCInterruptBit);
+ }
+
+out:
+ return bStatus;
+}
+
+void PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE * psDeviceNode, va_list va)
+{
+
+ int *pbStatus;
+ u32 *pui32InterruptSource;
+ u32 *pui32ClearInterrupts;
+
+ pbStatus = va_arg(va, int *);
+ pui32InterruptSource = va_arg(va, u32 *);
+ pui32ClearInterrupts = va_arg(va, u32 *);
+
+ if (psDeviceNode->pfnDeviceISR != NULL) {
+ if (*pui32InterruptSource & psDeviceNode->ui32SOCInterruptBit) {
+ if ((*psDeviceNode->pfnDeviceISR) (psDeviceNode->
+ pvISRData)) {
+
+ *pbStatus = 1;
+ }
+
+ *pui32ClearInterrupts |=
+ psDeviceNode->ui32SOCInterruptBit;
+ }
+ }
+}
+
+int PVRSRVSystemLISR(void *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ int bStatus = 0;
+ u32 ui32InterruptSource;
+ u32 ui32ClearInterrupts = 0;
+ if (!psSysData) {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+ } else {
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, NULL);
+
+ if (ui32InterruptSource) {
+
+ List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->
+ psDeviceNodeList,
+ PVRSRVSystemLISR_ForEachVaCb,
+ &bStatus,
+ &ui32InterruptSource,
+ &ui32ClearInterrupts);
+
+ SysClearInterrupts(psSysData, ui32ClearInterrupts);
+ }
+ }
+ return bStatus;
+}
+
+void PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+ if (psDeviceNode->pfnDeviceMISR != NULL) {
+ (*psDeviceNode->pfnDeviceMISR) (psDeviceNode->pvISRData);
+ }
+}
+
+void PVRSRVMISR(void *pvSysData)
+{
+ SYS_DATA *psSysData = pvSysData;
+ if (!psSysData) {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n"));
+ return;
+ }
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ PVRSRVMISR_ForEachCb);
+
+ if (PVRSRVProcessQueues(ISR_ID, 0) == PVRSRV_ERROR_PROCESSING_BLOCKED) {
+ PVRSRVProcessQueues(ISR_ID, 0);
+ }
+
+ if (psSysData->psGlobalEventObject) {
+ void *hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
+ if (hOSEventKM) {
+ OSEventObjectSignal(hOSEventKM);
+ }
+ }
+#ifdef INTEL_D3_CHANGES
+ WakeWriteOpSyncs();
+#endif
+}
+
+PVRSRV_ERROR PVRSRVProcessConnect(u32 ui32PID)
+{
+ return PVRSRVPerProcessDataConnect(ui32PID);
+}
+
+void PVRSRVProcessDisconnect(u32 ui32PID)
+{
+ PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+PVRSRV_ERROR PVRSRVSaveRestoreLiveSegments(void *hArena, IMG_PBYTE pbyBuffer,
+ u32 * puiBufSize, int bSave)
+{
+ u32 uiBytesSaved = 0;
+ void *pvLocalMemCPUVAddr;
+ RA_SEGMENT_DETAILS sSegDetails;
+
+ if (hArena == NULL) {
+ return (PVRSRV_ERROR_INVALID_PARAMS);
+ }
+
+ sSegDetails.uiSize = 0;
+ sSegDetails.sCpuPhyAddr.uiAddr = 0;
+ sSegDetails.hSegment = 0;
+
+ while (RA_GetNextLiveSegment(hArena, &sSegDetails)) {
+ if (pbyBuffer == NULL) {
+
+ uiBytesSaved +=
+ sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+ } else {
+ if ((uiBytesSaved + sizeof(sSegDetails.uiSize) +
+ sSegDetails.uiSize) > *puiBufSize) {
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x",
+ sSegDetails.sCpuPhyAddr.uiAddr,
+ sSegDetails.uiSize));
+
+ pvLocalMemCPUVAddr =
+ OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY |
+ PVRSRV_HAP_UNCACHED, NULL);
+ if (pvLocalMemCPUVAddr == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSaveRestoreLiveSegments: Failed to map local memory to host"));
+ return (PVRSRV_ERROR_OUT_OF_MEMORY);
+ }
+
+ if (bSave) {
+
+ memcpy(pbyBuffer, &sSegDetails.uiSize,
+ sizeof(sSegDetails.uiSize));
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ memcpy(pbyBuffer, pvLocalMemCPUVAddr,
+ sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ } else {
+ u32 uiSize;
+
+ memcpy(&uiSize, pbyBuffer,
+ sizeof(sSegDetails.uiSize));
+
+ if (uiSize != sSegDetails.uiSize) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVSaveRestoreLiveSegments: Segment size error"));
+ } else {
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ memcpy(pvLocalMemCPUVAddr, pbyBuffer,
+ sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ }
+
+ uiBytesSaved +=
+ sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+ OSUnMapPhysToLin(pvLocalMemCPUVAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY |
+ PVRSRV_HAP_UNCACHED, NULL);
+ }
+ }
+
+ if (pbyBuffer == NULL) {
+ *puiBufSize = uiBytesSaved;
+ }
+
+ return (PVRSRV_OK);
+}
diff --git a/drivers/staging/ice4100/sgx535/common/queue.c b/drivers/staging/ice4100/sgx535/common/queue.c
new file mode 100755
index 00000000000..10609208f07
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/queue.c
@@ -0,0 +1,1046 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+
+#include "lists.h"
+
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+
+#if defined(__linux__) && defined(__KERNEL__)
+
+#include "proc.h"
+
+static int
+QueuePrintCommands(PVRSRV_QUEUE_INFO * psQueue, char *buffer, size_t size)
+{
+ off_t off = 0;
+ int cmds = 0;
+ u32 ui32ReadOffset = psQueue->ui32ReadOffset;
+ u32 ui32WriteOffset = psQueue->ui32WriteOffset;
+ PVRSRV_COMMAND *psCmd;
+
+ while (ui32ReadOffset != ui32WriteOffset) {
+ psCmd =
+ (PVRSRV_COMMAND *) ((u32) psQueue->pvLinQueueKM +
+ ui32ReadOffset);
+
+ off =
+ printAppend(buffer, size, off,
+ "%p %p %5u %6u %3u %5u %2u %2u %3u \n",
+ psQueue, psCmd, psCmd->ui32ProcessID,
+ psCmd->CommandType, psCmd->ui32CmdSize,
+ psCmd->ui32DevIndex, psCmd->ui32DstSyncCount,
+ psCmd->ui32SrcSyncCount, psCmd->ui32DataSize);
+
+ ui32ReadOffset += psCmd->ui32CmdSize;
+ ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+ cmds++;
+ }
+ if (cmds == 0)
+ off = printAppend(buffer, size, off, "%p <empty>\n", psQueue);
+ return off;
+}
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+void ProcSeqShowQueue(struct seq_file *sfile, void *el)
+{
+ PVRSRV_QUEUE_INFO *psQueue = (PVRSRV_QUEUE_INFO *) el;
+ int cmds = 0;
+ u32 ui32ReadOffset;
+ u32 ui32WriteOffset;
+ PVRSRV_COMMAND *psCmd;
+
+ if (el == PVR_PROC_SEQ_START_TOKEN) {
+ seq_printf(sfile,
+ "Command Queues\n"
+ "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
+ return;
+ }
+
+ ui32ReadOffset = psQueue->ui32ReadOffset;
+ ui32WriteOffset = psQueue->ui32WriteOffset;
+
+ while (ui32ReadOffset != ui32WriteOffset) {
+ psCmd =
+ (PVRSRV_COMMAND *) ((u32) psQueue->pvLinQueueKM +
+ ui32ReadOffset);
+
+ seq_printf(sfile,
+ "%p %p %5u %6u %3u %5u %2u %2u %3u \n",
+ psQueue, psCmd, psCmd->ui32ProcessID,
+ psCmd->CommandType, psCmd->ui32CmdSize,
+ psCmd->ui32DevIndex, psCmd->ui32DstSyncCount,
+ psCmd->ui32SrcSyncCount, psCmd->ui32DataSize);
+
+ ui32ReadOffset += psCmd->ui32CmdSize;
+ ui32ReadOffset &= psQueue->ui32QueueSize - 1;
+ cmds++;
+ }
+
+ if (cmds == 0)
+ seq_printf(sfile, "%p <empty>\n", psQueue);
+}
+
+void *ProcSeqOff2ElementQueue(struct seq_file *sfile, loff_t off)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+
+ if (!off) {
+ return PVR_PROC_SEQ_START_TOKEN;
+ }
+
+ SysAcquireData(&psSysData);
+
+ for (psQueue = psSysData->psQueueList;
+ (((--off) > 0) && (psQueue != NULL));
+ psQueue = psQueue->psNextKM) ;
+ return psQueue;
+}
+
+#endif
+
+off_t QueuePrintQueues(char *buffer, size_t size, off_t off)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_QUEUE_INFO *psQueue;
+
+ SysAcquireData(&psSysData);
+
+ if (!off)
+ return printAppend(buffer, size, 0,
+ "Command Queues\n"
+ "Queue CmdPtr Pid Command Size DevInd DSC SSC #Data ...\n");
+
+ for (psQueue = psSysData->psQueueList;
+ (((--off) > 0) && (psQueue != NULL));
+ psQueue = psQueue->psNextKM) ;
+
+ return psQueue ? QueuePrintCommands(psQueue, buffer,
+ size) : END_OF_FILE;
+}
+#endif
+
+#define GET_SPACE_IN_CMDQ(psQueue) \
+ (((psQueue->ui32ReadOffset - psQueue->ui32WriteOffset) \
+ + (psQueue->ui32QueueSize - 1)) & (psQueue->ui32QueueSize - 1))
+
+#define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
+ psQueue->ui32WriteOffset = (psQueue->ui32WriteOffset + ui32Size) \
+ & (psQueue->ui32QueueSize - 1);
+
+#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
+ (ui32OpsComplete >= ui32OpsPending)
+
+DECLARE_LIST_FOR_EACH(PVRSRV_DEVICE_NODE);
+
+static void QueueDumpCmdComplete(COMMAND_COMPLETE_DATA * psCmdCompleteData,
+ u32 i, int bIsSrc)
+{
+ PVRSRV_SYNC_OBJECT *psSyncObject;
+
+ psSyncObject =
+ bIsSrc ? psCmdCompleteData->psSrcSync : psCmdCompleteData->
+ psDstSync;
+
+ if (psCmdCompleteData->bInUse) {
+ PVR_LOG(("\t%s %lu: ROC DevVAddr:0x%lX ROP:0x%lx ROC:0x%lx, WOC DevVAddr:0x%lX WOP:0x%lx WOC:0x%lx", bIsSrc ? "SRC" : "DEST", i, psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr, psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending, psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete, psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr, psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending, psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete));
+ } else {
+ PVR_LOG(("\t%s %lu: (Not in use)", bIsSrc ? "SRC" : "DEST", i));
+ }
+}
+
+static void QueueDumpDebugInfo_ForEachCb(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+ if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY) {
+ u32 i;
+ SYS_DATA *psSysData;
+ COMMAND_COMPLETE_DATA **ppsCmdCompleteData;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+
+ SysAcquireData(&psSysData);
+
+ ppsCmdCompleteData =
+ psSysData->ppsCmdCompleteData[psDeviceNode->sDevId.
+ ui32DeviceIndex];
+
+ if (ppsCmdCompleteData != NULL) {
+ psCmdCompleteData = ppsCmdCompleteData[DC_FLIP_COMMAND];
+
+ PVR_LOG(("Command Complete Data for display device %lu:", psDeviceNode->sDevId.ui32DeviceIndex));
+
+ for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount;
+ i++) {
+ QueueDumpCmdComplete(psCmdCompleteData, i, 1);
+ }
+
+ for (i = 0; i < psCmdCompleteData->ui32DstSyncCount;
+ i++) {
+ QueueDumpCmdComplete(psCmdCompleteData, i, 0);
+ }
+ } else {
+ PVR_LOG(("There is no Command Complete Data for display device %u", psDeviceNode->sDevId.ui32DeviceIndex));
+ }
+ }
+}
+
+void QueueDumpDebugInfo(void)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ QueueDumpDebugInfo_ForEachCb);
+}
+
+u32 NearestPower2(u32 ui32Value)
+{
+ u32 ui32Temp, ui32Result = 1;
+
+ if (!ui32Value)
+ return 0;
+
+ ui32Temp = ui32Value - 1;
+ while (ui32Temp) {
+ ui32Result <<= 1;
+ ui32Temp >>= 1;
+ }
+
+ return ui32Result;
+}
+
+PVRSRV_ERROR PVRSRVCreateCommandQueueKM(u32 ui32QueueSize,
+ PVRSRV_QUEUE_INFO ** ppsQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueueInfo;
+ u32 ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ void *hMemBlock;
+
+ SysAcquireData(&psSysData);
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ (void **)&psQueueInfo, &hMemBlock,
+ "Queue Info") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateCommandQueueKM: Failed to alloc queue struct"));
+ goto ErrorExit;
+ }
+ memset(psQueueInfo, 0, sizeof(PVRSRV_QUEUE_INFO));
+
+ psQueueInfo->hMemBlock[0] = hMemBlock;
+ psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
+ &psQueueInfo->pvLinQueueKM, &hMemBlock,
+ "Command Queue") != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVCreateCommandQueueKM: Failed to alloc queue buffer"));
+ goto ErrorExit;
+ }
+
+ psQueueInfo->hMemBlock[1] = hMemBlock;
+ psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
+
+ PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
+ PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
+
+ psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
+
+ if (psSysData->psQueueList == NULL) {
+ eError = OSCreateResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+ }
+
+ if (OSLockResource(&psSysData->sQProcessResource,
+ KERNEL_ID) != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+
+ psQueueInfo->psNextKM = psSysData->psQueueList;
+ psSysData->psQueueList = psQueueInfo;
+
+ if (OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID) !=
+ PVRSRV_OK) {
+ goto ErrorExit;
+ }
+
+ *ppsQueueInfo = psQueueInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psQueueInfo) {
+ if (psQueueInfo->pvLinQueueKM) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = NULL;
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo, psQueueInfo->hMemBlock[0]);
+
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+PVRSRV_ERROR PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO * psQueueInfo)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ int bTimeout = 1;
+
+ SysAcquireData(&psSysData);
+
+ psQueue = psSysData->psQueueList;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if (psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset) {
+ bTimeout = 0;
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout) {
+
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
+ eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
+ goto ErrorExit;
+ }
+
+ eError = OSLockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+
+ if (psQueue == psQueueInfo) {
+ psSysData->psQueueList = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ NearestPower2(psQueueInfo->ui32QueueSize) +
+ PVRSRV_MAX_CMD_SIZE, psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo, psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = NULL;
+ } else {
+ while (psQueue) {
+ if (psQueue->psNextKM == psQueueInfo) {
+ psQueue->psNextKM = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ psQueueInfo->pvLinQueueKM = NULL;
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+
+ psQueueInfo = NULL;
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if (!psQueue) {
+ eError =
+ OSUnlockResource(&psSysData->sQProcessResource,
+ KERNEL_ID);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrorExit;
+ }
+ }
+
+ eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+
+ if (psSysData->psQueueList == NULL) {
+ eError = OSDestroyResource(&psSysData->sQProcessResource);
+ if (eError != PVRSRV_OK) {
+ goto ErrorExit;
+ }
+ }
+
+ErrorExit:
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO * psQueue,
+ u32 ui32ParamSize, void **ppvSpace)
+{
+ int bTimeout = 1;
+
+ ui32ParamSize = (ui32ParamSize + 3) & 0xFFFFFFFC;
+
+ if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVGetQueueSpace: max command size is %d bytes",
+ PVRSRV_MAX_CMD_SIZE));
+ return PVRSRV_ERROR_CMD_TOO_BIG;
+ }
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize) {
+ bTimeout = 0;
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout == 1) {
+ *ppvSpace = NULL;
+
+ return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+ } else {
+ *ppvSpace =
+ (void *)((u32) psQueue->pvLinQueueUM +
+ psQueue->ui32WriteOffset);
+ }
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO * psQueue,
+ PVRSRV_COMMAND ** ppsCommand,
+ u32 ui32DevIndex,
+ u16 CommandType,
+ u32 ui32DstSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO * apsDstSync[],
+ u32 ui32SrcSyncCount,
+ PVRSRV_KERNEL_SYNC_INFO * apsSrcSync[],
+ u32 ui32DataByteSize)
+{
+ PVRSRV_ERROR eError;
+ PVRSRV_COMMAND *psCommand;
+ u32 ui32CommandSize;
+ u32 i;
+
+ ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
+
+ ui32CommandSize = sizeof(PVRSRV_COMMAND)
+ +
+ ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+ + ui32DataByteSize;
+
+ eError =
+ PVRSRVGetQueueSpaceKM(psQueue, ui32CommandSize,
+ (void **)&psCommand);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+
+ psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+ psCommand->ui32CmdSize = ui32CommandSize;
+ psCommand->ui32DevIndex = ui32DevIndex;
+ psCommand->CommandType = CommandType;
+ psCommand->ui32DstSyncCount = ui32DstSyncCount;
+ psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
+
+ psCommand->psDstSync =
+ (PVRSRV_SYNC_OBJECT *) (((u32) psCommand) + sizeof(PVRSRV_COMMAND));
+
+ psCommand->psSrcSync =
+ (PVRSRV_SYNC_OBJECT *) (((u32) psCommand->psDstSync)
+ +
+ (ui32DstSyncCount *
+ sizeof(PVRSRV_SYNC_OBJECT)));
+
+ psCommand->pvData = (PVRSRV_SYNC_OBJECT *) (((u32) psCommand->psSrcSync)
+ +
+ (ui32SrcSyncCount *
+ sizeof
+ (PVRSRV_SYNC_OBJECT)));
+ psCommand->ui32DataSize = ui32DataByteSize;
+
+ for (i = 0; i < ui32DstSyncCount; i++) {
+ psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
+ psCommand->psDstSync[i].ui32WriteOpsPending =
+ PVRSRVGetWriteOpsPending(apsDstSync[i], 0);
+ psCommand->psDstSync[i].ui32ReadOpsPending =
+ PVRSRVGetReadOpsPending(apsDstSync[i], 0);
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVInsertCommandKM: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i,
+ psCommand->psDstSync[i].psKernelSyncInfoKM->
+ sReadOpsCompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].psKernelSyncInfoKM->
+ sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psDstSync[i].ui32ReadOpsPending,
+ psCommand->psDstSync[i].ui32WriteOpsPending));
+ }
+
+ for (i = 0; i < ui32SrcSyncCount; i++) {
+ psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+ psCommand->psSrcSync[i].ui32WriteOpsPending =
+ PVRSRVGetWriteOpsPending(apsSrcSync[i], 1);
+ psCommand->psSrcSync[i].ui32ReadOpsPending =
+ PVRSRVGetReadOpsPending(apsSrcSync[i], 1);
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVInsertCommandKM: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i,
+ psCommand->psSrcSync[i].psKernelSyncInfoKM->
+ sReadOpsCompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].psKernelSyncInfoKM->
+ sWriteOpsCompleteDevVAddr.uiAddr,
+ psCommand->psSrcSync[i].ui32ReadOpsPending,
+ psCommand->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+ *ppsCommand = psCommand;
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO * psQueue,
+ PVRSRV_COMMAND * psCommand)
+{
+
+ if (psCommand->ui32DstSyncCount > 0) {
+ psCommand->psDstSync =
+ (PVRSRV_SYNC_OBJECT *) (((u32) psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset +
+ sizeof(PVRSRV_COMMAND));
+ }
+
+ if (psCommand->ui32SrcSyncCount > 0) {
+ psCommand->psSrcSync =
+ (PVRSRV_SYNC_OBJECT *) (((u32) psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset +
+ sizeof(PVRSRV_COMMAND)
+ +
+ (psCommand->ui32DstSyncCount *
+ sizeof(PVRSRV_SYNC_OBJECT)));
+ }
+
+ psCommand->pvData =
+ (PVRSRV_SYNC_OBJECT *) (((u32) psQueue->pvLinQueueKM)
+ + psQueue->ui32WriteOffset +
+ sizeof(PVRSRV_COMMAND)
+ +
+ (psCommand->ui32DstSyncCount *
+ sizeof(PVRSRV_SYNC_OBJECT))
+ +
+ (psCommand->ui32SrcSyncCount *
+ sizeof(PVRSRV_SYNC_OBJECT)));
+
+ UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
+
+ return PVRSRV_OK;
+}
+
+PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA * psSysData,
+ PVRSRV_COMMAND * psCommand, int bFlush)
+{
+ PVRSRV_SYNC_OBJECT *psWalkerObj;
+ PVRSRV_SYNC_OBJECT *psEndObj;
+ u32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ u32 ui32WriteOpsComplete;
+ u32 ui32ReadOpsComplete;
+
+ psWalkerObj = psCommand->psDstSync;
+ psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+ while (psWalkerObj < psEndObj) {
+ PVRSRV_SYNC_DATA *psSyncData =
+ psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+ ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending)) {
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete,
+ psWalkerObj->ui32WriteOpsPending)
+ || !SYNCOPS_STALE(ui32ReadOpsComplete,
+ psWalkerObj->
+ ui32ReadOpsPending)) {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+
+ psWalkerObj++;
+ }
+
+ psWalkerObj = psCommand->psSrcSync;
+ psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
+ while (psWalkerObj < psEndObj) {
+ PVRSRV_SYNC_DATA *psSyncData =
+ psWalkerObj->psKernelSyncInfoKM->psSyncData;
+
+ ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+ ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+ if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending)) {
+ if (!bFlush &&
+ SYNCOPS_STALE(ui32WriteOpsComplete,
+ psWalkerObj->ui32WriteOpsPending)
+ && SYNCOPS_STALE(ui32ReadOpsComplete,
+ psWalkerObj->ui32ReadOpsPending)) {
+ PVR_DPF((PVR_DBG_WARNING,
+ "PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+ psSyncData, ui32WriteOpsComplete,
+ psWalkerObj->ui32WriteOpsPending));
+ }
+
+ if (!bFlush ||
+ !SYNCOPS_STALE(ui32WriteOpsComplete,
+ psWalkerObj->ui32WriteOpsPending)
+ || !SYNCOPS_STALE(ui32ReadOpsComplete,
+ psWalkerObj->
+ ui32ReadOpsPending)) {
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+ }
+ psWalkerObj++;
+ }
+
+ if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVProcessCommand: invalid DeviceType 0x%x",
+ psCommand->ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psCmdCompleteData =
+ psSysData->ppsCmdCompleteData[psCommand->ui32DevIndex][psCommand->
+ CommandType];
+ if (psCmdCompleteData->bInUse) {
+
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ }
+
+ psCmdCompleteData->bInUse = 1;
+
+ psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+ for (i = 0; i < psCommand->ui32DstSyncCount; i++) {
+ psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVProcessCommand: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->
+ sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->
+ sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+ }
+
+ psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+ for (i = 0; i < psCommand->ui32SrcSyncCount; i++) {
+ psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVProcessCommand: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->
+ sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->
+ sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+ if (psSysData->
+ ppfnCmdProcList[psCommand->ui32DevIndex][psCommand->
+ CommandType] ((void *)
+ psCmdCompleteData,
+ psCommand->
+ ui32DataSize,
+ psCommand->
+ pvData) ==
+ 0) {
+
+ psCmdCompleteData->bInUse = 0;
+ eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+ return eError;
+}
+
+void PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+ if (psDeviceNode->bReProcessDeviceCommandComplete &&
+ psDeviceNode->pfnDeviceCommandComplete != NULL) {
+ (*psDeviceNode->pfnDeviceCommandComplete) (psDeviceNode);
+ }
+}
+
+PVRSRV_ERROR PVRSRVProcessQueues(u32 ui32CallerID, int bFlush)
+{
+ PVRSRV_QUEUE_INFO *psQueue;
+ SYS_DATA *psSysData;
+ PVRSRV_COMMAND *psCommand;
+ PVRSRV_ERROR eError;
+
+ SysAcquireData(&psSysData);
+
+ psSysData->bReProcessQueues = 0;
+
+ eError = OSLockResource(&psSysData->sQProcessResource, ui32CallerID);
+ if (eError != PVRSRV_OK) {
+
+ psSysData->bReProcessQueues = 1;
+
+ if (ui32CallerID == ISR_ID) {
+ if (bFlush) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVProcessQueues: Couldn't acquire queue processing lock for FLUSH"));
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVProcessQueues: Couldn't acquire queue processing lock"));
+ }
+ } else {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVProcessQueues: Queue processing lock-acquire failed when called from the Services driver."));
+ PVR_DPF((PVR_DBG_MESSAGE,
+ " This is due to MISR queue processing being interrupted by the Services driver."));
+ }
+
+ return PVRSRV_OK;
+ }
+
+ psQueue = psSysData->psQueueList;
+
+ if (!psQueue) {
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "No Queues installed - cannot process commands"));
+ }
+
+ if (bFlush) {
+ PVRSRVSetDCState(DC_STATE_FLUSH_COMMANDS);
+ }
+
+ while (psQueue) {
+ while (psQueue->ui32ReadOffset != psQueue->ui32WriteOffset) {
+ psCommand =
+ (PVRSRV_COMMAND *) ((u32) psQueue->pvLinQueueKM +
+ psQueue->ui32ReadOffset);
+
+ if (PVRSRVProcessCommand(psSysData, psCommand, bFlush)
+ == PVRSRV_OK) {
+
+ UPDATE_QUEUE_ROFF(psQueue,
+ psCommand->ui32CmdSize)
+
+ if (bFlush) {
+ continue;
+ }
+ }
+
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if (bFlush) {
+ PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
+ }
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ PVRSRVProcessQueues_ForEachCb);
+
+ OSUnlockResource(&psSysData->sQProcessResource, ui32CallerID);
+
+ if (psSysData->bReProcessQueues) {
+ return PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+
+ return PVRSRV_OK;
+}
+
+void PVRSRVCommandCompleteKM(void *hCmdCookie, int bScheduleMISR)
+{
+ u32 i;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData =
+ (COMMAND_COMPLETE_DATA *) hCmdCookie;
+ SYS_DATA *psSysData;
+
+ SysAcquireData(&psSysData);
+
+ for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++) {
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->
+ ui32WriteOpsComplete++;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVCommandCompleteKM: Dst %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->
+ sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->
+ sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
+ }
+
+ for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++) {
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->
+ ui32ReadOpsComplete++;
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "PVRSRVCommandCompleteKM: Src %lu RO-VA:0x%lx WO-VA:0x%lx ROP:0x%lx WOP:0x%lx",
+ i,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->
+ sReadOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->
+ sWriteOpsCompleteDevVAddr.uiAddr,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
+ }
+
+ psCmdCompleteData->bInUse = 0;
+
+ PVRSRVCommandCompleteCallbacks();
+
+#if defined(SYS_USING_INTERRUPTS)
+ if (bScheduleMISR) {
+ OSScheduleMISR(psSysData);
+ }
+#else
+#endif
+}
+
+void PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE * psDeviceNode)
+{
+ if (psDeviceNode->pfnDeviceCommandComplete != NULL) {
+
+ (*psDeviceNode->pfnDeviceCommandComplete) (psDeviceNode);
+ }
+}
+
+void PVRSRVCommandCompleteCallbacks(void)
+{
+ SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+
+ List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
+ PVRSRVCommandCompleteCallbacks_ForEachCb);
+}
+
+PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(u32 ui32DevIndex,
+ PFN_CMD_PROC * ppfnCmdProcList,
+ u32 ui32MaxSyncsPerCmd[][2],
+ u32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ PVRSRV_ERROR eError;
+ u32 i;
+ u32 ui32AllocSize;
+ PFN_CMD_PROC *ppfnCmdProc;
+ COMMAND_COMPLETE_DATA *psCmdCompleteData;
+
+ if (ui32DevIndex >= SYS_DEVICE_COUNT) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(PFN_CMD_PROC),
+ (void **)&psSysData->ppfnCmdProcList[ui32DevIndex],
+ NULL, "Internal Queue Info structure");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: Failed to alloc queue"));
+ return eError;
+ }
+
+ ppfnCmdProc = psSysData->ppfnCmdProcList[ui32DevIndex];
+
+ for (i = 0; i < ui32CmdCount; i++) {
+ ppfnCmdProc[i] = ppfnCmdProcList[i];
+ }
+
+ ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *);
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (void **)&psSysData->
+ ppsCmdCompleteData[ui32DevIndex], NULL,
+ "Array of Pointers for Command Store");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: Failed to alloc CC data"));
+ goto ErrorExit;
+ }
+
+ for (i = 0; i < ui32CmdCount; i++) {
+
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ + ((ui32MaxSyncsPerCmd[i][0]
+ + ui32MaxSyncsPerCmd[i][1])
+ * sizeof(PVRSRV_SYNC_OBJECT));
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (void **)&psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i], NULL,
+ "Command Complete Data");
+ if (eError != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: Failed to alloc cmd %d",
+ i));
+ goto ErrorExit;
+ }
+
+ memset(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00,
+ ui32AllocSize);
+
+ psCmdCompleteData =
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i];
+
+ psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT *)
+ (((u32) psCmdCompleteData)
+ + sizeof(COMMAND_COMPLETE_DATA));
+ psCmdCompleteData->psSrcSync = (PVRSRV_SYNC_OBJECT *)
+ (((u32) psCmdCompleteData->psDstSync)
+ + (sizeof(PVRSRV_SYNC_OBJECT) * ui32MaxSyncsPerCmd[i][0]));
+
+ psCmdCompleteData->ui32AllocSize = ui32AllocSize;
+ }
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psSysData->ppsCmdCompleteData[ui32DevIndex] != NULL) {
+ for (i = 0; i < ui32CmdCount; i++) {
+ if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
+ NULL) {
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ + ((ui32MaxSyncsPerCmd[i][0]
+ + ui32MaxSyncsPerCmd[i][1])
+ * sizeof(PVRSRV_SYNC_OBJECT));
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i],
+ NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i] =
+ NULL;
+ }
+ }
+ ui32AllocSize = ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize,
+ psSysData->ppsCmdCompleteData[ui32DevIndex], NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex] = NULL;
+ }
+
+ if (psSysData->ppfnCmdProcList[ui32DevIndex] != NULL) {
+ ui32AllocSize = ui32CmdCount * sizeof(PFN_CMD_PROC);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize,
+ psSysData->ppfnCmdProcList[ui32DevIndex], NULL);
+ psSysData->ppfnCmdProcList[ui32DevIndex] = NULL;
+ }
+
+ return eError;
+}
+
+PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(u32 ui32DevIndex, u32 ui32CmdCount)
+{
+ SYS_DATA *psSysData;
+ u32 i;
+
+ if (ui32DevIndex >= SYS_DEVICE_COUNT) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ SysAcquireData(&psSysData);
+
+ if (psSysData->ppsCmdCompleteData[ui32DevIndex] == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "PVRSRVRemoveCmdProcListKM: Invalid command array"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ } else {
+ for (i = 0; i < ui32CmdCount; i++) {
+
+ if (psSysData->ppsCmdCompleteData[ui32DevIndex][i] !=
+ NULL) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i]->
+ ui32AllocSize,
+ psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i],
+ NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i] =
+ NULL;
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(COMMAND_COMPLETE_DATA *),
+ psSysData->ppsCmdCompleteData[ui32DevIndex], NULL);
+ psSysData->ppsCmdCompleteData[ui32DevIndex] = NULL;
+ }
+
+ if (psSysData->ppfnCmdProcList[ui32DevIndex] != NULL) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(PFN_CMD_PROC),
+ psSysData->ppfnCmdProcList[ui32DevIndex], NULL);
+ psSysData->ppfnCmdProcList[ui32DevIndex] = NULL;
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/staging/ice4100/sgx535/common/ra.c b/drivers/staging/ice4100/sgx535/common/ra.c
new file mode 100755
index 00000000000..f51aea7a244
--- /dev/null
+++ b/drivers/staging/ice4100/sgx535/common/ra.c
@@ -0,0 +1,1889 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+#include "services_headers.h"
+#include "hash.h"
+#include "ra.h"
+#include "buffer_manager.h"
+#include "osfunc.h"
+
+#ifdef __linux__
+#include <linux/kernel.h>
+#include "proc.h"
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+#include <stdio.h>
+#endif
+
+#define MINIMUM_HASH_SIZE (64)
+
+#if defined(VALIDATE_ARENA_TEST)
+
+typedef enum RESOURCE_DESCRIPTOR_TAG {
+
+ RESOURCE_SPAN_LIVE = 10,
+ RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_START,
+ IMPORTED_RESOURCE_SPAN_LIVE,
+ IMPORTED_RESOURCE_SPAN_FREE,
+ IMPORTED_RESOURCE_SPAN_END,
+
+} RESOURCE_DESCRIPTOR;
+
+typedef enum RESOURCE_TYPE_TAG {
+
+ IMPORTED_RESOURCE_TYPE = 20,
+ NON_IMPORTED_RESOURCE_TYPE
+} RESOURCE_TYPE;
+
+static u32 ui32BoundaryTagID = 0;
+
+u32 ValidateArena(RA_ARENA * pArena);
+#endif
+
+struct _BT_ {
+ enum bt_type {
+ btt_span,
+ btt_free,
+ btt_live
+ } type;
+
+ u32 base;
+ u32 uSize;
+
+ struct _BT_ *pNextSegment;
+ struct _BT_ *pPrevSegment;
+
+ struct _BT_ *pNextFree;
+ struct _BT_ *pPrevFree;
+
+ BM_MAPPING *psMapping;
+
+#if defined(VALIDATE_ARENA_TEST)
+ RESOURCE_DESCRIPTOR eResourceSpan;
+ RESOURCE_TYPE eResourceType;
+
+ u32 ui32BoundaryTagID;
+#endif
+
+};
+typedef struct _BT_ BT;
+
+struct _RA_ARENA_ {
+
+ char *name;
+
+ u32 uQuantum;
+
+ int (*pImportAlloc) (void *,
+ u32 uSize,
+ u32 * pActualSize,
+ BM_MAPPING ** ppsMapping, u32 uFlags, u32 * pBase);
+ void (*pImportFree) (void *, u32, BM_MAPPING * psMapping);
+ void (*pBackingStoreFree) (void *, u32, u32, void *);
+
+ void *pImportHandle;
+
+#define FREE_TABLE_LIMIT 32
+
+ BT *aHeadFree[FREE_TABLE_LIMIT];
+
+ BT *pHeadSegment;
+ BT *pTailSegment;
+
+ HASH_TABLE *pSegmentHash;
+
+#ifdef RA_STATS
+ RA_STATISTICS sStatistics;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+#define PROC_NAME_SIZE 32
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+ struct proc_dir_entry *pProcInfo;
+ struct proc_dir_entry *pProcSegs;
+#else
+ char szProcInfoName[PROC_NAME_SIZE];
+ char szProcSegsName[PROC_NAME_SIZE];
+#endif
+
+ int bInitProcEntry;
+#endif
+};
+#if defined(ENABLE_RA_DUMP)
+void RA_Dump(RA_ARENA * pArena);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+
+#ifdef PVR_PROC_USE_SEQ_FILE
+
+static void RA_ProcSeqShowInfo(struct seq_file *sfile, void *el);
+static void *RA_ProcSeqOff2ElementInfo(struct seq_file *sfile, loff_t off);
+
+static void RA_ProcSeqShowRegs(struct seq_file *sfile, void *el);
+static void *RA_ProcSeqOff2ElementRegs(struct seq_file *sfile, loff_t off);
+
+#else
+static int
+RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
+ void *data);
+static int RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
+ void *data);
+#endif
+
+#endif
+
+#ifdef USE_BM_FREESPACE_CHECK
+void CheckBMFreespace(void);
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(DEBUG)
+static char *ReplaceSpaces(char *const pS)
+{
+ char *pT;
+
+ for (pT = pS; *pT != 0; pT++) {
+ if (*pT == ' ' || *pT == '\t') {
+ *pT = '_';
+ }
+ }
+
+ return pS;
+}
+#endif
+
+static int
+_RequestAllocFail(void *_h,
+ u32 _uSize,
+ u32 * _pActualSize,
+ BM_MAPPING ** _ppsMapping, u32 _uFlags, u32 * _pBase)
+{
+ return 0;
+}
+
+static u32 pvr_log2(u32 n)
+{
+ u32 l = 0;
+ n >>= 1;
+ while (n > 0) {
+ n >>= 1;
+ l++;
+ }
+ return l;
+}
+
+static PVRSRV_ERROR
+_SegmentListInsertAfter(RA_ARENA * pArena, BT * pInsertionPoint, BT * pBT)
+{
+ PVR_ASSERT(pArena != NULL);
+ PVR_ASSERT(pInsertionPoint != NULL);
+
+ if ((pInsertionPoint == NULL) || (pArena == NULL)) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_SegmentListInsertAfter: invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pBT->pNextSegment = pInsertionPoint->pNextSegment;
+ pBT->pPrevSegment = pInsertionPoint;
+ if (pInsertionPoint->pNextSegment == NULL)
+ pArena->pTailSegment = pBT;
+ else
+ pInsertionPoint->pNextSegment->pPrevSegment = pBT;
+ pInsertionPoint->pNextSegment = pBT;
+
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR _SegmentListInsert(RA_ARENA * pArena, BT * pBT)
+{
+ PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (pArena->pHeadSegment == NULL) {
+ pArena->pHeadSegment = pArena->pTailSegment = pBT;
+ pBT->pNextSegment = pBT->pPrevSegment = NULL;
+ } else {
+ BT *pBTScan;
+
+ if (pBT->base < pArena->pHeadSegment->base) {
+
+ pBT->pNextSegment = pArena->pHeadSegment;
+ pArena->pHeadSegment->pPrevSegment = pBT;
+ pArena->pHeadSegment = pBT;
+ pBT->pPrevSegment = NULL;
+ } else {
+
+ pBTScan = pArena->pHeadSegment;
+
+ while ((pBTScan->pNextSegment != NULL)
+ && (pBT->base >= pBTScan->pNextSegment->base)) {
+ pBTScan = pBTScan->pNextSegment;
+ }
+
+ eError = _SegmentListInsertAfter(pArena, pBTScan, pBT);
+ if (eError != PVRSRV_OK) {
+ return eError;
+ }
+ }
+ }
+ return eError;
+}
+
+static void _SegmentListRemove(RA_ARENA * pArena, BT * pBT)
+{
+ if (pBT->pPrevSegment == NULL)
+ pArena->pHeadSegment = pBT->pNextSegment;
+ else
+ pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
+
+ if (pBT->pNextSegment == NULL)
+ pArena->pTailSegment = pBT->pPrevSegment;
+ else
+ pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
+}
+
+static BT *_SegmentSplit(RA_ARENA * pArena, BT * pBT, u32 uSize)
+{
+ BT *pNeighbour;
+
+ PVR_ASSERT(pArena != NULL);
+
+ if (pArena == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_SegmentSplit: invalid parameter - pArena"));
+ return NULL;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (void **)&pNeighbour, NULL,
+ "Boundary Tag") != PVRSRV_OK) {
+ return NULL;
+ }
+
+ memset(pNeighbour, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pNeighbour->pPrevSegment = pBT;
+ pNeighbour->pNextSegment = pBT->pNextSegment;
+ if (pBT->pNextSegment == NULL)
+ pArena->pTailSegment = pNeighbour;
+ else
+ pBT->pNextSegment->pPrevSegment = pNeighbour;
+ pBT->pNextSegment = pNeighbour;
+
+ pNeighbour->type = btt_free;
+ pNeighbour->uSize = pBT->uSize - uSize;
+ pNeighbour->base = pBT->base + uSize;
+ pNeighbour->psMapping = pBT->psMapping;
+ pBT->uSize = uSize;
+
+#if defined(VALIDATE_ARENA_TEST)
+ if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE) {
+ pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ } else if (pNeighbour->pPrevSegment->eResourceType ==
+ NON_IMPORTED_RESOURCE_TYPE) {
+ pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+ pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
+ } else {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
+ PVR_DBG_BREAK;
+ }
+#endif
+
+ return pNeighbour;
+}
+
+static void _FreeListInsert(RA_ARENA * pArena, BT * pBT)
+{
+ u32 uIndex;
+ uIndex = pvr_log2(pBT->uSize);
+ pBT->type = btt_free;
+ pBT->pNextFree = pArena->aHeadFree[uIndex];
+ pBT->pPrevFree = NULL;
+ if (pArena->aHeadFree[uIndex] != NULL)
+ pArena->aHeadFree[uIndex]->pPrevFree = pBT;
+ pArena->aHeadFree[uIndex] = pBT;
+}
+
+static void _FreeListRemove(RA_ARENA * pArena, BT * pBT)
+{
+ u32 uIndex;
+ uIndex = pvr_log2(pBT->uSize);
+ if (pBT->pNextFree != NULL)
+ pBT->pNextFree->pPrevFree = pBT->pPrevFree;
+ if (pBT->pPrevFree == NULL)
+ pArena->aHeadFree[uIndex] = pBT->pNextFree;
+ else
+ pBT->pPrevFree->pNextFree = pBT->pNextFree;
+}
+
+static BT *_BuildSpanMarker(u32 base, u32 uSize)
+{
+ BT *pBT;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (void **)&pBT, NULL, "Boundary Tag") != PVRSRV_OK) {
+ return NULL;
+ }
+
+ memset(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_span;
+ pBT->base = base;
+ pBT->uSize = uSize;
+ pBT->psMapping = NULL;
+
+ return pBT;
+}
+
+static BT *_BuildBT(u32 base, u32 uSize)
+{
+ BT *pBT;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(BT),
+ (void **)&pBT, NULL, "Boundary Tag") != PVRSRV_OK) {
+ return NULL;
+ }
+
+ memset(pBT, 0, sizeof(BT));
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
+#endif
+
+ pBT->type = btt_free;
+ pBT->base = base;
+ pBT->uSize = uSize;
+
+ return pBT;
+}
+
+static BT *_InsertResource(RA_ARENA * pArena, u32 base, u32 uSize)
+{
+ BT *pBT;
+ PVR_ASSERT(pArena != NULL);
+ if (pArena == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_InsertResource: invalid parameter - pArena"));
+ return NULL;
+ }
+
+ pBT = _BuildBT(base, uSize);
+ if (pBT != NULL) {
+
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = RESOURCE_SPAN_FREE;
+ pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
+#endif
+
+ if (_SegmentListInsert(pArena, pBT) != PVRSRV_OK) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_InsertResource: call to _SegmentListInsert failed"));
+ return NULL;
+ }
+ _FreeListInsert(pArena, pBT);
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount += uSize;
+ pArena->sStatistics.uFreeResourceCount += uSize;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ }
+ return pBT;
+}
+
+static BT *_InsertResourceSpan(RA_ARENA * pArena, u32 base, u32 uSize)
+{
+ PVRSRV_ERROR eError;
+ BT *pSpanStart;
+ BT *pSpanEnd;
+ BT *pBT;
+
+ PVR_ASSERT(pArena != NULL);
+ if (pArena == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_InsertResourceSpan: invalid parameter - pArena"));
+ return NULL;
+ }
+
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
+ pArena->name, base, uSize));
+
+ pSpanStart = _BuildSpanMarker(base, uSize);
+ if (pSpanStart == NULL) {
+ goto fail_start;
+ }
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
+ pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pSpanEnd = _BuildSpanMarker(base + uSize, 0);
+ if (pSpanEnd == NULL) {
+ goto fail_end;
+ }
+#if defined(VALIDATE_ARENA_TEST)
+ pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
+ pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ pBT = _BuildBT(base, uSize);
+ if (pBT == NULL) {
+ goto fail_bt;
+ }
+#if defined(VALIDATE_ARENA_TEST)
+ pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
+ pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
+#endif
+
+ eError = _SegmentListInsert(pArena, pSpanStart);
+ if (eError != PVRSRV_OK) {
+ goto fail_SegListInsert;
+ }
+
+ eError = _SegmentListInsertAfter(pArena, pSpanStart, pBT);
+ if (eError != PVRSRV_OK) {
+ goto fail_SegListInsert;
+ }
+
+ _FreeListInsert(pArena, pBT);
+
+ eError = _SegmentListInsertAfter(pArena, pBT, pSpanEnd);
+ if (eError != PVRSRV_OK) {
+ goto fail_SegListInsert;
+ }
+#ifdef RA_STATS
+ pArena->sStatistics.uTotalResourceCount += uSize;
+#endif
+ return pBT;
+
+fail_SegListInsert:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, NULL);
+
+fail_bt:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, NULL);
+
+fail_end:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, NULL);
+
+fail_start:
+ return NULL;
+}
+
+static void _FreeBT(RA_ARENA * pArena, BT * pBT, int bFreeBackingStore)
+{
+ BT *pNeighbour;
+ u32 uOrigBase;
+ u32 uOrigSize;
+
+ PVR_ASSERT(pArena != NULL);
+ PVR_ASSERT(pBT != NULL);
+
+ if ((pArena == NULL) || (pBT == NULL)) {
+ PVR_DPF((PVR_DBG_ERROR, "_FreeBT: invalid parameter"));
+ return;
+ }
+#ifdef RA_STATS
+ pArena->sStatistics.uLiveSegmentCount--;
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount += pBT->uSize;
+#endif
+
+ uOrigBase = pBT->base;
+ uOrigSize = pBT->uSize;
+
+ pNeighbour = pBT->pPrevSegment;
+ if (pNeighbour != NULL
+ && pNeighbour->type == btt_free
+ && pNeighbour->base + pNeighbour->uSize == pBT->base) {
+ _FreeListRemove(pArena, pNeighbour);
+ _SegmentListRemove(pArena, pNeighbour);
+ pBT->base = pNeighbour->base;
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour,
+ NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+ pNeighbour = pBT->pNextSegment;
+ if (pNeighbour != NULL
+ && pNeighbour->type == btt_free
+ && pBT->base + pBT->uSize == pNeighbour->base) {
+ _FreeListRemove(pArena, pNeighbour);
+ _SegmentListRemove(pArena, pNeighbour);
+ pBT->uSize += pNeighbour->uSize;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour,
+ NULL);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount--;
+#endif
+ }
+
+ if (pArena->pBackingStoreFree != NULL && bFreeBackingStore) {
+ u32 uRoundedStart, uRoundedEnd;
+
+ uRoundedStart =
+ (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedStart < pBT->base) {
+ uRoundedStart += pArena->uQuantum;
+ }
+
+ uRoundedEnd =
+ ((uOrigBase + uOrigSize + pArena->uQuantum -
+ 1) / pArena->uQuantum) * pArena->uQuantum;
+
+ if (uRoundedEnd > (pBT->base + pBT->uSize)) {
+ uRoundedEnd -= pArena->uQuantum;
+ }
+
+ if (uRoundedStart < uRoundedEnd) {
+ pArena->pBackingStoreFree(pArena->pImportHandle,
+ uRoundedStart, uRoundedEnd,
+ (void *)0);
+ }
+ }
+
+ if (pBT->pNextSegment != NULL && pBT->pNextSegment->type == btt_span
+ && pBT->pPrevSegment != NULL && pBT->pPrevSegment->type == btt_span)
+ {
+ BT *next = pBT->pNextSegment;
+ BT *prev = pBT->pPrevSegment;
+ _SegmentListRemove(pArena, next);
+ _SegmentListRemove(pArena, prev);
+ _SegmentListRemove(pArena, pBT);
+ pArena->pImportFree(pArena->pImportHandle, pBT->base,
+ pBT->psMapping);
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+ pArena->sStatistics.uExportCount++;
+ pArena->sStatistics.uFreeSegmentCount--;
+ pArena->sStatistics.uFreeResourceCount -= pBT->uSize;
+ pArena->sStatistics.uTotalResourceCount -= pBT->uSize;
+#endif
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, NULL);
+
+ } else
+ _FreeListInsert(pArena, pBT);
+}
+
+static int
+_AttemptAllocAligned(RA_ARENA * pArena,
+ u32 uSize,
+ BM_MAPPING ** ppsMapping,
+ u32 uFlags,
+ u32 uAlignment, u32 uAlignmentOffset, u32 * base)
+{
+ u32 uIndex;
+ PVR_ASSERT(pArena != NULL);
+ if (pArena == NULL) {
+ PVR_DPF((PVR_DBG_ERROR,
+ "_AttemptAllocAligned: invalid parameter - pArena"));
+ return 0;
+ }
+
+ if (uAlignment > 1)
+ uAlignmentOffset %= uAlignment;
+
+ uIndex = pvr_log2(uSize);
+
+#if 0
+
+ if (1u << uIndex < uSize)
+ uIndex++;
+#endif
+
+ while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex] == NULL)
+ uIndex++;
+
+ while (uIndex < FREE_TABLE_LIMIT) {
+ if (pArena->aHeadFree[uIndex] != NULL) {
+
+ BT *pBT;
+
+ pBT = pArena->aHeadFree[uIndex];
+ while (pBT != NULL) {
+ u32 aligned_base;
+
+ if (uAlignment > 1)
+ aligned_base =
+ (pBT->base + uAlignmentOffset +
+ uAlignment -
+ 1) / uAlignment * uAlignment -
+ uAlignmentOffset;
+ else
+ aligned_base = pBT->base;
+ PVR_DPF((PVR_DBG_MESSAGE,
+ "RA_AttemptAllocAligned: pBT-base=0x%x "
+ "pBT-size=0x%x alignedbase=0x%x size=0x%x",
+ pBT->base, pBT->uSize, aligned_base,
+ uSize));
+
+ if (pBT->base + pBT->uSize >=
+ aligned_base + uSize) {
+ if (!pBT->psMapping
+ || pBT->psMapping->ui32Flags ==
+ uFlags) {
+ _FreeListRemove(pArena, pBT);
+
+ PVR_ASSERT(pBT->type ==
+ btt_free);