aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathieu J. Poirier <mathieu.poirier@linaro.org>2011-09-18 11:37:01 -0600
committerMathieu J. Poirier <mathieu.poirier@linaro.org>2011-09-18 11:37:01 -0600
commitaa8366e08836ece21fe8dcee87f6065ca7cb9d1c (patch)
treea85e8ed1547f0b4f3609a3b4a5c4829fef055067
parent6242e334ff8a9f1651c2515535d98485e343dcb1 (diff)
parentae2294a089c4c2289b8ad4c18447d45c439e8db1 (diff)
Merge branch 'meego-device-adaptation.n9xx-v3.0-wip' into new-oneiric-meego-merge.sept18
-rw-r--r--arch/arm/configs/meego_n9xx_defconfig2456
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c48
-rw-r--r--arch/arm/mach-omap2/board-rx51-video.c19
-rw-r--r--arch/arm/plat-omap/omap-pm-noop.c1
-rw-r--r--drivers/gpu/Makefile2
-rw-r--r--drivers/gpu/pvr/COPYING351
-rw-r--r--drivers/gpu/pvr/Kconfig55
-rw-r--r--drivers/gpu/pvr/Makefile44
-rw-r--r--drivers/gpu/pvr/README27
-rw-r--r--drivers/gpu/pvr/bridged_pvr_bridge.c3341
-rw-r--r--drivers/gpu/pvr/bridged_pvr_bridge.h158
-rw-r--r--drivers/gpu/pvr/bridged_sgx_bridge.c1871
-rw-r--r--drivers/gpu/pvr/bridged_sgx_bridge.h167
-rw-r--r--drivers/gpu/pvr/bridged_support.c77
-rw-r--r--drivers/gpu/pvr/bridged_support.h35
-rw-r--r--drivers/gpu/pvr/buffer_manager.c1493
-rw-r--r--drivers/gpu/pvr/buffer_manager.h171
-rw-r--r--drivers/gpu/pvr/bufferclass_example.c266
-rw-r--r--drivers/gpu/pvr/bufferclass_example.h104
-rw-r--r--drivers/gpu/pvr/bufferclass_example_linux.c202
-rw-r--r--drivers/gpu/pvr/bufferclass_example_linux.h46
-rw-r--r--drivers/gpu/pvr/bufferclass_example_private.c194
-rw-r--r--drivers/gpu/pvr/bufferclass_example_private.h33
-rw-r--r--drivers/gpu/pvr/dbgdrvif.h318
-rw-r--r--drivers/gpu/pvr/device.h187
-rw-r--r--drivers/gpu/pvr/deviceclass.c1522
-rw-r--r--drivers/gpu/pvr/devicemem.c1208
-rw-r--r--drivers/gpu/pvr/env_data.h57
-rw-r--r--drivers/gpu/pvr/env_perproc.h51
-rw-r--r--drivers/gpu/pvr/event.c274
-rw-r--r--drivers/gpu/pvr/event.h35
-rw-r--r--drivers/gpu/pvr/handle.c1442
-rw-r--r--drivers/gpu/pvr/handle.h150
-rw-r--r--drivers/gpu/pvr/hash.c379
-rw-r--r--drivers/gpu/pvr/hash.h51
-rw-r--r--drivers/gpu/pvr/img_defs.h46
-rw-r--r--drivers/gpu/pvr/img_types.h69
-rw-r--r--drivers/gpu/pvr/ioctldef.h93
-rw-r--r--drivers/gpu/pvr/kernelbuffer.h55
-rw-r--r--drivers/gpu/pvr/kerneldisplay.h104
-rw-r--r--drivers/gpu/pvr/mem.c130
-rw-r--r--drivers/gpu/pvr/mm.c1499
-rw-r--r--drivers/gpu/pvr/mm.h261
-rw-r--r--drivers/gpu/pvr/mmap.c920
-rw-r--r--drivers/gpu/pvr/mmap.h74
-rw-r--r--drivers/gpu/pvr/mmu.c1439
-rw-r--r--drivers/gpu/pvr/mmu.h86
-rw-r--r--drivers/gpu/pvr/module.c294
-rw-r--r--drivers/gpu/pvr/mutils.h37
-rw-r--r--drivers/gpu/pvr/ocpdefs.h294
-rw-r--r--drivers/gpu/pvr/oemfuncs.h41
-rw-r--r--drivers/gpu/pvr/omaplfb.h140
-rw-r--r--drivers/gpu/pvr/omaplfb_displayclass.c820
-rw-r--r--drivers/gpu/pvr/omaplfb_linux.c168
-rw-r--r--drivers/gpu/pvr/osfunc.c1498
-rw-r--r--drivers/gpu/pvr/osfunc.h216
-rw-r--r--drivers/gpu/pvr/osperproc.c84
-rw-r--r--drivers/gpu/pvr/osperproc.h36
-rw-r--r--drivers/gpu/pvr/pb.c419
-rw-r--r--drivers/gpu/pvr/pdump.c1271
-rw-r--r--drivers/gpu/pvr/pdump_common.c237
-rw-r--r--drivers/gpu/pvr/pdump_km.h268
-rw-r--r--drivers/gpu/pvr/pdumpdefs.h92
-rw-r--r--drivers/gpu/pvr/perproc.c266
-rw-r--r--drivers/gpu/pvr/perproc.h79
-rw-r--r--drivers/gpu/pvr/power.c559
-rw-r--r--drivers/gpu/pvr/power.h97
-rw-r--r--drivers/gpu/pvr/private_data.h42
-rw-r--r--drivers/gpu/pvr/proc.c421
-rw-r--r--drivers/gpu/pvr/proc.h54
-rw-r--r--drivers/gpu/pvr/pvr_bridge.h1107
-rw-r--r--drivers/gpu/pvr/pvr_bridge_k.c241
-rw-r--r--drivers/gpu/pvr/pvr_bridge_km.h222
-rw-r--r--drivers/gpu/pvr/pvr_debug.c358
-rw-r--r--drivers/gpu/pvr/pvr_debug.h110
-rw-r--r--drivers/gpu/pvr/pvr_events.c303
-rw-r--r--drivers/gpu/pvr/pvr_events.h99
-rw-r--r--drivers/gpu/pvr/pvrconfig.h35
-rw-r--r--drivers/gpu/pvr/pvrmmap.h36
-rw-r--r--drivers/gpu/pvr/pvrmodule.h31
-rw-r--r--drivers/gpu/pvr/pvrsrv.c921
-rw-r--r--drivers/gpu/pvr/pvrversion.h37
-rw-r--r--drivers/gpu/pvr/queue.c761
-rw-r--r--drivers/gpu/pvr/queue.h81
-rw-r--r--drivers/gpu/pvr/ra.c1164
-rw-r--r--drivers/gpu/pvr/ra.h107
-rw-r--r--drivers/gpu/pvr/resman.c568
-rw-r--r--drivers/gpu/pvr/resman.h95
-rw-r--r--drivers/gpu/pvr/services.h237
-rw-r--r--drivers/gpu/pvr/services_headers.h42
-rw-r--r--drivers/gpu/pvr/servicesext.h435
-rw-r--r--drivers/gpu/pvr/servicesint.h181
-rw-r--r--drivers/gpu/pvr/sgx530defs.h471
-rw-r--r--drivers/gpu/pvr/sgx_bridge.h397
-rw-r--r--drivers/gpu/pvr/sgx_bridge_km.h109
-rw-r--r--drivers/gpu/pvr/sgx_options.h178
-rw-r--r--drivers/gpu/pvr/sgxapi_km.h238
-rw-r--r--drivers/gpu/pvr/sgxconfig.h75
-rw-r--r--drivers/gpu/pvr/sgxcoretypes.h41
-rw-r--r--drivers/gpu/pvr/sgxdefs.h38
-rw-r--r--drivers/gpu/pvr/sgxerrata.h34
-rw-r--r--drivers/gpu/pvr/sgxfeaturedefs.h40
-rw-r--r--drivers/gpu/pvr/sgxinfo.h342
-rw-r--r--drivers/gpu/pvr/sgxinfokm.h270
-rw-r--r--drivers/gpu/pvr/sgxinit.c1663
-rw-r--r--drivers/gpu/pvr/sgxkick.c521
-rw-r--r--drivers/gpu/pvr/sgxmmu.h57
-rw-r--r--drivers/gpu/pvr/sgxpower.c488
-rw-r--r--drivers/gpu/pvr/sgxreset.c223
-rw-r--r--drivers/gpu/pvr/sgxscript.h65
-rw-r--r--drivers/gpu/pvr/sgxtransfer.c293
-rw-r--r--drivers/gpu/pvr/sgxutils.c749
-rw-r--r--drivers/gpu/pvr/sgxutils.h78
-rw-r--r--drivers/gpu/pvr/srvkm.h50
-rw-r--r--drivers/gpu/pvr/syscommon.h177
-rw-r--r--drivers/gpu/pvr/sysconfig.c836
-rw-r--r--drivers/gpu/pvr/sysconfig.h53
-rw-r--r--drivers/gpu/pvr/sysinfo.h94
-rw-r--r--drivers/gpu/pvr/syslocal.h100
-rw-r--r--drivers/gpu/pvr/sysutils.c731
-rw-r--r--drivers/gpu/pvr/tools/Makefile29
-rw-r--r--drivers/gpu/pvr/tools/dbgdriv.c1652
-rw-r--r--drivers/gpu/pvr/tools/dbgdriv.h183
-rw-r--r--drivers/gpu/pvr/tools/hostfunc.c267
-rw-r--r--drivers/gpu/pvr/tools/hostfunc.h58
-rw-r--r--drivers/gpu/pvr/tools/hotkey.c101
-rw-r--r--drivers/gpu/pvr/tools/hotkey.h60
-rw-r--r--drivers/gpu/pvr/tools/ioctl.c399
-rw-r--r--drivers/gpu/pvr/tools/ioctl.h81
-rw-r--r--drivers/gpu/pvr/tools/linuxsrv.h47
-rw-r--r--drivers/gpu/pvr/tools/main.c197
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/omap2/dss/dss.h2
-rw-r--r--drivers/video/omap2/dss/manager.c538
-rw-r--r--drivers/video/omap2/dss/overlay.c7
-rw-r--r--include/linux/pvr.h8
-rw-r--r--include/video/omapdss.h55
-rw-r--r--include/video/sgx-util.h64
138 files changed, 48242 insertions, 134 deletions
diff --git a/arch/arm/configs/meego_n9xx_defconfig b/arch/arm/configs/meego_n9xx_defconfig
new file mode 100644
index 00000000000..8f07a3f4e81
--- /dev/null
+++ b/arch/arm/configs/meego_n9xx_defconfig
@@ -0,0 +1,2456 @@
+#
+# Automatically generated make config: don't edit
+# Linux/arm 3.0.0 Kernel Configuration
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_HAVE_SCHED_CLOCK=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_HAVE_IRQ_WORK=y
+CONFIG_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_CHIP=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_RCU_FAST_NO_HZ is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_CGROUPS is not set
+# CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_KRETPROBES=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS4 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_TCC_926 is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+
+#
+# TI OMAP Common Features
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+CONFIG_ARCH_OMAP2PLUS=y
+
+#
+# OMAP Feature Selections
+#
+CONFIG_OMAP_DEBUG_DEVICES=y
+# CONFIG_OMAP_SMARTREFLEX is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_MUX_WARNINGS=y
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+CONFIG_OMAP_32K_TIMER=y
+# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_PM_NONE is not set
+CONFIG_OMAP_PM_NOOP=y
+CONFIG_MACH_OMAP_GENERIC=y
+
+#
+# TI OMAP2/3/4 Specific Features
+#
+CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
+CONFIG_ARCH_OMAP2=y
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
+
+#
+# OMAP Core Type
+#
+CONFIG_SOC_OMAP2420=y
+CONFIG_SOC_OMAP2430=y
+CONFIG_SOC_OMAP3430=y
+CONFIG_SOC_OMAPTI816X=y
+CONFIG_OMAP_PACKAGE_ZAF=y
+CONFIG_OMAP_PACKAGE_ZAC=y
+CONFIG_OMAP_PACKAGE_CBB=y
+CONFIG_OMAP_PACKAGE_CUS=y
+CONFIG_OMAP_PACKAGE_CBP=y
+CONFIG_OMAP_PACKAGE_CBL=y
+CONFIG_OMAP_PACKAGE_CBS=y
+
+#
+# OMAP Board Type
+#
+CONFIG_MACH_OMAP2_TUSB6010=y
+CONFIG_MACH_OMAP_H4=y
+CONFIG_MACH_OMAP_APOLLON=y
+CONFIG_MACH_OMAP_2430SDP=y
+CONFIG_MACH_OMAP3_BEAGLE=y
+CONFIG_MACH_DEVKIT8000=y
+CONFIG_MACH_OMAP_LDP=y
+CONFIG_MACH_OMAP3530_LV_SOM=y
+CONFIG_MACH_OMAP3_TORPEDO=y
+CONFIG_MACH_OVERO=y
+CONFIG_MACH_OMAP3EVM=y
+CONFIG_MACH_OMAP3517EVM=y
+# CONFIG_MACH_CRANEBOARD is not set
+CONFIG_MACH_OMAP3_PANDORA=y
+CONFIG_MACH_OMAP3_TOUCHBOOK=y
+CONFIG_MACH_OMAP_3430SDP=y
+CONFIG_MACH_NOKIA_N800=y
+CONFIG_MACH_NOKIA_N810=y
+CONFIG_MACH_NOKIA_N810_WIMAX=y
+CONFIG_MACH_NOKIA_N8X0=y
+CONFIG_MACH_NOKIA_RM680=y
+CONFIG_MACH_NOKIA_RX51=y
+CONFIG_MACH_OMAP_ZOOM2=y
+CONFIG_MACH_OMAP_ZOOM3=y
+CONFIG_MACH_CM_T35=y
+CONFIG_MACH_CM_T3517=y
+CONFIG_MACH_IGEP0020=y
+CONFIG_MACH_IGEP0030=y
+CONFIG_MACH_SBC3530=y
+CONFIG_MACH_OMAP_3630SDP=y
+CONFIG_MACH_TI8168EVM=y
+CONFIG_MACH_OMAP_4430SDP=y
+CONFIG_MACH_OMAP4_PANDA=y
+# CONFIG_OMAP3_EMU is not set
+# CONFIG_OMAP3_SDRC_AC_TIMING is not set
+
+#
+# System MMU
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_V6=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v6=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV6=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_V6=y
+CONFIG_CPU_PABRT_V7=y
+CONFIG_CPU_CACHE_V6=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_USE_DOMAINS=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_OUTER_CACHE=y
+CONFIG_OUTER_CACHE_SYNC=y
+CONFIG_CACHE_L2X0=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_ARM_ERRATA_411920=y
+# CONFIG_ARM_ERRATA_430973 is not set
+# CONFIG_ARM_ERRATA_458693 is not set
+# CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_742230 is not set
+# CONFIG_ARM_ERRATA_742231 is not set
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_ARM_ERRATA_720789=y
+CONFIG_PL310_ERRATA_727915=y
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_751472 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
+# CONFIG_ARM_ERRATA_754327 is not set
+CONFIG_ARM_GIC=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_SMP=y
+CONFIG_SMP_ON_UP=y
+CONFIG_HAVE_ARM_SCU=y
+CONFIG_HAVE_ARM_TWD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_NR_CPUS=2
+CONFIG_HOTPLUG_CPU=y
+CONFIG_LOCAL_TIMERS=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_CLEANCACHE is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+
+#
+# Boot options
+#
+# CONFIG_USE_OF is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/mmcblk0p1 rootwait rw console=ttyO2,115200n8 console=tty0 omapfb.vram=0:2M,1:2M,2:2M mtdoops.mtddev=2"
+CONFIG_CMDLINE_FROM_BOOTLOADER=y
+# CONFIG_CMDLINE_EXTEND is not set
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+CONFIG_PM_SLEEP_SMP=y
+CONFIG_PM_RUNTIME=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_ADVANCED_DEBUG is not set
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_CAN_PM_TRACE=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_HAS_OPP=y
+CONFIG_PM_OPP=y
+CONFIG_PM_RUNTIME_CLK=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+# CONFIG_XFRM_SUB_POLICY is not set
+CONFIG_XFRM_MIGRATE=y
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+CONFIG_RPS=y
+CONFIG_RFS_ACCEL=y
+CONFIG_XPS=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+# CONFIG_BT_L2CAP is not set
+# CONFIG_BT_SCO is not set
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+# CONFIG_BT_HCIUART_ATH3K is not set
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_SPY=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_RFKILL_REGULATOR is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+CONFIG_MTD_OOPS=y
+# CONFIG_MTD_SWAP is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+# CONFIG_MTD_ONENAND_GENERIC is not set
+CONFIG_MTD_ONENAND_OMAP2=y
+# CONFIG_MTD_ONENAND_OTP is not set
+# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
+# CONFIG_MTD_ONENAND_SIM is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_DM is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_AX88796 is not set
+CONFIG_SMC91X=y
+# CONFIG_TI_DAVINCI_EMAC is not set
+# CONFIG_TI_DAVINCI_MDIO is not set
+# CONFIG_TI_DAVINCI_CPDMA is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+CONFIG_SMSC911X=y
+# CONFIG_SMSC911X_ARCH_HOOKS is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_KS8851=y
+CONFIG_KS8851_MLL=y
+# CONFIG_FTMAC100 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NETDEV_10000=y
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8187 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_ATH_COMMON is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_IWM is not set
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+# CONFIG_LIBERTAS_SPI is not set
+CONFIG_LIBERTAS_DEBUG=y
+# CONFIG_LIBERTAS_MESH is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL8192SE is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_WL1251 is not set
+# CONFIG_WL12XX_MENU is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_MWIFIEX is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+# CONFIG_USB_NET_CDC_EEM is not set
+CONFIG_USB_NET_CDC_NCM=y
+# CONFIG_USB_NET_DM9601 is not set
+# CONFIG_USB_NET_SMSC75XX is not set
+# CONFIG_USB_NET_SMSC95XX is not set
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=y
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_MCS7830 is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_NET_CX82310_ETH is not set
+# CONFIG_USB_NET_KALMIA is not set
+# CONFIG_USB_NET_INT51X1 is not set
+# CONFIG_USB_IPHETH is not set
+# CONFIG_USB_SIERRA_NET is not set
+# CONFIG_USB_VL600 is not set
+# CONFIG_WAN is not set
+
+#
+# CAIF transport drivers
+#
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_KEYBOARD_TCA6416 is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_OMAP is not set
+# CONFIG_KEYBOARD_OMAP4 is not set
+CONFIG_KEYBOARD_TWL4030=y
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_MOUSE_SYNAPTICS_I2C is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_AD7877 is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
+# CONFIG_TOUCHSCREEN_EETI is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
+# CONFIG_TOUCHSCREEN_MCS5000 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+CONFIG_TOUCHSCREEN_TSC2005=y
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+# CONFIG_INPUT_TWL4030_VIBRA is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_PCF8574 is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_OMAP=y
+CONFIG_SERIAL_OMAP_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_HW_RANDOM_OMAP=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_RAMOOPS is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+CONFIG_SPI_OMAP24XX=y
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO drivers:
+#
+# CONFIG_GPIO_BASIC_MMIO is not set
+# CONFIG_GPIO_IT8761E is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+CONFIG_GPIO_TWL4030=y
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+# CONFIG_HDQ_MASTER_OMAP is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2408 is not set
+# CONFIG_W1_SLAVE_DS2423 is not set
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_DS2780 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ20Z75 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
+# CONFIG_CHARGER_ISP1704 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_TWL4030 is not set
+# CONFIG_CHARGER_GPIO is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS620 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_LINEAGE is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4151 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LTC4261 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX16065 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6639 is not set
+# CONFIG_SENSORS_MAX6642 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_PMBUS is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SHT21 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+# CONFIG_SENSORS_EMC6W201 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH5627 is not set
+# CONFIG_SENSORS_ADS1015 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83795 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_MPCORE_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL4030_WATCHDOG=y
+# CONFIG_MAX63XX_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+CONFIG_MFD_SUPPORT=y
+CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS6586X is not set
+CONFIG_MENELAUS=y
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_MADC is not set
+CONFIG_TWL4030_POWER=y
+CONFIG_TWL4030_CODEC=y
+# CONFIG_TWL6030_PWM is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_TPS65910 is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+# CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
+CONFIG_REGULATOR_TWL4030=y
+# CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_TPS6524X is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_DRM is not set
+CONFIG_PVR=m
+CONFIG_PVR_RELEASE=y
+# CONFIG_PVR_DEBUG is not set
+# CONFIG_PVR_TIMING is not set
+# CONFIG_PVR_DEBUG_PDUMP is not set
+# CONFIG_PVR_EDM_DEBUG is not set
+# CONFIG_PVR_NO_HARDWARE is not set
+# CONFIG_PVR_FORCE_CLOCKS_ON is not set
+# CONFIG_PVR_EXAMPLES is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_WMT_GE_ROPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_TMIO is not set
+# CONFIG_FB_UDL is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_BROADSHEET is not set
+CONFIG_FB_OMAP_LCD_VGA=y
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_VRAM=y
+CONFIG_OMAP2_VRFB=y
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_VRAM_SIZE=6
+# CONFIG_OMAP2_DSS_DEBUG_SUPPORT is not set
+# CONFIG_OMAP2_DSS_DPI is not set
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+CONFIG_OMAP4_DSS_HDMI=y
+CONFIG_OMAP2_DSS_SDI=y
+# CONFIG_OMAP2_DSS_DSI is not set
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0
+CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET=y
+CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET=y
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+CONFIG_FB_OMAP2_NUM_FBS=3
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_ACX565AKM=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+# CONFIG_LCD_L4F00242T03 is not set
+# CONFIG_LCD_LMS283GF05 is not set
+# CONFIG_LCD_LTV350QV is not set
+# CONFIG_LCD_TDO24M is not set
+# CONFIG_LCD_VGG2432A4 is not set
+CONFIG_LCD_PLATFORM=y
+# CONFIG_LCD_S6E63M0 is not set
+# CONFIG_LCD_LD9040 is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+# CONFIG_SND_DEBUG_VERBOSE is not set
+# CONFIG_SND_PCM_XRUN_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_ALOOP is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+# CONFIG_SND_USB_UA101 is not set
+# CONFIG_SND_USB_CAIAQ is not set
+# CONFIG_SND_USB_6FIRE is not set
+CONFIG_SND_SOC=m
+# CONFIG_SND_SOC_CACHE_LZO is not set
+CONFIG_SND_OMAP_SOC=m
+CONFIG_SND_OMAP_SOC_MCBSP=m
+# CONFIG_SND_OMAP_SOC_N810 is not set
+# CONFIG_SND_OMAP_SOC_RX51 is not set
+# CONFIG_SND_OMAP_SOC_OVERO is not set
+# CONFIG_SND_OMAP_SOC_OMAP3EVM is not set
+# CONFIG_SND_OMAP_SOC_AM3517EVM is not set
+# CONFIG_SND_OMAP_SOC_SDP3430 is not set
+# CONFIG_SND_OMAP_SOC_SDP4430 is not set
+CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
+# CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE is not set
+# CONFIG_SND_OMAP_SOC_ZOOM2 is not set
+# CONFIG_SND_OMAP_SOC_IGEP0020 is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=m
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_ROCCAT_ARVO is not set
+# CONFIG_HID_ROCCAT_KONE is not set
+# CONFIG_HID_ROCCAT_KONEPLUS is not set
+# CONFIG_HID_ROCCAT_KOVAPLUS is not set
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_EHCI_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+# CONFIG_USB_MUSB_TUSB6010 is not set
+# CONFIG_USB_MUSB_OMAP2PLUS is not set
+# CONFIG_USB_MUSB_AM35X is not set
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+CONFIG_MUSB_PIO_ONLY=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+CONFIG_USB_WDM=y
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+CONFIG_USB_LIBUSUAL=y
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=y
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_GADGET=m
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_FUSB300 is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_PXA_U2O is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+# CONFIG_USB_ZERO_HNPTEST is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_G_NCM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_ISP1301_OMAP is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_TWL4030_USB=y
+CONFIG_TWL6030_USB=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_NFC_DEVICES is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+CONFIG_RTC_DRV_TWL92330=y
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T93 is not set
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+CONFIG_CLKDEV_LOOKUP=y
+# CONFIG_HWSPINLOCK is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT23=y
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_TRACE_IRQFLAGS=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_KPROBES_SANITY_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_DEBUG_PER_CPU_MAPS is not set
+# CONFIG_LKDTM is not set
+# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_RING_BUFFER=y
+CONFIG_EVENT_TRACING=y
+CONFIG_EVENT_POWER_TRACING_DEPRECATED=y
+CONFIG_CONTEXT_SWITCH_TRACER=y
+CONFIG_RING_BUFFER_ALLOW_SWAP=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_KPROBE_EVENT=y
+# CONFIG_RING_BUFFER_BENCHMARK is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_NETWORK is not set
+# CONFIG_SECURITY_PATH is not set
+# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
+# CONFIG_IMA is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_PCRYPT is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
+# CONFIG_CRYPTO_DEV_OMAP_AES is not set
+CONFIG_BINARY_PRINTF=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_CPU_RMAP=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_AVERAGE=y
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 88bd6f7705f..11e99c3834e 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -15,6 +15,7 @@
#include <linux/input/matrix_keypad.h>
#include <linux/spi/spi.h>
#include <linux/wl12xx.h>
+#include <linux/spi/tsc2005.h>
#include <linux/i2c.h>
#include <linux/i2c/twl.h>
#include <linux/clk.h>
@@ -54,6 +55,9 @@
#define RX51_FMTX_RESET_GPIO 163
#define RX51_FMTX_IRQ 53
+#define RX51_TSC2005_RESET_GPIO 104
+#define RX51_TSC2005_IRQ_GPIO 100
+
#define RX51_USB_TRANSCEIVER_RST_GPIO 67
/* list all spi devices here */
@@ -64,6 +68,7 @@ enum {
};
static struct wl12xx_platform_data wl1251_pdata;
+static struct tsc2005_platform_data tsc2005_pdata;
#if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE)
static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
@@ -107,10 +112,10 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = {
.modalias = "tsc2005",
.bus_num = 1,
.chip_select = 0,
- /* .irq = OMAP_GPIO_IRQ(RX51_TSC2005_IRQ_GPIO),*/
+ .irq = OMAP_GPIO_IRQ(RX51_TSC2005_IRQ_GPIO),
.max_speed_hz = 6000000,
.controller_data = &tsc2005_mcspi_config,
- /* .platform_data = &tsc2005_config,*/
+ .platform_data = &tsc2005_pdata,
},
};
@@ -183,7 +188,7 @@ static struct gpio_keys_button rx51_gpio_keys[] = {
.type = EV_SW,
.code = SW_KEYPAD_SLIDE,
.gpio = RX51_GPIO_KEYPAD_SLIDE,
- .active_low = 1,
+ .active_low = 0,
.debounce_interval = RX51_GPIO_DEBOUNCE_TIMEOUT,
}, {
.desc = "Proximity Sensor",
@@ -902,6 +907,42 @@ static struct omap_onenand_platform_data board_onenand_data[] = {
};
#endif
+static struct tsc2005_platform_data tsc2005_pdata = {
+ .ts_pressure_max = 2048,
+ .ts_pressure_fudge = 2,
+ .ts_x_max = 4096,
+ .ts_x_fudge = 4,
+ .ts_y_max = 4096,
+ .ts_y_fudge = 7,
+ .ts_x_plate_ohm = 280,
+ .esd_timeout_ms = 8000,
+};
+
+static void rx51_tsc2005_set_reset(bool enable)
+{
+ gpio_set_value(RX51_TSC2005_RESET_GPIO, enable);
+}
+
+static void __init rx51_init_tsc2005(void)
+{
+ int r;
+
+ r = gpio_request(RX51_TSC2005_IRQ_GPIO, "tsc2005 IRQ");
+ if (r >= 0)
+ gpio_direction_input(RX51_TSC2005_IRQ_GPIO);
+ else
+ printk(KERN_ERR "unable to get %s GPIO\n", "tsc2005 IRQ");
+
+ r = gpio_request(RX51_TSC2005_RESET_GPIO, "tsc2005 reset");
+ if (r >= 0) {
+ gpio_direction_output(RX51_TSC2005_RESET_GPIO, 1);
+ tsc2005_pdata.set_reset = rx51_tsc2005_set_reset;
+ } else {
+ printk(KERN_ERR "unable to get %s GPIO\n", "tsc2005 reset");
+ tsc2005_pdata.esd_timeout_ms = 0;
+ }
+}
+
#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
static struct omap_smc91x_platform_data board_smc91x_data = {
@@ -978,6 +1019,7 @@ void __init rx51_peripherals_init(void)
rx51_add_gpio_keys();
rx51_init_wl1251();
rx51_init_si4713();
+ rx51_init_tsc2005();
spi_register_board_info(rx51_peripherals_spi_board_info,
ARRAY_SIZE(rx51_peripherals_spi_board_info));
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index 2c1289bd5e6..ddba833ad3a 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -14,6 +14,7 @@
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/mm.h>
+#include <linux/pvr.h>
#include <asm/mach-types.h>
#include <video/omapdss.h>
#include <plat/vram.h>
@@ -66,6 +67,22 @@ static struct omap_dss_board_info rx51_dss_board_info = {
.default_device = &rx51_lcd_device,
};
+static struct sgx_platform_data rx51_sgx_data = {
+ .fclock_max = 110666666,
+};
+
+static struct platform_device rx51_sgx_device = {
+ .name = "pvrsrvkm",
+ .id = -1,
+ .dev = {
+ .platform_data = &rx51_sgx_data,
+ },
+};
+
+static struct platform_device *rx51_video_devices[] __initdata = {
+ &rx51_sgx_device,
+};
+
static int __init rx51_video_init(void)
{
if (!machine_is_nokia_rx51())
@@ -83,6 +100,8 @@ static int __init rx51_video_init(void)
}
omap_display_init(&rx51_dss_board_info);
+ platform_add_devices(rx51_video_devices,
+ ARRAY_SIZE(rx51_video_devices));
return 0;
}
diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
index b0471bb2d47..4046b3f28e0 100644
--- a/arch/arm/plat-omap/omap-pm-noop.c
+++ b/arch/arm/plat-omap/omap-pm-noop.c
@@ -87,6 +87,7 @@ int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
return 0;
}
+EXPORT_SYMBOL(omap_pm_set_min_bus_tput);
int omap_pm_set_max_dev_wakeup_lat(struct device *req_dev, struct device *dev,
long t)
diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index cc9277885dd..bd7fc6683d8 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -1 +1 @@
-obj-y += drm/ vga/ stub/
+obj-y += drm/ vga/ stub/ pvr/
diff --git a/drivers/gpu/pvr/COPYING b/drivers/gpu/pvr/COPYING
new file mode 100644
index 00000000000..80dd76b2624
--- /dev/null
+++ b/drivers/gpu/pvr/COPYING
@@ -0,0 +1,351 @@
+
+This software is Copyright (C) 2008 Imagination Technologies Ltd.
+ All rights reserved.
+
+You may use, distribute and copy this software under the terms of
+GNU General Public License version 2, which is displayed below.
+
+-------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+-------------------------------------------------------------------------
+
diff --git a/drivers/gpu/pvr/Kconfig b/drivers/gpu/pvr/Kconfig
new file mode 100644
index 00000000000..949911c86f1
--- /dev/null
+++ b/drivers/gpu/pvr/Kconfig
@@ -0,0 +1,55 @@
+menuconfig PVR
+ tristate "PowerVR Services"
+ depends on OMAP2_DSS
+
+if PVR
+
+choice
+ prompt "Build type"
+ default PVR_RELEASE
+config PVR_RELEASE
+ bool "Release"
+config PVR_DEBUG
+ bool "Debug"
+config PVR_TIMING
+ bool "Timing"
+endchoice
+
+config PVR_DEBUG_EXTRA
+ bool "Extra debugging info"
+ depends on PVR_DEBUG
+ help
+ This enables extra debugging facilities on top of what you
+ get with setting debug build type above. This effectively
+ changes the driver's ABI, so the user space clients using
+ the driver need to be built in debug mode as well.
+
+config PVR_DEBUG_PDUMP
+ tristate "PDUMP debug support"
+ depends on PVR
+ default n
+
+config PVR_EDM_DEBUG
+ depends on PVR
+ bool "Enable EDM trace"
+ default n
+ help
+ EDM trace helps to track down some HW recovery events. You _must_
+ also enabled EDM (PVRSRV_USSE_EDM_STATUS_DEBUG) in the userland
+ libraries otherwise the drivers won't start
+
+config PVR_NO_HARDWARE
+ bool
+ default n
+
+config PVR_FORCE_CLOCKS_ON
+ bool "Force clocks on"
+ depends on !PVR_NO_HARDWARE
+ default n
+
+config PVR_EXAMPLES
+ tristate "Example code"
+ default n
+
+endif
+
diff --git a/drivers/gpu/pvr/Makefile b/drivers/gpu/pvr/Makefile
new file mode 100644
index 00000000000..48e37d0b694
--- /dev/null
+++ b/drivers/gpu/pvr/Makefile
@@ -0,0 +1,44 @@
+obj-$(CONFIG_PVR) += omaplfb.o pvrsrvkm.o
+
+omaplfb-objs := omaplfb_displayclass.o omaplfb_linux.o
+
+pvrsrvkm-objs := osfunc.o mmap.o module.o pdump.o proc.o \
+ pvr_bridge_k.o mm.o event.o \
+ buffer_manager.o devicemem.o deviceclass.o \
+ handle.o hash.o pvrsrv.o queue.o ra.o \
+ resman.o power.o mem.o bridged_pvr_bridge.o \
+ sgxinit.o sgxreset.o sgxutils.o sgxkick.o \
+ sgxtransfer.o mmu.o pb.o perproc.o sysconfig.o \
+ sysutils.o osperproc.o bridged_support.o \
+ bridged_sgx_bridge.o sgxpower.o pdump_common.o \
+ pvr_events.o
+
+pvrsrvkm-objs-$(CONFIG_PVR_DEBUG) += pvr_debug.o
+pvrsrvkm-objs-$(CONFIG_PVR_TIMING) += pvr_debug.o
+
+pvrsrvkm-objs += $(pvrsrvkm-objs-y) $(pvrsrvkm-objs-m)
+
+obj-$(CONFIG_PVR_EXAMPLES) += bc_example.o
+
+bc_example-objs := bufferclass_example.o bufferclass_example_linux.o \
+ bufferclass_example_private.o
+
+
+obj-$(CONFIG_PVR_DEBUG_PDUMP) += pvrdbg.o
+
+pvrdbg-objs := tools/main.o tools/dbgdriv.o tools/ioctl.o \
+ tools/hostfunc.o tools/hotkey.o
+
+
+DATE := $(shell date "+%a %B %d %Z %Y" )
+CBUILD := -O2 \
+ -DPVR_BUILD_DIR="\"$(PVR_BUILD_DIR)\"" \
+ -DPVR_BUILD_DATE="\"$(DATE)\""
+
+ccflags-y += $(CBUILD) -include $(srctree)/$(src)/pvrconfig.h
+
+ccflags-$(CONFIG_PVR_DEBUG_PDUMP) += -I $(srctree)/$(src)/tools \
+ -I $(srctree)/$(src)
+ccflags-y += $(ccflags-m)
+
+
diff --git a/drivers/gpu/pvr/README b/drivers/gpu/pvr/README
new file mode 100644
index 00000000000..7da0e623511
--- /dev/null
+++ b/drivers/gpu/pvr/README
@@ -0,0 +1,27 @@
+
+SGX Embedded Systems DDK for Linux kernel.
+Copyright (C) 2008 Imagination Technologies Ltd. All rights reserved.
+======================================================================
+
+
+About
+-------------------------------------------
+
+This is the Imagination Technologies SGX DDK for the Linux kernel.
+
+
+License
+-------------------------------------------
+
+You may use, distribute and copy this software under the terms of
+GNU General Public License version 2.
+
+The full GNU General Public License version 2 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
diff --git a/drivers/gpu/pvr/bridged_pvr_bridge.c b/drivers/gpu/pvr/bridged_pvr_bridge.c
new file mode 100644
index 00000000000..740981675ce
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_pvr_bridge.c
@@ -0,0 +1,3341 @@
+/**********************************************************************
+ *
+ * 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"
+#include "sgx_bridge.h"
+#include "perproc.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+#include "pdump_km.h"
+#include "syscommon.h"
+
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "env_data.h"
+
+#include "mmap.h"
+
+#include <linux/kernel.h>
+#include <linux/pagemap.h> /* for cache flush */
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+struct PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+ g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+#if defined(DEBUG_BRIDGE_KM)
+struct PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+static IMG_BOOL abSharedDeviceMemHeap[PVRSRV_MAX_CLIENT_HEAPS];
+static IMG_BOOL *pbSharedDeviceMemHeap = abSharedDeviceMemHeap;
+
+#if defined(DEBUG_BRIDGE_KM)
+enum PVRSRV_ERROR
+CopyFromUserWrapper(struct PVRSRV_PER_PROCESS_DATA *pProcData,
+ u32 ui32BridgeID, void *pvDest, void __user *pvSrc,
+ u32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyFromUserTotalBytes +=
+ ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes += ui32Size;
+ return OSCopyFromUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+
+enum PVRSRV_ERROR CopyToUserWrapper(struct PVRSRV_PER_PROCESS_DATA *pProcData,
+ u32 ui32BridgeID, void __user *pvDest, void *pvSrc,
+ u32 ui32Size)
+{
+ g_BridgeDispatchTable[ui32BridgeID].ui32CopyToUserTotalBytes +=
+ ui32Size;
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes += ui32Size;
+ return OSCopyToUser(pProcData, pvDest, pvSrc, ui32Size);
+}
+#endif
+
+static int PVRSRVEnumerateDevicesBW(u32 ui32BridgeID, void *psBridgeIn,
+ struct PVRSRV_BRIDGE_OUT_ENUMDEVICE *psEnumDeviceOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_DEVICES);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ psEnumDeviceOUT->eError =
+ PVRSRVEnumerateDevicesKM(&psEnumDeviceOUT->ui32NumDevices,
+ psEnumDeviceOUT->asDeviceIdentifier);
+
+ return 0;
+}
+
+static int PVRSRVAcquireDeviceDataBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO *psAcquireDevInfoIN,
+ struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO *psAcquireDevInfoOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT *psCreateDevMemContextIN,
+ struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT *psCreateDevMemContextOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDevMemContextInt;
+ u32 i;
+ IMG_BOOL 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 (abSharedDeviceMemHeap[i]) {
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psCreateDevMemContextOUT->
+ sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ } 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;
+ }
+ }
+ psCreateDevMemContextOUT->sHeapInfo[i].hDevMemHeap =
+ hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError,
+ psPerProc);
+
+ return 0;
+}
+
+static int PVRSRVDestroyDeviceMemContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT *psDestroyDevMemContextIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDevMemContextInt;
+ IMG_BOOL 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,
+ struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO *psGetDevMemHeapInfoOUT,
+ struct 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 (abSharedDeviceMemHeap[i]) {
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED);
+ } else {
+ psGetDevMemHeapInfoOUT->eError =
+ PVRSRVFindHandle(psPerProc->psHandleBase,
+ &hDevMemHeapExt,
+ psGetDevMemHeapInfoOUT->
+ sHeapInfo[i].hDevMemHeap,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP);
+ if (psGetDevMemHeapInfoOUT->eError != PVRSRV_OK)
+ return 0;
+ }
+ psGetDevMemHeapInfoOUT->sHeapInfo[i].hDevMemHeap =
+ hDevMemHeapExt;
+ }
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psGetDevMemHeapInfoOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static int PVRSRVAllocDeviceMemBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
+ struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *psAllocDeviceMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct 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;
+
+ OSMemSet(&psAllocDeviceMemOUT->sClientMemInfo, 0,
+ sizeof(psAllocDeviceMemOUT->sClientMemInfo));
+
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+ psAllocDeviceMemOUT->sClientMemInfo.pvLinAddr = NULL;
+ 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) {
+ OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo, 0,
+ sizeof(struct 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;
+}
+
+
+static int PVRSRVFreeDeviceMemBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM *psFreeDeviceMemIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ void *pvKernelMemInfo;
+ struct 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 = (struct PVRSRV_KERNEL_MEM_INFO *)pvKernelMemInfo;
+ if (psKernelMemInfo->ui32RefCount != 1) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVFreeDeviceMemBW: "
+ "mappings are open in other processes");
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psRetOUT->eError = PVRSRVFreeDeviceMemKM(hDevCookieInt,
+ pvKernelMemInfo);
+
+ 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,
+ struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM *psExportDeviceMemIN,
+ struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY *psMapDevMemIN,
+ struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDevMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psSrcKernelMemInfo = NULL;
+ struct 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;
+
+ OSMemSet(&psMapDevMemOUT->sDstClientMemInfo, 0,
+ sizeof(psMapDevMemOUT->sDstClientMemInfo));
+ OSMemSet(&psMapDevMemOUT->sDstClientSyncInfo, 0,
+ sizeof(psMapDevMemOUT->sDstClientSyncInfo));
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddrKM =
+ psDstKernelMemInfo->pvLinAddrKM;
+
+ psMapDevMemOUT->sDstClientMemInfo.pvLinAddr = NULL;
+ 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,
+ struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY *psUnmapDevMemIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct 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 FlushCacheDRI(u32 ui32Type, u32 ui32Virt, u32 ui32Length)
+{
+ switch (ui32Type) {
+ case DRM_PVR2D_CFLUSH_FROM_GPU:
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "DRM_PVR2D_CFLUSH_FROM_GPU 0x%08x, length 0x%08x\n",
+ ui32Virt, ui32Length);
+#ifdef CONFIG_ARM
+ dmac_map_area((const void *)ui32Virt, ui32Length, DMA_FROM_DEVICE);
+#endif
+ return 0;
+ case DRM_PVR2D_CFLUSH_TO_GPU:
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "DRM_PVR2D_CFLUSH_TO_GPU 0x%08x, length 0x%08x\n",
+ ui32Virt, ui32Length);
+#ifdef CONFIG_ARM
+ dmac_map_area((const void *)ui32Virt, ui32Length, DMA_TO_DEVICE);
+#endif
+ return 0;
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "Invalid cflush type 0x%x\n",
+ ui32Type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int PVRSRVCacheFlushDRIBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER *psCacheFlushIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct vm_area_struct *vma;
+ unsigned long start;
+ size_t len;
+ int type;
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CACHE_FLUSH_DRM);
+
+ start = psCacheFlushIN->ui32Virt;
+ len = psCacheFlushIN->ui32Length;
+ type = psCacheFlushIN->ui32Type;
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, start);
+ if (vma == NULL || vma->vm_start > start ||
+ vma->vm_end < start + len)
+ pr_err("PVR: %s: invalid address %08lx %zu %c\n",
+ __func__, start, len,
+ type == DRM_PVR2D_CFLUSH_TO_GPU ? 'c' :
+ type == DRM_PVR2D_CFLUSH_FROM_GPU ? 'i' :
+ '?');
+ else
+ psRetOUT->eError = FlushCacheDRI(type, start, len);
+
+ up_read(&current->mm->mmap_sem);
+
+ return 0;
+}
+
+static int PVRSRVMapDeviceClassMemoryBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY *psMapDevClassMemIN,
+ struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY *psMapDevClassMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ void *hOSMapInfo;
+ void *hDeviceClassBufferInt;
+ void *hDevMemContextInt;
+ enum 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) {
+ case PVRSRV_HANDLE_TYPE_DISP_BUFFER:
+ case PVRSRV_HANDLE_TYPE_BUF_BUFFER:
+ break;
+ default:
+ psMapDevClassMemOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ psMapDevClassMemOUT->eError =
+ PVRSRVMapDeviceClassMemoryKM(psPerProc, hDevMemContextInt,
+ hDeviceClassBufferInt, &psMemInfo, &hOSMapInfo);
+
+ if (psMapDevClassMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ OSMemSet(&psMapDevClassMemOUT->sClientMemInfo, 0,
+ sizeof(psMapDevClassMemOUT->sClientMemInfo));
+ OSMemSet(&psMapDevClassMemOUT->sClientSyncInfo, 0,
+ sizeof(psMapDevClassMemOUT->sClientSyncInfo));
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddrKM =
+ psMemInfo->pvLinAddrKM;
+
+ psMapDevClassMemOUT->sClientMemInfo.pvLinAddr = NULL;
+ 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,
+ struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY *psUnmapDevClassMemIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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;
+}
+
+static int PVRSRVWrapExtMemoryBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
+ struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ void *hDevMemContextInt;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ u32 ui32PageTableSize = 0;
+ struct 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(struct IMG_SYS_PHYADDR);
+
+ ASSIGN_AND_EXIT_ON_ERROR(psWrapExtMemOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32PageTableSize,
+ (void **)&psSysPAddr, NULL));
+
+ if (CopyFromUserWrapper(psPerProc, ui32BridgeID, psSysPAddr,
+ psWrapExtMemIN->psSysPAddr,
+ ui32PageTableSize) != PVRSRV_OK) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize,
+ (void *) psSysPAddr, NULL);
+ return -EFAULT;
+ }
+ }
+
+ psWrapExtMemOUT->eError = PVRSRVWrapExtMemoryKM(hDevCookieInt,
+ psPerProc, hDevMemContextInt,
+ psWrapExtMemIN->ui32ByteSize,
+ psWrapExtMemIN->ui32PageOffset,
+ psWrapExtMemIN->bPhysContig,
+ psSysPAddr, psWrapExtMemIN->pvLinAddr,
+ &psMemInfo);
+ if (psWrapExtMemIN->ui32NumPageTableEntries)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize,
+ (void *)psSysPAddr, NULL);
+ if (psWrapExtMemOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM = psMemInfo->pvLinAddrKM;
+
+ psWrapExtMemOUT->sClientMemInfo.pvLinAddr = NULL;
+ 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_MULTI,
+ psWrapExtMemOUT->sClientMemInfo.hKernelMemInfo);
+
+ COMMIT_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc);
+
+ return 0;
+}
+
+static int PVRSRVUnwrapExtMemoryBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY *psUnwrapExtMemIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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((struct 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,
+ struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
+ struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM *psGetFreeDeviceMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GETFREE_DEVICEMEM);
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psGetFreeDeviceMemOUT->eError =
+ PVRSRVGetFreeDeviceMemKM(psGetFreeDeviceMemIN->ui32Flags,
+ &psGetFreeDeviceMemOUT->ui32Total,
+ &psGetFreeDeviceMemOUT->ui32Free,
+ &psGetFreeDeviceMemOUT->ui32LargestBlock);
+
+ return 0;
+}
+
+static int PVRMMapOSMemHandleToMMapDataBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *psMMapDataIN,
+ struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *psMMapDataOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
+
+ psMMapDataOUT->eError =
+ PVRMMapOSMemHandleToMMapData(psPerProc, psMMapDataIN->hMHandle,
+ &psMMapDataOUT->ui32MMapOffset,
+ &psMMapDataOUT->ui32ByteOffset,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+ return 0;
+}
+
+static int PVRMMapReleaseMMapDataBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA *psMMapDataIN,
+ struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA *psMMapDataOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
+
+ psMMapDataOUT->eError = PVRMMapReleaseMMapData(psPerProc,
+ psMMapDataIN->hMHandle,
+ &psMMapDataOUT->bMUnmap,
+ &psMMapDataOUT->ui32RealByteSize,
+ &psMMapDataOUT->ui32UserVAddr);
+ return 0;
+}
+
+#ifdef PDUMP
+static int PDumpIsCaptureFrameBW(u32 ui32BridgeID, void *psBridgeIn,
+ struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING *psPDumpIsCapturingOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_ISCAPTURING);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psPDumpIsCapturingOUT->bIsCapturing = PDumpIsCaptureFrameKM();
+ psPDumpIsCapturingOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int PDumpCommentBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT *psPDumpCommentIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_COMMENT);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpCommentKM(&psPDumpCommentIN->szComment[0],
+ psPDumpCommentIN->ui32Flags);
+ return 0;
+}
+
+static int PDumpSetFrameBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME *psPDumpSetFrameIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_SETFRAME);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpSetFrameKM(psPDumpSetFrameIN->ui32Frame);
+
+ return 0;
+}
+
+static int PDumpRegWithFlagsBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG *psPDumpRegDumpIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REG);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError =
+ PDumpRegWithFlagsKM(psPDumpRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpRegDumpIN->sHWReg.ui32RegVal,
+ psPDumpRegDumpIN->ui32Flags);
+
+ return 0;
+}
+
+static int PDumpRegPolBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL *psPDumpRegPolIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_REGPOL);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError =
+ PDumpRegPolWithFlagsKM(psPDumpRegPolIN->sHWReg.ui32RegAddr,
+ psPDumpRegPolIN->sHWReg.ui32RegVal,
+ psPDumpRegPolIN->ui32Mask,
+ psPDumpRegPolIN->ui32Flags);
+
+ return 0;
+}
+
+static int PDumpMemPolBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL *psPDumpMemPolIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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(((struct PVRSRV_KERNEL_MEM_INFO *)pvMemInfo),
+ psPDumpMemPolIN->ui32Offset,
+ psPDumpMemPolIN->ui32Value,
+ psPDumpMemPolIN->ui32Mask,
+ PDUMP_POLL_OPERATOR_EQUAL,
+ psPDumpMemPolIN->bLastFrame,
+ psPDumpMemPolIN->bOverwrite,
+ MAKEUNIQUETAG(pvMemInfo));
+
+ return 0;
+}
+
+static int PDumpMemBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM *psPDumpMemDumpIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP *psPDumpBitmapIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ 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,
+ struct PVRSRV_BRIDGE_IN_PDUMP_READREG *psPDumpReadRegIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DUMPREADREG);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpReadRegKM(&psPDumpReadRegIN->szFileName[0],
+ psPDumpReadRegIN->ui32FileOffset,
+ psPDumpReadRegIN->ui32Address,
+ psPDumpReadRegIN->ui32Size,
+ psPDumpReadRegIN->ui32Flags);
+
+ return 0;
+}
+
+static int PDumpDriverInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO *psPDumpDriverInfoIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 ui32PDumpFlags;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_DRIVERINFO);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ ui32PDumpFlags = 0;
+ if (psPDumpDriverInfoIN->bContinuous)
+ ui32PDumpFlags |= PDUMP_FLAGS_CONTINUOUS;
+ psRetOUT->eError = PDumpDriverInfoKM(&psPDumpDriverInfoIN->szString[0],
+ ui32PDumpFlags);
+
+ return 0;
+}
+
+static int PDumpSyncDumpBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC *psPDumpSyncDumpIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ ((struct PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->
+ psSyncDataMemInfoKM,
+ psPDumpSyncDumpIN->ui32Offset, ui32Bytes, 0,
+ MAKEUNIQUETAG(((struct PVRSRV_KERNEL_SYNC_INFO *)
+ pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static int PDumpSyncPolBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL *psPDumpSyncPolIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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(struct PVRSRV_SYNC_DATA,
+ ui32ReadOpsComplete);
+ else
+ ui32Offset = offsetof(struct PVRSRV_SYNC_DATA,
+ ui32WriteOpsComplete);
+
+ psRetOUT->eError =
+ PDumpMemPolKM(((struct PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo)->
+ psSyncDataMemInfoKM, ui32Offset,
+ psPDumpSyncPolIN->ui32Value,
+ psPDumpSyncPolIN->ui32Mask, PDUMP_POLL_OPERATOR_EQUAL,
+ IMG_FALSE, IMG_FALSE,
+ MAKEUNIQUETAG(((struct PVRSRV_KERNEL_SYNC_INFO *)
+ pvSyncInfo)->psSyncDataMemInfoKM));
+
+ return 0;
+}
+
+static int PDumpPDRegBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG *psPDumpPDRegDumpIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_PDUMP_PDREG);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ PDumpPDReg(psPDumpPDRegDumpIN->sHWReg.ui32RegAddr,
+ psPDumpPDRegDumpIN->sHWReg.ui32RegVal, PDUMP_PD_UNIQUETAG);
+
+ psRetOUT->eError = PVRSRV_OK;
+ return 0;
+}
+
+static int PDumpCycleCountRegReadBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ
+ *psPDumpCycleCountRegReadIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ PDumpCycleCountRegRead(psPDumpCycleCountRegReadIN->ui32RegOffset,
+ psPDumpCycleCountRegReadIN->bLastFrame);
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int PDumpPDDevPAddrBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR *psPDumpPDDevPAddrIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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((struct PVRSRV_KERNEL_MEM_INFO *)pvMemInfo,
+ psPDumpPDDevPAddrIN->ui32Offset,
+ psPDumpPDDevPAddrIN->sPDDevPAddr,
+ MAKEUNIQUETAG(pvMemInfo), PDUMP_PD_UNIQUETAG);
+ return 0;
+}
+
+static int PDumpStartInitPhaseBW(u32 ui32BridgeID, void *psBridgeIn,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_PDUMP_STARTINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStartInitPhaseKM();
+
+ return 0;
+}
+
+static int PDumpStopInitPhaseBW(u32 ui32BridgeID, void *psBridgeIn,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_PDUMP_STOPINITPHASE);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+
+ psRetOUT->eError = PDumpStopInitPhaseKM();
+
+ return 0;
+}
+
+#endif
+
+static int PVRSRVGetMiscInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_GET_MISC_INFO *psGetMiscInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO *psGetMiscInfoOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ enum PVRSRV_ERROR eError;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo, &psGetMiscInfoIN->sMiscInfo,
+ sizeof(struct 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,
+ NULL));
+
+ psGetMiscInfoOUT->eError =
+ PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
+
+ eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
+ (void __force __user *)
+ psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen,
+ (void *)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,
+ struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES *psConnectServicesOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
+
+ psConnectServicesOUT->hKernelServices = psPerProc->hPerProcData;
+ psConnectServicesOUT->eError = PVRSRV_OK;
+
+#if defined(PDUMP)
+
+ {
+ struct SYS_DATA *psSysData;
+ SysAcquireData(&psSysData);
+ psSysData->bPowerUpPDumped = IMG_FALSE;
+ }
+#endif
+
+ return 0;
+}
+
+static int PVRSRVDisconnectBW(u32 ui32BridgeID, void *psBridgeIn,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_DISCONNECT_SERVICES);
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int PVRSRVEnumerateDCBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+ struct PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(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,
+ struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceIN,
+ struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE *psOpenDispClassDeviceOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE *psCloseDispClassDeviceIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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, IMG_FALSE);
+ 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,
+ struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsIN,
+ struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS *psEnumDispClassFormatsOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsIN,
+ struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS *psEnumDispClassDimsOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,
+ struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
+ struct 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,
+ (enum 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,
+ struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO *psGetDispClassInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO *psGetDispClassInfoOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN
+ *psCreateDispClassSwapChainIN,
+ struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN
+ *psCreateDispClassSwapChainOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *pvDispClassInfo;
+ void *hSwapChainInt;
+
+ 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;
+
+ psCreateDispClassSwapChainOUT->eError =
+ PVRSRVCreateDCSwapChainKM(psPerProc, pvDispClassInfo,
+ psCreateDispClassSwapChainIN->ui32Flags,
+ &psCreateDispClassSwapChainIN->sDstSurfAttrib,
+ &psCreateDispClassSwapChainIN->sSrcSurfAttrib,
+ psCreateDispClassSwapChainIN->ui32BufferCount,
+ psCreateDispClassSwapChainIN->ui32OEMFlags,
+ &hSwapChainInt,
+ &psCreateDispClassSwapChainOUT->ui32SwapChainID);
+
+ if (psCreateDispClassSwapChainOUT->eError != PVRSRV_OK)
+ return 0;
+
+ 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,
+ struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN
+ *psDestroyDispClassSwapChainIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassDstRectIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT *psSetDispClassSrcRectIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY *psSetDispClassColKeyIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersIN,
+ struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS *psGetDispClassBuffersOUT,
+ struct 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,
+ (enum 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,
+ struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER *psSwapDispClassBufferIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceIN,
+ struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE *psOpenBufferClassDeviceOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE *psCloseBufferClassDeviceIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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, IMG_FALSE);
+
+ 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,
+ struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO *psGetBufferClassInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO *psGetBufferClassInfoOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferIN,
+ struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER *psGetBufferClassBufferOUT,
+ struct 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,
+ (enum 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,
+ struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemIN,
+ struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM *psAllocSharedSysMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct 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;
+
+ OSMemSet(&psAllocSharedSysMemOUT->sClientMemInfo,
+ 0, sizeof(psAllocSharedSysMemOUT->sClientMemInfo));
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psAllocSharedSysMemOUT->sClientMemInfo.pvLinAddr = NULL;
+ 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,
+ struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM *psFreeSharedSysMemIN,
+ struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM *psFreeSharedSysMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM *psMapMemInfoMemIN,
+ struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM *psMapMemInfoMemOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ enum 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) {
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+ 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;
+
+ OSMemSet(&psMapMemInfoMemOUT->sClientMemInfo,
+ 0, sizeof(psMapMemInfoMemOUT->sClientMemInfo));
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psMapMemInfoMemOUT->sClientMemInfo.pvLinAddr = NULL;
+ 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) {
+ OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo, 0,
+ sizeof(struct 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 PVRSRVModifySyncOpsBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_MODIFY_SYNC_OPS *psModifySyncOpsIN,
+ struct PVRSRV_BRIDGE_OUT_MODIFY_SYNC_OPS *psModifySyncOpsOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hKernelSyncInfo;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MODIFY_SYNC_OPS);
+
+ psModifySyncOpsOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &hKernelSyncInfo,
+ psModifySyncOpsIN->hKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psModifySyncOpsOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psKernelSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)hKernelSyncInfo;
+
+ /* We return PRE-INCREMENTED versions of all sync Op Values */
+
+ psModifySyncOpsOUT->ui32ReadOpsPending =
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psModifySyncOpsOUT->ui32WriteOpsPending =
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ psModifySyncOpsOUT->ui32ReadOpsComplete =
+ psKernelSyncInfo->psSyncData->ui32ReadOpsComplete;
+
+ psModifySyncOpsOUT->ui32WriteOpsComplete =
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete;
+
+ if (psModifySyncOpsIN->ui32ModifyFlags &
+ PVRSRV_MODIFYSYNCOPS_FLAGS_WOP_INC)
+ psKernelSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+ if (psModifySyncOpsIN->ui32ModifyFlags &
+ PVRSRV_MODIFYSYNCOPS_FLAGS_ROP_INC)
+ psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ if (psModifySyncOpsIN->ui32ModifyFlags &
+ PVRSRV_MODIFYSYNCOPS_FLAGS_WOC_INC)
+ psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
+
+ if (psModifySyncOpsIN->ui32ModifyFlags &
+ PVRSRV_MODIFYSYNCOPS_FLAGS_ROC_INC)
+ psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
+
+ return 0;
+}
+
+static int MMU_GetPDDevPAddrBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrIN,
+ struct PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR *psGetMmuPDDevPAddrOUT,
+ struct 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,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+#if !defined(CONFIG_PVR_DEBUG_EXTRA)
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+#endif
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+ PVR_UNREFERENCED_PARAMETER(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!)",
+ __func__, 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!)",
+ __func__, ui32BridgeID);
+#endif
+ return -ENOTTY;
+}
+
+void _SetDispatchTableEntry(u32 ui32Index, const char *pszIOCName,
+ int (*pfFunction)(u32 ui32BridgeID,
+ void *psBridgeIn,
+ void *psBridgeOut,
+ struct PVRSRV_PER_PROCESS_DATA
+ *psPerProc),
+ const char *pszFunctionName)
+{
+ static u32 ui32PrevIndex = ~0UL;
+#if !defined(CONFIG_PVR_DEBUG_EXTRA)
+ PVR_UNREFERENCED_PARAMETER(pszIOCName);
+#endif
+#if !defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE) && !defined(DEBUG_BRIDGE_KM)
+ PVR_UNREFERENCED_PARAMETER(pszFunctionName);
+#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",
+ __func__, 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)",
+ __func__, pszIOCName, ui32Index);
+#endif
+ PVR_DPF(PVR_DBG_ERROR,
+"NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue.",
+ __func__);
+ }
+
+ 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)",
+ __func__, 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)",
+ __func__, (unsigned)ui32PrevIndex, (unsigned)ui32Index,
+ pszIOCName);
+#endif
+ PVR_DPF(PVR_DBG_ERROR,
+ "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE "
+ "may help debug this issue.",
+ __func__);
+ }
+
+ 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,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
+ PVR_UNREFERENCED_PARAMETER(psBridgeIn);
+
+ if (!OSProcHasPrivSrvInit() ||
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) ||
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN)) {
+ psRetOUT->eError = PVRSRV_ERROR_GENERIC;
+ return 0;
+ }
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
+ psPerProc->bInitProcess = IMG_TRUE;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+static int PVRSRVInitSrvDisconnectBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT *psInitSrvDisconnectIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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 = IMG_FALSE;
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_FALSE);
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RAN, IMG_TRUE);
+
+ psRetOUT->eError =
+ PVRSRVFinaliseSystem(psInitSrvDisconnectIN->bInitSuccesful);
+
+ PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL,
+ (IMG_BOOL)(((psRetOUT->eError == PVRSRV_OK) &&
+ (psInitSrvDisconnectIN->
+ bInitSuccesful))));
+
+ return 0;
+}
+
+static int PVRSRVEventObjectWaitBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT *psEventObjectWaitIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN *psEventObjectOpenIN,
+ struct PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN *psEventObjectOpenOUT,
+ struct 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,
+ struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE *psEventObjectCloseIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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;
+}
+
+enum 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);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_CACHE_FLUSH_DRM,
+ PVRSRVCacheFlushDRIBW);
+
+ 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(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_SYNC_OPS,
+ PVRSRVModifySyncOpsBW);
+
+ SetSGXDispatchTableEntry();
+
+ 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;
+}
+
+static int bridged_check_cmd(u32 cmd_id)
+{
+ if (PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN)) {
+ if (!PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Initialisation failed. Driver unusable.",
+ __func__);
+ return 1;
+ }
+ } else {
+ if (PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Initialisation is in progress",
+ __func__);
+ return 1;
+ } else {
+ switch (cmd_id) {
+ 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.",
+ __func__);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int bridged_ioctl(struct file *filp, u32 cmd, void *in, void *out,
+ size_t in_size,
+ struct PVRSRV_PER_PROCESS_DATA *per_proc)
+{
+ int err = -EFAULT;
+
+ switch (PVRSRV_IOWR(cmd)) {
+ case PVRSRV_BRIDGE_ENUM_DEVICES:
+ err = PVRSRVEnumerateDevicesBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO:
+ err = PVRSRVAcquireDeviceDataBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_RELEASE_DEVICEINFO:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT:
+ err = PVRSRVCreateDeviceMemContextBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT:
+ err = PVRSRVDestroyDeviceMemContextBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO:
+ err = PVRSRVGetDeviceMemHeapInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_ALLOC_DEVICEMEM:
+ err = PVRSRVAllocDeviceMemBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_FREE_DEVICEMEM:
+ err = PVRSRVFreeDeviceMemBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_GETFREE_DEVICEMEM:
+ err = PVRSRVGetFreeDeviceMemBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_CREATE_COMMANDQUEUE:
+ case PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA:
+ err = PVRMMapOSMemHandleToMMapDataBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_CONNECT_SERVICES:
+ err = PVRSRVConnectBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_DISCONNECT_SERVICES:
+ err = PVRSRVDisconnectBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_WRAP_DEVICE_MEM:
+ case PVRSRV_BRIDGE_GET_DEVICEMEMINFO:
+ case PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM:
+ case PVRSRV_BRIDGE_FREE_DEV_VIRTMEM:
+ case PVRSRV_BRIDGE_MAP_EXT_MEMORY:
+ case PVRSRV_BRIDGE_UNMAP_EXT_MEMORY:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ err = PVRSRVMapDeviceMemoryBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_UNMAP_DEV_MEMORY:
+ err = PVRSRVUnmapDeviceMemoryBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY:
+ err = PVRSRVMapDeviceClassMemoryBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY:
+ err = PVRSRVUnmapDeviceClassMemoryBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER:
+ case PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_EXPORT_DEVICEMEM:
+ err = PVRSRVExportDeviceMemBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_RELEASE_MMAP_DATA:
+ err = PVRMMapReleaseMMapDataBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_CACHE_FLUSH_DRM:
+ err = PVRSRVCacheFlushDRIBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT:
+ case PVRSRV_BRIDGE_REGISTER_SIM_PROCESS:
+ case PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS:
+ case PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE:
+ case PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE:
+ case PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP:
+ case PVRSRV_BRIDGE_GET_FB_STATS:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_GET_MISC_INFO:
+ err = PVRSRVGetMiscInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_RELEASE_MISC_INFO:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+#if defined(PDUMP)
+ case PVRSRV_BRIDGE_PDUMP_INIT:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_MEMPOL:
+ err = PDumpMemPolBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_DUMPMEM:
+ err = PDumpMemBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_REG:
+ err = PDumpRegWithFlagsBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_REGPOL:
+ err = PDumpRegPolBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_COMMENT:
+ err = PDumpCommentBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_SETFRAME:
+ err = PDumpSetFrameBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_ISCAPTURING:
+ err = PDumpIsCaptureFrameBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_DUMPBITMAP:
+ err = PDumpBitmapBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_DUMPREADREG:
+ err = PDumpReadRegBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_SYNCPOL:
+ err = PDumpSyncPolBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_DUMPSYNC:
+ err = PDumpSyncDumpBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_DRIVERINFO:
+ err = PDumpDriverInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_PDREG:
+ err = PDumpPDRegBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR:
+ err = PDumpPDDevPAddrBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ:
+ err = PDumpCycleCountRegReadBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_STARTINITPHASE:
+ err = PDumpStartInitPhaseBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_PDUMP_STOPINITPHASE:
+ err = PDumpStopInitPhaseBW(cmd, in, out, per_proc);
+ break;
+#endif
+
+ case PVRSRV_BRIDGE_GET_OEMJTABLE:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_ENUM_CLASS:
+ err = PVRSRVEnumerateDCBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE:
+ err = PVRSRVOpenDCDeviceBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE:
+ err = PVRSRVCloseDCDeviceBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS:
+ err = PVRSRVEnumDCFormatsBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS:
+ err = PVRSRVEnumDCDimsBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER:
+ err = PVRSRVGetDCSystemBufferBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_GET_DISPCLASS_INFO:
+ err = PVRSRVGetDCInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN:
+ err = PVRSRVCreateDCSwapChainBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN:
+ err = PVRSRVDestroyDCSwapChainBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT:
+ err = PVRSRVSetDCDstRectBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT:
+ err = PVRSRVSetDCSrcRectBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY:
+ err = PVRSRVSetDCDstColourKeyBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY:
+ err = PVRSRVSetDCSrcColourKeyBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS:
+ err = PVRSRVGetDCBuffersBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER:
+ err = PVRSRVSwapToDCBufferBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM:
+ err = PVRSRVSwapToDCSystemBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE:
+ err = PVRSRVOpenBCDeviceBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE:
+ err = PVRSRVCloseBCDeviceBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO:
+ err = PVRSRVGetBCInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER:
+ err = PVRSRVGetBCBufferBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_WRAP_EXT_MEMORY:
+ err = PVRSRVWrapExtMemoryBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY:
+ err = PVRSRVUnwrapExtMemoryBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM:
+ err = PVRSRVAllocSharedSysMemoryBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM:
+ err = PVRSRVFreeSharedSysMemoryBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_MAP_MEMINFO_MEM:
+ err = PVRSRVMapMemInfoMemBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR:
+ err = MMU_GetPDDevPAddrBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_INITSRV_CONNECT:
+ err = PVRSRVInitSrvConnectBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_INITSRV_DISCONNECT:
+ err = PVRSRVInitSrvDisconnectBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_EVENT_OBJECT_WAIT:
+ err = PVRSRVEventObjectWaitBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_EVENT_OBJECT_OPEN:
+ err = PVRSRVEventObjectOpenBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE:
+ err = PVRSRVEventObjectCloseBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_MODIFY_SYNC_OPS:
+ err = PVRSRVModifySyncOpsBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_GETCLIENTINFO:
+ err = SGXGetClientInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO:
+ err = SGXReleaseClientInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO:
+ err = SGXGetInternalDevInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_DOKICK:
+ err = SGXDoKickBW(cmd, in, out, in_size, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR:
+ case PVRSRV_BRIDGE_SGX_READREGISTRYDWORD:
+ case PVRSRV_BRIDGE_SGX_SCHEDULECOMMAND:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE:
+ err = SGX2DQueryBlitsCompleteBW(filp, cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_GETMMUPDADDR:
+ err = DummyBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_SUBMITTRANSFER:
+ err = SGXSubmitTransferBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_GETMISCINFO:
+ err = SGXGetMiscInfoBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT:
+ err = SGXGetInfoForSrvinitBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_DEVINITPART2:
+ err = SGXDevInitPart2BW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC:
+ err = SGXFindSharedPBDescBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC:
+ err = SGXUnrefSharedPBDescBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:
+ err = SGXAddSharedPBDescBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT:
+ err = SGXRegisterHWRenderContextBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET:
+ err = SGXFlushHWRenderTargetBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT:
+ err = SGXUnregisterHWRenderContextBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT:
+ err = SGXRegisterHWTransferContextBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT:
+ err = SGXUnregisterHWTransferContextBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS:
+ err = SGXReadDiffCountersBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_READ_HWPERF_CB:
+ err = SGXReadHWPerfCBBW(cmd, in, out, per_proc);
+ break;
+
+ case PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES:
+ err = SGXScheduleProcessQueuesBW(cmd, in, out, per_proc);
+ break;
+
+#if defined(PDUMP)
+ case PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY:
+ err = SGXPDumpBufferArrayBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS:
+ err = SGXPDump3DSignatureRegistersBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS:
+ err = SGXPDumpCounterRegistersBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS:
+ err = SGXPDumpTASignatureRegistersBW(cmd, in, out, per_proc);
+ break;
+ case PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB:
+ err = SGXPDumpHWPerfCBBW(cmd, in, out, per_proc);
+ break;
+#endif
+
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "%s: cmd = %d is out if range!",
+ __func__, cmd);
+ }
+
+ return err;
+}
+
+int BridgedDispatchKM(struct file *filp, struct PVRSRV_PER_PROCESS_DATA *pd,
+ struct PVRSRV_BRIDGE_PACKAGE *pkg)
+{
+
+ void *in;
+ void *out;
+ u32 bid = pkg->ui32BridgeID;
+ int err = -EFAULT;
+ struct SYS_DATA *psSysData;
+
+#if defined(DEBUG_BRIDGE_KM)
+ g_BridgeDispatchTable[bid].ui32CallCount++;
+ g_BridgeGlobalStats.ui32IOCTLCount++;
+#endif
+ if (!pd->bInitProcess && bridged_check_cmd(bid))
+ goto return_fault;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ goto return_fault;
+
+ in = ((struct ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
+ out = (void *)((u8 *)in + PVRSRV_MAX_BRIDGE_IN_SIZE);
+
+ if (pkg->ui32InBufferSize > 0 &&
+ CopyFromUserWrapper(pd, bid, in, pkg->pvParamIn,
+ pkg->ui32InBufferSize) != PVRSRV_OK)
+ goto return_fault;
+
+ if (bid >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: ui32BridgeID = %d is out if range!", __func__,
+ bid);
+ goto return_fault;
+ }
+
+ err = bridged_ioctl(filp, bid, in, out, pkg->ui32InBufferSize, pd);
+
+ if (err < 0)
+ goto return_fault;
+
+ if (CopyToUserWrapper(pd, bid, pkg->pvParamOut, out,
+ pkg->ui32OutBufferSize) != PVRSRV_OK)
+ goto return_fault;
+
+ err = 0;
+return_fault:
+ ReleaseHandleBatch(pd);
+ return err;
+}
diff --git a/drivers/gpu/pvr/bridged_pvr_bridge.h b/drivers/gpu/pvr/bridged_pvr_bridge.h
new file mode 100644
index 00000000000..188fdedf092
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_pvr_bridge.h
@@ -0,0 +1,158 @@
+/**********************************************************************
+ *
+ * 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"
+
+#define PVRSRV_GET_BRIDGE_ID(X) _IOC_NR(X)
+
+#if defined(DEBUG_BRIDGE_KM)
+enum PVRSRV_ERROR CopyFromUserWrapper(struct PVRSRV_PER_PROCESS_DATA *pProcData,
+ u32 ui32BridgeID, void *pvDest,
+ void __user *pvSrc, u32 ui32Size);
+enum PVRSRV_ERROR CopyToUserWrapper(struct PVRSRV_PER_PROCESS_DATA *pProcData,
+ u32 ui32BridgeID, void __user *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)
+
+static inline enum PVRSRV_ERROR NewHandleBatch(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32BatchSize)
+{
+ enum PVRSRV_ERROR eError;
+
+ PVR_ASSERT(!psPerProc->bHandlesBatched);
+
+ eError = PVRSRVNewHandleBatch(psPerProc->psHandleBase, ui32BatchSize);
+
+ if (eError == PVRSRV_OK)
+ psPerProc->bHandlesBatched = IMG_TRUE;
+
+ return eError;
+}
+
+#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, NewHandleBatch(psPerProc, \
+ ui32BatchSize))
+
+static inline enum PVRSRV_ERROR
+CommitHandleBatch(struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVR_ASSERT(psPerProc->bHandlesBatched);
+
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ return PVRSRVCommitHandleBatch(psPerProc->psHandleBase);
+}
+
+#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc) \
+ ASSIGN_AND_EXIT_ON_ERROR(error, CommitHandleBatch(psPerProc))
+
+static inline void ReleaseHandleBatch(struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->bHandlesBatched) {
+ psPerProc->bHandlesBatched = IMG_FALSE;
+
+ PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
+ }
+}
+
+int DummyBW(u32 ui32BridgeID, void *psBridgeIn, void *psBridgeOut,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+struct PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY {
+ int (*pfFunction)(u32 ui32BridgeID, void *psBridgeIn, void *psBridgeOut,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+#if defined(DEBUG_BRIDGE_KM)
+ const char *pszIOCName;
+ const char *pszFunctionName;
+ u32 ui32CallCount;
+ u32 ui32CopyFromUserTotalBytes;
+ u32 ui32CopyToUserTotalBytes;
+#endif
+};
+
+#define BRIDGE_DISPATCH_TABLE_ENTRY_COUNT (PVRSRV_BRIDGE_LAST_SGX_CMD+1)
+#define PVRSRV_BRIDGE_LAST_DEVICE_CMD PVRSRV_BRIDGE_LAST_SGX_CMD
+
+extern struct PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
+ g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
+
+void _SetDispatchTableEntry(u32 ui32Index,
+ const char *pszIOCName,
+ int (*pfFunction) (u32 ui32BridgeID,
+ void *psBridgeIn,
+ void *psBridgeOut,
+ struct PVRSRV_PER_PROCESS_DATA *
+ psPerProc),
+ const char *pszFunctionName);
+
+#define SetDispatchTableEntry(ui32Index, pfFunction) \
+ _SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, \
+ (int (*)(u32 ui32BridgeID, void *psBridgeIn, void *psBridgeOut, \
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc))pfFunction, #pfFunction)
+
+#define DISPATCH_TABLE_GAP_THRESHOLD 5
+
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_ASSERT(X == PVRSRV_GET_BRIDGE_ID(Y))
+#else
+#define PVRSRV_BRIDGE_ASSERT_CMD(X, Y) PVR_UNREFERENCED_PARAMETER(X)
+#endif
+
+#if defined(DEBUG_BRIDGE_KM)
+struct PVRSRV_BRIDGE_GLOBAL_STATS {
+ u32 ui32IOCTLCount;
+ u32 ui32TotalCopyFromUserBytes;
+ u32 ui32TotalCopyToUserBytes;
+};
+
+extern struct PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
+#endif
+
+enum PVRSRV_ERROR CommonBridgeInit(void);
+
+int BridgedDispatchKM(struct file *filp,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ struct PVRSRV_BRIDGE_PACKAGE *psBridgePackageKM);
+
+#endif
diff --git a/drivers/gpu/pvr/bridged_sgx_bridge.c b/drivers/gpu/pvr/bridged_sgx_bridge.c
new file mode 100644
index 00000000000..b2dae3790c6
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_sgx_bridge.c
@@ -0,0 +1,1871 @@
+/**********************************************************************
+ *
+ * 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 <linux/errno.h>
+
+#include <stddef.h>
+
+#include "img_defs.h"
+
+#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"
+#include "bridged_pvr_bridge.h"
+#include "bridged_sgx_bridge.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+#include "pvr_events.h"
+
+int SGXGetClientInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+ struct 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;
+}
+
+int SGXReleaseClientInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct 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 =
+ (struct PVRSRV_SGXDEV_INFO *)((struct PVRSRV_DEVICE_NODE *)
+ hDevCookieInt)->pvDevice;
+
+ PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
+
+ psDevInfo->ui32ClientRefCount--;
+
+ psRetOUT->eError = PVRSRV_OK;
+
+ return 0;
+}
+
+int SGXGetInternalDevInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+ struct 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;
+}
+
+/* Convert the IOCTL parameter from "old" to "new" format. */
+static int kick_compat_conv(struct PVRSRV_BRIDGE_IN_DOKICK *kick,
+ size_t in_size)
+{
+ struct SGX_CCB_KICK *ccb;
+ size_t diff;
+
+ ccb = &kick->sCCBKick;
+
+ diff = sizeof(ccb->ah3DStatusSyncInfo[0]) *
+ (SGX_MAX_3D_STATUS_VALS - SGX_MAX_3D_STATUS_VALS_OLD);
+ if (sizeof(*kick) - in_size != diff)
+ return -EINVAL;
+
+ /* Trailing size at the end of struct to move. */
+ diff = sizeof(*kick) - offsetof(typeof(*kick),
+ sCCBKick.ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS]);
+ memmove(&kick->sCCBKick.ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS],
+ &kick->sCCBKick.ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS_OLD],
+ diff);
+
+ return 0;
+}
+
+int SGXDoKickBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ size_t in_size,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ int max_3dstat_vals;
+ u32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DOKICK);
+
+ max_3dstat_vals = SGX_MAX_3D_STATUS_VALS;
+ if (unlikely(in_size != sizeof(*psDoKickIN))) {
+ max_3dstat_vals = SGX_MAX_3D_STATUS_VALS_OLD;
+ if (kick_compat_conv(psDoKickIN, in_size) != 0) {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return -EINVAL;
+ }
+
+ }
+ 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 (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;
+ }
+
+ 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 =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ahTAStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psRetOUT->eError != PVRSRV_OK)
+ return 0;
+ }
+
+ if (psDoKickIN->sCCBKick.ui32Num3DStatusVals > max_3dstat_vals) {
+ psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ for (i = 0; i < psDoKickIN->sCCBKick.ui32Num3DStatusVals; i++) {
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ psDoKickIN->sCCBKick.ah3DStatusSyncInfo[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ return 0;
+ }
+
+ if (psDoKickIN->sCCBKick.ui32NumDstSyncObjects > 0) {
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.
+ hKernelHWSyncListMemInfo,
+ psDoKickIN->sCCBKick.
+ hKernelHWSyncListMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psDoKickIN->sCCBKick.sDstSyncHandle,
+ psDoKickIN->sCCBKick.sDstSyncHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ return 0;
+ }
+
+ psRetOUT->eError = SGXDoKickKM(hDevCookieInt, &psDoKickIN->sCCBKick,
+ max_3dstat_vals);
+
+ return 0;
+}
+
+int SGXScheduleProcessQueuesBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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;
+}
+
+int SGXSubmitTransferBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ struct PVRSRV_TRANSFER_SGX_KICK *psKick;
+ u32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_SUBMITTRANSFER);
+ PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
+
+ 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;
+}
+
+int SGXGetMiscInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ struct SGX_MISC_INFO sMiscInfo;
+ struct 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;
+
+ psDeviceNode = hDevCookieInt;
+ PVR_ASSERT(psDeviceNode != NULL);
+ if (psDeviceNode == NULL)
+ return -EFAULT;
+
+ psDevInfo = psDeviceNode->pvDevice;
+
+ psRetOUT->eError = CopyFromUserWrapper(psPerProc, ui32BridgeID,
+ &sMiscInfo,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ sizeof(struct SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ return -EFAULT;
+
+ if (sMiscInfo.eRequest == SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB) {
+ void *pAllocated;
+ void *hAllocatedHandle;
+ void __user *psTmpUserData;
+ u32 allocatedSize;
+
+ allocatedSize =
+ (u32) (sMiscInfo.uData.sRetrieveCB.ui32ArraySize *
+ sizeof(struct PVRSRV_SGX_HWPERF_CBDATA));
+
+ ASSIGN_AND_EXIT_ON_ERROR(psRetOUT->eError,
+ OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize,
+ &pAllocated,
+ &hAllocatedHandle));
+
+ psTmpUserData = (void __force __user *)
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData;
+ sMiscInfo.uData.sRetrieveCB.psHWPerfData = pAllocated;
+
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo,
+ &sMiscInfo, psDeviceNode);
+ 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 =
+ (void __force *)psTmpUserData;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ allocatedSize, pAllocated, hAllocatedHandle);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ return -EFAULT;
+ } else {
+ psRetOUT->eError = SGXGetMiscInfoKM(psDevInfo,
+ &sMiscInfo, psDeviceNode);
+
+ if (psRetOUT->eError != PVRSRV_OK)
+ return 0;
+ }
+
+ psRetOUT->eError = CopyToUserWrapper(psPerProc,
+ ui32BridgeID,
+ psSGXGetMiscInfoIN->psMiscInfo,
+ &sMiscInfo,
+ sizeof(struct SGX_MISC_INFO));
+ if (psRetOUT->eError != PVRSRV_OK)
+ return -EFAULT;
+ return 0;
+}
+
+int SGXReadDiffCountersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS *psSGXReadDiffCountersIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS
+ *psSGXReadDiffCountersOUT,
+ struct 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,
+ &psSGXReadDiffCountersOUT->ui32Time,
+ &psSGXReadDiffCountersOUT->bActive,
+ &psSGXReadDiffCountersOUT->sDiffs);
+
+ return 0;
+}
+
+int SGXReadHWPerfCBBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ struct 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));
+
+ 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;
+}
+
+int SGXDevInitPart2BW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ enum PVRSRV_ERROR eError;
+ IMG_BOOL bDissociateFailed = IMG_FALSE;
+ IMG_BOOL bLookupFailed = IMG_FALSE;
+ IMG_BOOL bReleaseFailed = IMG_FALSE;
+ 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 |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupHandle(psPerProc->psHandleBase, &hDummy,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bLookupFailed |= (IMG_BOOL) (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 |= (IMG_BOOL) (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 |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBEventKickerMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBEventKickerMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXHostCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXHostCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXTA3DCtlMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXTA3DCtlMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXMiscMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXMiscMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.
+ hKernelHWPerfCBMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelHWPerfCBMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
+ &psSGXDevInitPart2IN->sInitInfo.
+ hKernelEDMStatusBufferMemInfo,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelEDMStatusBufferMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ bReleaseFailed |= (IMG_BOOL)(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 |= (IMG_BOOL) (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 |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBCtlMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelCCBEventKickerMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXHostCtlMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXTA3DCtlMemInfo);
+ bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelSGXMiscMemInfo);
+ bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelHWPerfCBMemInfo);
+ bDissociateFailed |= (IMG_BOOL) (eError != PVRSRV_OK);
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt,
+ psSGXDevInitPart2IN->sInitInfo.
+ hKernelEDMStatusBufferMemInfo);
+ bDissociateFailed |= (IMG_BOOL) (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 |= (IMG_BOOL) (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,
+ (struct 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;
+}
+
+int SGXRegisterHWRenderContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT
+ *psSGXRegHWRenderContextIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT
+ *psSGXRegHWRenderContextOUT,
+ struct 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;
+}
+
+int SGXUnregisterHWRenderContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT
+ *psSGXUnregHWRenderContextIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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;
+}
+
+int SGXRegisterHWTransferContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT
+ *psSGXRegHWTransferContextIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT
+ *psSGXRegHWTransferContextOUT,
+ struct 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;
+}
+
+int SGXUnregisterHWTransferContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT
+ *psSGXUnregHWTransferContextIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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;
+}
+
+int SGXFlushHWRenderTargetBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET
+ *psSGXFlushHWRenderTargetIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct 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;
+}
+
+int SGX2DQueryBlitsCompleteBW(struct file *filp, u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ void *pvSyncInfo;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ struct PVRSRV_FILE_PRIVATE_DATA *priv = filp->private_data;
+
+ 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;
+
+ if (ps2DQueryBltsCompleteIN->type == _PVR_SYNC_WAIT_FLIP ||
+ ps2DQueryBltsCompleteIN->type == _PVR_SYNC_WAIT_UPDATE) {
+ if (pvr_flip_event_req(priv,
+ (long)ps2DQueryBltsCompleteIN->
+ hKernSyncInfo,
+ ps2DQueryBltsCompleteIN->type,
+ ps2DQueryBltsCompleteIN->user_data))
+ psRetOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase, &pvSyncInfo,
+ ps2DQueryBltsCompleteIN->hKernSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if (psRetOUT->eError != PVRSRV_OK)
+ return 0;
+
+ psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)((struct PVRSRV_DEVICE_NODE *)
+ hDevCookieInt)->pvDevice;
+
+ if (ps2DQueryBltsCompleteIN->type == _PVR_SYNC_WAIT_EVENT) {
+ if (pvr_sync_event_req(priv,
+ (struct PVRSRV_KERNEL_SYNC_INFO *)pvSyncInfo,
+ ps2DQueryBltsCompleteIN->user_data))
+ psRetOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ return 0;
+ }
+
+ psRetOUT->eError =
+ SGX2DQueryBlitsCompleteKM(psDevInfo,
+ (struct PVRSRV_KERNEL_SYNC_INFO *)
+ pvSyncInfo,
+ ps2DQueryBltsCompleteIN->type == _PVR_SYNC_WAIT_BLOCK);
+
+ return 0;
+}
+
+int SGXFindSharedPBDescBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+ struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ struct 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,
+ &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 =
+ NULL;
+
+ 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);
+
+ for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) {
+ struct 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(struct 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;
+}
+
+int SGXUnrefSharedPBDescBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+ struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC
+ *psSGXUnrefSharedPBDescOUT,
+ struct 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;
+}
+
+int SGXAddSharedPBDescBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+ struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ void *hDevCookieInt;
+ struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ u32 ui32KernelMemInfoHandlesCount =
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount;
+ int ret = 0;
+ void **phKernelMemInfoHandles = NULL;
+ struct PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfos = NULL;
+ u32 i;
+ enum 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;
+
+ if (!OSAccessOK(PVR_VERIFY_READ,
+ psSGXAddSharedPBDescIN->phKernelMemInfoHandles,
+ ui32KernelMemInfoHandlesCount * sizeof(void *))) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC:"
+ " Invalid phKernelMemInfos pointer", __func__);
+ ret = -EFAULT;
+ goto PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC_RETURN_RESULT;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32KernelMemInfoHandlesCount * sizeof(void *),
+ (void **)&phKernelMemInfoHandles, NULL);
+ 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(struct PVRSRV_KERNEL_MEM_INFO *),
+ (void **)&ppsKernelMemInfos, NULL);
+ 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);
+
+ 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,
+ 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, NULL);
+ if (ppsKernelMemInfos)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSGXAddSharedPBDescIN->ui32KernelMemInfoHandlesCount
+ * sizeof(struct PVRSRV_KERNEL_MEM_INFO *),
+ (void *)ppsKernelMemInfos, NULL);
+
+ if (ret == 0 && eError == PVRSRV_OK)
+ COMMIT_HANDLE_BATCH_OR_ERROR(psSGXAddSharedPBDescOUT->eError,
+ psPerProc);
+
+ psSGXAddSharedPBDescOUT->eError = eError;
+
+ return ret;
+}
+
+int SGXGetInfoForSrvinitBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+ struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+ struct 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++) {
+ struct 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(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ struct SGX_KICKTA_DUMP_BUFFER *psBufferArray,
+ u32 ui32BufferArrayLength, IMG_BOOL bDumpPolls)
+{
+ u32 i;
+
+ for (i = 0; i < ui32BufferArrayLength; i++) {
+ struct SGX_KICKTA_DUMP_BUFFER *psBuffer;
+ struct PVRSRV_KERNEL_MEM_INFO *psCtrlMemInfoKM;
+ char *pszName;
+ void *hUniqueTag;
+ u32 ui32Offset;
+
+ psBuffer = &psBufferArray[i];
+ pszName = psBuffer->pszName;
+ if (!pszName)
+ pszName = "Nameless buffer";
+
+ hUniqueTag =
+ MAKEUNIQUETAG((struct PVRSRV_KERNEL_MEM_INFO *)psBuffer->
+ hKernelMemInfo);
+
+ psCtrlMemInfoKM =
+ ((struct PVRSRV_KERNEL_MEM_INFO *)psBuffer->
+ hKernelMemInfo)->psKernelSyncInfo->psSyncDataMemInfoKM;
+ ui32Offset =
+ offsetof(struct PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+
+ 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,
+ (struct 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,
+ (struct PVRSRV_KERNEL_MEM_INFO *)psBuffer->
+ hKernelMemInfo,
+ psBuffer->ui32Start,
+ psBuffer->ui32BackEndLength, 0, hUniqueTag);
+
+ if (bDumpPolls) {
+ PDUMPMEMPOL(psCtrlMemInfoKM, ui32Offset,
+ 0, 0xFFFFFFFF,
+ PDUMP_POLL_OPERATOR_NOTEQUAL,
+ IMG_FALSE, IMG_FALSE,
+ 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,
+ (struct PVRSRV_KERNEL_MEM_INFO *)psBuffer->
+ hKernelMemInfo,
+ 0, psBuffer->ui32End, 0, hUniqueTag);
+ }
+ }
+}
+
+int SGXPDumpBufferArrayBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 i;
+ struct SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
+ u32 ui32BufferArrayLength = psPDumpBufferArrayIN->ui32BufferArrayLength;
+ u32 ui32BufferArraySize =
+ ui32BufferArrayLength * sizeof(struct SGX_KICKTA_DUMP_BUFFER);
+ enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize,
+ (void **)&psKickTADumpBuffer, NULL) != PVRSRV_OK)
+ return -ENOMEM;
+
+ if (CopyFromUserWrapper(psPerProc, ui32BridgeID, psKickTADumpBuffer,
+ psPDumpBufferArrayIN->psBufferArray,
+ ui32BufferArraySize) != PVRSRV_OK) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize,
+ psKickTADumpBuffer, NULL);
+ 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 (eError == PVRSRV_OK)
+ DumpBufferArray(psPerProc, psKickTADumpBuffer,
+ ui32BufferArrayLength,
+ psPDumpBufferArrayIN->bDumpPolls);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize,
+ psKickTADumpBuffer, NULL);
+
+ return 0;
+}
+
+int SGXPDump3DSignatureRegistersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS
+ *psPDump3DSignatureRegistersIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 ui32RegisterArraySize =
+ psPDump3DSignatureRegistersIN->ui32NumRegisters * sizeof(u32);
+ u32 *pui32Registers = NULL;
+ int ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ goto ExitNoError;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (void **)&pui32Registers, NULL) != 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:
+ ret = 0;
+Exit:
+ if (pui32Registers != NULL)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize,
+ pui32Registers, NULL);
+
+ return ret;
+}
+
+int SGXPDumpCounterRegistersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS
+ *psPDumpCounterRegistersIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 ui32RegisterArraySize =
+ psPDumpCounterRegistersIN->ui32NumRegisters * sizeof(u32);
+ u32 *pui32Registers = NULL;
+ int ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ 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, NULL) != 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, NULL);
+
+ return ret;
+}
+
+int SGXPDumpTASignatureRegistersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS
+ *psPDumpTASignatureRegistersIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ u32 ui32RegisterArraySize =
+ psPDumpTASignatureRegistersIN->ui32NumRegisters * sizeof(u32);
+ u32 *pui32Registers = NULL;
+ int ret = -EFAULT;
+
+ PVR_UNREFERENCED_PARAMETER(psBridgeOut);
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID,
+ PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS);
+
+ if (ui32RegisterArraySize == 0)
+ goto ExitNoError;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32RegisterArraySize,
+ (void **)&pui32Registers, NULL) != 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:
+ ret = 0;
+Exit:
+ if (pui32Registers != NULL)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32RegisterArraySize,
+ pui32Registers, NULL);
+
+ return ret;
+}
+
+int SGXPDumpHWPerfCBBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ struct 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 = ((struct PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
+ PDumpHWPerfCBKM(&psPDumpHWPerfCBIN->szFileName[0],
+ psPDumpHWPerfCBIN->ui32FileOffset,
+ psDevInfo->psKernelHWPerfCBMemInfo->sDevVAddr,
+ psDevInfo->psKernelHWPerfCBMemInfo->ui32AllocSize,
+ psPDumpHWPerfCBIN->ui32PDumpFlags);
+
+ return 0;
+}
+
+#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_SCHEDULECOMMAND, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE,
+ SGX2DQueryBlitsCompleteBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_GETMMUPDADDR, DummyBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SUBMITTRANSFER,
+ SGXSubmitTransferBW);
+ 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);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT,
+ SGXRegisterHWTransferContextBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT,
+ SGXUnregisterHWTransferContextBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS,
+ SGXReadDiffCountersBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_READ_HWPERF_CB,
+ SGXReadHWPerfCBBW);
+
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES,
+ SGXScheduleProcessQueuesBW);
+
+#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
+}
diff --git a/drivers/gpu/pvr/bridged_sgx_bridge.h b/drivers/gpu/pvr/bridged_sgx_bridge.h
new file mode 100644
index 00000000000..c2a8c476dd5
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_sgx_bridge.h
@@ -0,0 +1,167 @@
+/**********************************************************************
+ *
+ * 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__
+
+void SetSGXDispatchTableEntry(void);
+
+int SGXGetClientInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_GETCLIENTINFO *psGetClientInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO *psGetClientInfoOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXReleaseClientInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO *psReleaseClientInfoIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXGetInternalDevInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO *psSGXGetInternalDevInfoIN,
+ struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *psSGXGetInternalDevInfoOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXDoKickBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_DOKICK *psDoKickIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT, size_t in_size,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXScheduleProcessQueuesBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES *psScheduleProcQIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXSubmitTransferBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER *psSubmitTransferIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXGetMiscInfoBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO *psSGXGetMiscInfoIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXReadDiffCountersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS *psSGXReadDiffCountersIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS
+ *psSGXReadDiffCountersOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXReadHWPerfCBBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB *psSGXReadHWPerfCBOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXDevInitPart2BW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2 *psSGXDevInitPart2IN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXRegisterHWRenderContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT
+ *psSGXRegHWRenderContextIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT
+ *psSGXRegHWRenderContextOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXUnregisterHWRenderContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT
+ *psSGXUnregHWRenderContextIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXRegisterHWTransferContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT
+ *psSGXRegHWTransferContextIN,
+ struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT
+ *psSGXRegHWTransferContextOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXUnregisterHWTransferContextBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT
+ *psSGXUnregHWTransferContextIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXFlushHWRenderTargetBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET
+ *psSGXFlushHWRenderTargetIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGX2DQueryBlitsCompleteBW(struct file *filp, u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE *ps2DQueryBltsCompleteIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXFindSharedPBDescBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescIN,
+ struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC *psSGXFindSharedPBDescOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXUnrefSharedPBDescBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC *psSGXUnrefSharedPBDescIN,
+ struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC
+ *psSGXUnrefSharedPBDescOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXAddSharedPBDescBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescIN,
+ struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC *psSGXAddSharedPBDescOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXGetInfoForSrvinitBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitIN,
+ struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT *psSGXInfoForSrvinitOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+#if defined(PDUMP)
+int SGXPDumpBufferArrayBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY *psPDumpBufferArrayIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXPDump3DSignatureRegistersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS
+ *psPDump3DSignatureRegistersIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXPDumpCounterRegistersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS
+ *psPDumpCounterRegistersIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXPDumpTASignatureRegistersBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS
+ *psPDumpTASignatureRegistersIN,
+ void *psBridgeOut, struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+int SGXPDumpHWPerfCBBW(u32 ui32BridgeID,
+ struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
+ struct PVRSRV_BRIDGE_RETURN *psRetOUT,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+#endif
+#endif
diff --git a/drivers/gpu/pvr/bridged_support.c b/drivers/gpu/pvr/bridged_support.c
new file mode 100644
index 00000000000..499a3df13bb
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_support.c
@@ -0,0 +1,77 @@
+/**********************************************************************
+ *
+ * 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"
+
+enum PVRSRV_ERROR
+PVRSRVLookupOSMemHandle(struct PVRSRV_HANDLE_BASE *psHandleBase,
+ void **phOSMemHandle, void *hMHandle)
+{
+ void *hMHandleInt;
+ enum PVRSRV_HANDLE_TYPE eHandleType;
+ enum PVRSRV_ERROR eError;
+
+ eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
+ &eHandleType, hMHandle);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ switch (eHandleType) {
+ case PVRSRV_HANDLE_TYPE_MEM_INFO:
+ case PVRSRV_HANDLE_TYPE_MEM_INFO_REF:
+ case PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO:
+ {
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)hMHandleInt;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SYNC_INFO:
+ {
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)hMHandleInt;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psSyncInfo->psSyncDataMemInfoKM;
+
+ *phOSMemHandle = psMemInfo->sMemBlk.hOSMemHandle;
+
+ break;
+ }
+ case PVRSRV_HANDLE_TYPE_SOC_TIMER:
+ {
+ *phOSMemHandle = (void *)hMHandleInt;
+ break;
+ }
+ default:
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+
+ return PVRSRV_OK;;
+}
diff --git a/drivers/gpu/pvr/bridged_support.h b/drivers/gpu/pvr/bridged_support.h
new file mode 100644
index 00000000000..96b86433e86
--- /dev/null
+++ b/drivers/gpu/pvr/bridged_support.h
@@ -0,0 +1,35 @@
+/**********************************************************************
+ *
+ * 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"
+
+enum PVRSRV_ERROR PVRSRVLookupOSMemHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phOSMemHandle, void *hMHandle);
+
+#endif
diff --git a/drivers/gpu/pvr/buffer_manager.c b/drivers/gpu/pvr/buffer_manager.c
new file mode 100644
index 00000000000..8f1190c81e7
--- /dev/null
+++ b/drivers/gpu/pvr/buffer_manager.c
@@ -0,0 +1,1493 @@
+/**********************************************************************
+ *
+ * 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"
+#include "mmu.h"
+
+#define MIN(a, b) (a > b ? b : a)
+
+static IMG_BOOL ZeroBuf(struct BM_BUF *pBuf, struct BM_MAPPING *pMapping,
+ u32 ui32Bytes, u32 ui32Flags);
+static void BM_FreeMemory(void *pH, u32 base, struct BM_MAPPING *psMapping);
+static IMG_BOOL BM_ImportMemory(void *pH, size_t uSize,
+ size_t *pActualSize, struct BM_MAPPING **ppsMapping, u32 uFlags,
+ u32 *pBase);
+
+static IMG_BOOL DevMemoryAlloc(struct BM_CONTEXT *pBMContext,
+ struct BM_MAPPING *pMapping, u32 uFlags,
+ u32 dev_vaddr_alignment, struct IMG_DEV_VIRTADDR *pDevVAddr);
+static void DevMemoryFree(struct BM_MAPPING *pMapping);
+
+static IMG_BOOL AllocMemory(struct BM_CONTEXT *pBMContext,
+ struct BM_HEAP *psBMHeap, struct IMG_DEV_VIRTADDR *psDevVAddr,
+ size_t uSize, u32 uFlags, u32 uDevVAddrAlignment,
+ struct BM_BUF *pBuf)
+{
+ struct BM_MAPPING *pMapping;
+ u32 uOffset;
+ struct 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 IMG_FALSE;
+ }
+
+ 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 IMG_FALSE;
+ }
+
+ if (!RA_Alloc(pArena, uSize, (void *)&pMapping, uFlags,
+ uDevVAddrAlignment,
+ (u32 *)&(pBuf->DevVAddr.uiAddr))) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "AllocMemory: RA_Alloc(0x%x) FAILED", uSize);
+ return IMG_FALSE;
+ }
+
+ 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 IMG_FALSE;
+ }
+ }
+
+ pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
+
+ if (uFlags & PVRSRV_MEM_ZERO)
+ if (!ZeroBuf(pBuf, pMapping, uSize,
+ psBMHeap->ui32Attribs | uFlags))
+ return IMG_FALSE;
+ } 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 IMG_FALSE;
+ }
+
+ pBMContext->psDeviceNode->pfnMMUAlloc(
+ psBMHeap->pMMUHeap, uSize,
+ PVRSRV_MEM_USER_SUPPLIED_DEVVADDR,
+ uDevVAddrAlignment, psDevVAddr);
+ pBuf->DevVAddr = *psDevVAddr;
+ } else {
+ pBMContext->psDeviceNode->pfnMMUAlloc(psBMHeap->
+ pMMUHeap, uSize, 0,
+ uDevVAddrAlignment,
+ &pBuf->DevVAddr);
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct BM_MAPPING),
+ (void **)&pMapping, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "AllocMemory: OSAllocMem(0x%x) FAILED");
+ return IMG_FALSE;
+ }
+
+ pBuf->CpuVAddr = NULL;
+ pBuf->hOSMemHandle = NULL;
+ pBuf->CpuPAddr.uiAddr = 0;
+
+ pMapping->CpuVAddr = NULL;
+ pMapping->CpuPAddr.uiAddr = 0;
+ pMapping->DevVAddr = pBuf->DevVAddr;
+ pMapping->psSysAddr = NULL;
+ pMapping->uSize = uSize;
+ pMapping->hOSMemHandle = NULL;
+ }
+
+ 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 IMG_TRUE;
+}
+
+static IMG_BOOL WrapMemory(struct BM_HEAP *psBMHeap,
+ size_t uSize, u32 ui32BaseOffset, IMG_BOOL bPhysContig,
+ struct IMG_SYS_PHYADDR *psAddr, void *pvCPUVAddr, u32 uFlags,
+ struct BM_BUF *pBuf)
+{
+ struct IMG_DEV_VIRTADDR DevVAddr = { 0 };
+ struct BM_MAPPING *pMapping;
+ IMG_BOOL 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) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "WrapMemory: OSAllocMem(0x%x) FAILED",
+ sizeof(*pMapping));
+ return IMG_FALSE;
+ }
+
+ OSMemSet(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,
+ uFlags | PVRSRV_MEM_READ | PVRSRV_MEM_WRITE,
+ 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 + ui32BaseOffset;
+
+ if (uFlags & PVRSRV_MEM_ZERO)
+ if (!ZeroBuf(pBuf, pMapping, uSize, uFlags))
+ return IMG_FALSE;
+
+ 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 IMG_TRUE;
+
+fail_cleanup:
+ if (ui32BaseOffset && pBuf->hOSMemHandle)
+ OSReleaseSubMemHandle(pBuf->hOSMemHandle, uFlags);
+
+ if (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(struct BM_MAPPING), pMapping,
+ NULL);
+
+ return IMG_FALSE;
+}
+
+static IMG_BOOL ZeroBuf(struct BM_BUF *pBuf, struct BM_MAPPING *pMapping,
+ u32 ui32Bytes, u32 ui32Flags)
+{
+ void *pvCpuVAddr;
+
+ if (pBuf->CpuVAddr) {
+ OSMemSet(pBuf->CpuVAddr, 0, ui32Bytes);
+ } else if (pMapping->eCpuMemoryOrigin == hm_contiguous ||
+ pMapping->eCpuMemoryOrigin == hm_wrapped) {
+ pvCpuVAddr = (void __force *)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 IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32Bytes);
+ OSUnMapPhysToLin((void __force __iomem *)pvCpuVAddr, ui32Bytes,
+ PVRSRV_HAP_KERNEL_ONLY |
+ (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK),
+ NULL);
+ } else {
+ u32 ui32BytesRemaining = ui32Bytes;
+ u32 ui32CurrentOffset = 0;
+ struct 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 = (void __force *)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 IMG_FALSE;
+ }
+ OSMemSet(pvCpuVAddr, 0, ui32BlockBytes);
+ OSUnMapPhysToLin((void __force __iomem *)pvCpuVAddr,
+ ui32BlockBytes,
+ PVRSRV_HAP_KERNEL_ONLY |
+ (ui32Flags &
+ PVRSRV_HAP_CACHETYPE_MASK),
+ NULL);
+
+ ui32BytesRemaining -= ui32BlockBytes;
+ ui32CurrentOffset += ui32BlockBytes;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static void FreeBuf(struct BM_BUF *pBuf, u32 ui32Flags)
+{
+ struct 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(struct BM_MAPPING),
+ 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,
+ IMG_FALSE);
+ } 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(struct BM_MAPPING), pMapping, NULL);
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF), pBuf, NULL);
+}
+
+void BM_DestroyContext(void *hBMContext)
+{
+ struct BM_CONTEXT *pBMContext = (struct BM_CONTEXT *)hBMContext;
+ struct BM_HEAP *psBMHeap;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "BM_DestroyContext");
+
+ for (psBMHeap = pBMContext->psBMHeap;
+ psBMHeap != NULL; psBMHeap = psBMHeap->psNext)
+ if (psBMHeap->ui32Attribs &
+ (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG |
+ PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
+ if (psBMHeap->pImportArena) {
+ IMG_BOOL bTestDelete =
+ RA_TestDelete(psBMHeap->pImportArena);
+ BUG_ON(!bTestDelete);
+ }
+
+ ResManFreeResByPtr(pBMContext->hResItem);
+}
+
+static enum PVRSRV_ERROR BM_DestroyContextCallBack(void *pvParam, u32 ui32Param)
+{
+ struct BM_CONTEXT *pBMContext = pvParam;
+ struct BM_CONTEXT **ppBMContext;
+ struct BM_HEAP *psBMHeap, *psTmpBMHeap;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psDeviceNode = pBMContext->psDeviceNode;
+
+ psBMHeap = pBMContext->psBMHeap;
+ while (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_DestroyContext: "
+ "backing store type unsupported");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
+
+ psTmpBMHeap = psBMHeap;
+
+ psBMHeap = psBMHeap->psNext;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_HEAP),
+ psTmpBMHeap, NULL);
+ }
+
+ if (pBMContext->psMMUContext)
+ psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
+
+ if (pBMContext->pBufferHash)
+ HASH_Delete(pBMContext->pBufferHash);
+
+ if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext) {
+ psDeviceNode->sDevMemoryInfo.pBMKernelContext = NULL;
+ } else {
+ for (ppBMContext = &psDeviceNode->sDevMemoryInfo.pBMContext;
+ *ppBMContext; ppBMContext = &((*ppBMContext)->psNext))
+ if (*ppBMContext == pBMContext) {
+ *ppBMContext = pBMContext->psNext;
+ break;
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_CONTEXT),
+ pBMContext, NULL);
+
+ return PVRSRV_OK;
+}
+
+void *BM_CreateContext(struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct IMG_DEV_PHYADDR *psPDDevPAddr,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc, IMG_BOOL *pbCreated)
+{
+ struct BM_CONTEXT *pBMContext;
+ struct BM_HEAP *psBMHeap;
+ struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ IMG_BOOL bKernelContext;
+ struct RESMAN_CONTEXT *hResManContext;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "BM_CreateContext");
+
+ if (psPerProc == NULL) {
+ bKernelContext = IMG_TRUE;
+ hResManContext = psDeviceNode->hResManContext;
+ } else {
+ bKernelContext = IMG_FALSE;
+ hResManContext = psPerProc->hResManContext;
+ }
+
+ if (pbCreated != NULL)
+ *pbCreated = IMG_FALSE;
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ if (bKernelContext == IMG_FALSE)
+ for (pBMContext = psDevMemoryInfo->pBMContext;
+ pBMContext != NULL; pBMContext = pBMContext->psNext)
+ if (ResManFindResourceByPtr(hResManContext,
+ pBMContext->hResItem) ==
+ PVRSRV_OK) {
+ pBMContext->ui32RefCount++;
+ return (void *)pBMContext;
+ }
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_CONTEXT),
+ (void **)&pBMContext, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "BM_CreateContext: Alloc failed");
+ return NULL;
+ }
+ OSMemSet(pBMContext, 0, sizeof(struct 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;
+
+ psBMHeap = pBMContext->psBMSharedHeap;
+ while (psBMHeap) {
+ switch (psBMHeap->sDevArena.DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ psDeviceNode->
+ pfnMMUInsertHeap(pBMContext->
+ psMMUContext,
+ psBMHeap->
+ pMMUHeap);
+ break;
+ }
+ }
+ psBMHeap = psBMHeap->psNext;
+ }
+ pBMContext->psNext = psDevMemoryInfo->pBMContext;
+ 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 = IMG_TRUE;
+ return (void *)pBMContext;
+
+cleanup:
+ BM_DestroyContextCallBack(pBMContext, 0);
+
+ return NULL;
+}
+
+void *BM_CreateHeap(void *hBMContext,
+ struct DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
+{
+ struct BM_CONTEXT *pBMContext = (struct BM_CONTEXT *)hBMContext;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = pBMContext->psDeviceNode;
+ struct BM_HEAP *psBMHeap;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "BM_CreateHeap");
+
+ if (pBMContext->ui32RefCount > 0) {
+ psBMHeap = pBMContext->psBMHeap;
+
+ while (psBMHeap) {
+ if (psBMHeap->sDevArena.ui32HeapID ==
+ psDevMemHeapInfo->ui32HeapID)
+
+ return psBMHeap;
+ psBMHeap = psBMHeap->psNext;
+ }
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_HEAP),
+ (void **) &psBMHeap, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "BM_CreateHeap: Alloc failed");
+ return NULL;
+ }
+
+ OSMemSet(psBMHeap, 0, sizeof(struct 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;
+ }
+ }
+
+ psBMHeap->psNext = pBMContext->psBMHeap;
+ 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(struct BM_HEAP),
+ psBMHeap, NULL);
+
+ return NULL;
+}
+
+void BM_DestroyHeap(void *hDevMemHeap)
+{
+ struct BM_HEAP *psBMHeap = (struct BM_HEAP *)hDevMemHeap;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode =
+ psBMHeap->pBMContext->psDeviceNode;
+ struct BM_HEAP **ppsBMHeap;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "BM_DestroyHeap");
+
+ 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);
+
+ ppsBMHeap = &psBMHeap->pBMContext->psBMHeap;
+ while (*ppsBMHeap) {
+ if (*ppsBMHeap == psBMHeap) {
+ *ppsBMHeap = psBMHeap->psNext;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct BM_HEAP), psBMHeap,
+ NULL);
+ break;
+ }
+ ppsBMHeap = &((*ppsBMHeap)->psNext);
+ }
+}
+
+IMG_BOOL BM_Reinitialise(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_DPF(PVR_DBG_MESSAGE, "BM_Reinitialise");
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL BM_Alloc(void *hDevMemHeap, struct IMG_DEV_VIRTADDR *psDevVAddr,
+ size_t uSize, u32 *pui32Flags, u32 uDevVAddrAlignment,
+ void **phBuf)
+{
+ struct BM_BUF *pBuf;
+ struct BM_CONTEXT *pBMContext;
+ struct BM_HEAP *psBMHeap;
+ struct SYS_DATA *psSysData;
+ u32 uFlags;
+
+ if (pui32Flags == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "BM_Alloc: invalid parameter");
+ PVR_DBG_BREAK;
+ return IMG_FALSE;
+ }
+
+ uFlags = *pui32Flags;
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "BM_Alloc (uSize=0x%x, uFlags=0x%x, uDevVAddrAlignment=0x%x)",
+ uSize, uFlags, uDevVAddrAlignment);
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return IMG_FALSE;
+
+ psBMHeap = (struct BM_HEAP *)hDevMemHeap;
+ pBMContext = psBMHeap->pBMContext;
+
+ if (uDevVAddrAlignment == 0)
+ uDevVAddrAlignment = 1;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF),
+ (void **)&pBuf, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "BM_Alloc: BM_Buf alloc FAILED");
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof(struct BM_BUF));
+
+ if (AllocMemory(pBMContext, psBMHeap, psDevVAddr, uSize, uFlags,
+ uDevVAddrAlignment, pBuf) != IMG_TRUE) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF), pBuf,
+ NULL);
+ PVR_DPF(PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED");
+ return IMG_FALSE;
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE, "BM_Alloc (uSize=0x%x, uFlags=0x%x)=%08X",
+ uSize, uFlags, pBuf);
+
+ pBuf->ui32RefCount = 1;
+ pvr_get_ctx(pBMContext);
+ *phBuf = (void *) pBuf;
+ *pui32Flags = uFlags | psBMHeap->ui32Attribs;
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL BM_Wrap(void *hDevMemHeap, u32 ui32Size, u32 ui32Offset,
+ IMG_BOOL bPhysContig, struct IMG_SYS_PHYADDR *psSysAddr,
+ void *pvCPUVAddr, u32 *pui32Flags, void **phBuf)
+{
+ struct BM_BUF *pBuf;
+ struct BM_CONTEXT *psBMContext;
+ struct BM_HEAP *psBMHeap;
+ struct SYS_DATA *psSysData;
+ struct IMG_SYS_PHYADDR sHashAddress;
+ u32 uFlags;
+
+ psBMHeap = (struct BM_HEAP *)hDevMemHeap;
+ psBMContext = psBMHeap->pBMContext;
+
+ uFlags = psBMHeap->ui32Attribs &
+ (PVRSRV_HAP_CACHETYPE_MASK | PVRSRV_HAP_MAPTYPE_MASK);
+
+ if (pui32Flags)
+ uFlags |= *pui32Flags;
+
+ 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);
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return IMG_FALSE;
+
+ sHashAddress = psSysAddr[0];
+
+ sHashAddress.uiAddr += ui32Offset;
+
+ pBuf = (struct 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 = (void *)pBuf;
+ if (pui32Flags)
+ *pui32Flags = uFlags;
+
+ return IMG_TRUE;
+ }
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF),
+ (void **)&pBuf, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "BM_Wrap: BM_Buf alloc FAILED");
+ return IMG_FALSE;
+ }
+ OSMemSet(pBuf, 0, sizeof(struct BM_BUF));
+
+ if (WrapMemory(psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr,
+ pvCPUVAddr, uFlags, pBuf) != IMG_TRUE) {
+ PVR_DPF(PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED");
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_BUF), pBuf,
+ NULL);
+ return IMG_FALSE;
+ }
+
+ 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 IMG_FALSE;
+ }
+ }
+
+ 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;
+ pvr_get_ctx(psBMContext);
+ *phBuf = (void *) pBuf;
+ if (pui32Flags)
+ *pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) |
+ PVRSRV_HAP_MULTI_PROCESS;
+
+ return IMG_TRUE;
+}
+
+void BM_Free(void *hBuf, u32 ui32Flags)
+{
+ struct BM_BUF *pBuf = (struct BM_BUF *)hBuf;
+ struct SYS_DATA *psSysData;
+ struct 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;
+ }
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return;
+
+ pBuf->ui32RefCount--;
+
+ if (pBuf->ui32RefCount == 0) {
+ struct BM_MAPPING *map = pBuf->pMapping;
+ struct BM_CONTEXT *ctx = map->pBMHeap->pBMContext;
+
+ if (map->eCpuMemoryOrigin == hm_wrapped ||
+ map->eCpuMemoryOrigin == hm_wrapped_virtaddr) {
+ sHashAddr = SysCpuPAddrToSysPAddr(pBuf->CpuPAddr);
+
+ HASH_Remove(ctx->pBufferHash, (u32)sHashAddr.uiAddr);
+ }
+ FreeBuf(pBuf, ui32Flags);
+ pvr_put_ctx(ctx);
+ }
+}
+
+void *BM_HandleToCpuVaddr(void *hBuf)
+{
+ struct BM_BUF *pBuf = (struct 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;
+}
+
+struct IMG_DEV_VIRTADDR BM_HandleToDevVaddr(void *hBuf)
+{
+ struct BM_BUF *pBuf = (struct BM_BUF *)hBuf;
+
+ PVR_ASSERT(pBuf != NULL);
+ if (pBuf == NULL) {
+ struct 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;
+}
+
+struct IMG_SYS_PHYADDR BM_HandleToSysPaddr(void *hBuf)
+{
+ struct BM_BUF *pBuf = (struct BM_BUF *)hBuf;
+
+ PVR_ASSERT(pBuf != NULL);
+
+ if (pBuf == NULL) {
+ struct 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(void *hBuf)
+{
+ struct BM_BUF *pBuf = (struct 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;
+}
+
+IMG_BOOL BM_ContiguousStatistics(u32 uFlags, u32 *pTotalBytes,
+ u32 *pAvailableBytes)
+{
+ if (pAvailableBytes || pTotalBytes || uFlags)
+ ;
+ return IMG_FALSE;
+}
+
+static IMG_BOOL DevMemoryAlloc(struct BM_CONTEXT *pBMContext,
+ struct BM_MAPPING *pMapping, u32 uFlags, u32 dev_vaddr_alignment,
+ struct IMG_DEV_VIRTADDR *pDevVAddr)
+{
+ struct 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, 0, dev_vaddr_alignment,
+ &(pMapping->DevVAddr))) {
+ PVR_DPF(PVR_DBG_ERROR, "DevMemoryAlloc ERROR MMU_Alloc");
+ return IMG_FALSE;
+ }
+
+ 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 IMG_FALSE;
+ }
+
+
+ return IMG_TRUE;
+}
+
+static void DevMemoryFree(struct BM_MAPPING *pMapping)
+{
+ struct 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, (IMG_BOOL)(pMapping->
+ ui32Flags & PVRSRV_MEM_INTERLEAVED));
+#endif
+
+ psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
+
+ psDeviceNode->pfnMMUFree(pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr, pMapping->uSize);
+}
+
+static IMG_BOOL BM_ImportMemory(void *pH, size_t uRequestSize,
+ size_t *pActualSize, struct BM_MAPPING **ppsMapping,
+ u32 uFlags, u32 *pBase)
+{
+ struct BM_MAPPING *pMapping;
+ struct BM_HEAP *pBMHeap = pH;
+ struct BM_CONTEXT *pBMContext = pBMHeap->pBMContext;
+ IMG_BOOL bResult;
+ size_t uSize;
+ size_t 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(struct BM_MAPPING),
+ (void **)&pMapping, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "BM_ImportMemory: failed struct BM_MAPPING alloc");
+ goto fail_exit;
+ }
+
+ pMapping->hOSMemHandle = NULL;
+ pMapping->CpuVAddr = NULL;
+ 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) {
+ if (OSAllocPages(pBMHeap->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) {
+ struct IMG_SYS_PHYADDR sSysPAddr;
+
+ PVR_ASSERT(pBMHeap->pLocalDevMemArena != NULL);
+
+ if (!RA_Alloc(pBMHeap->pLocalDevMemArena, uPSize, NULL, 0,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ (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,
+ pBMHeap->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, 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: IMG_TRUE");
+ return IMG_TRUE;
+
+fail_dev_mem_alloc:
+ if (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 {
+ struct 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,
+ IMG_FALSE);
+ }
+ }
+fail_mapping_alloc:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_MAPPING), pMapping,
+ NULL);
+fail_exit:
+ return IMG_FALSE;
+}
+
+static void BM_FreeMemory(void *h, u32 _base, struct BM_MAPPING *psMapping)
+{
+ struct BM_HEAP *pBMHeap = h;
+ size_t uPSize;
+
+ PVR_UNREFERENCED_PARAMETER(_base);
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)", h, _base,
+ psMapping);
+
+ 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) {
+ struct IMG_SYS_PHYADDR sSysPAddr;
+
+ OSUnReservePhys(psMapping->CpuVAddr, uPSize,
+ pBMHeap->ui32Attribs, psMapping->hOSMemHandle);
+
+ sSysPAddr = SysCpuPAddrToSysPAddr(psMapping->CpuPAddr);
+
+ RA_Free(pBMHeap->pLocalDevMemArena, sSysPAddr.uiAddr,
+ IMG_FALSE);
+ } else {
+ PVR_DPF(PVR_DBG_ERROR,
+ "BM_FreeMemory: Invalid backing store type");
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BM_MAPPING), psMapping,
+ NULL);
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "..BM_FreeMemory (h=%08X, base=0x%x, psMapping=0x%x)",
+ h, _base, psMapping);
+}
+
+enum PVRSRV_ERROR BM_GetPhysPageAddr(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ struct IMG_DEV_VIRTADDR sDevVPageAddr,
+ struct IMG_DEV_PHYADDR *psDevPAddr)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "BM_GetPhysPageAddr");
+
+ if (!psMemInfo || !psDevPAddr) {
+ PVR_DPF(PVR_DBG_ERROR, "BM_GetPhysPageAddr: Invalid params");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
+
+ psDeviceNode =
+ ((struct BM_BUF *)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->
+ pBMContext->psDeviceNode;
+
+ *psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((struct BM_BUF *)
+ psMemInfo->sMemBlk.hBuffer)->
+ pMapping->pBMHeap->pMMUHeap, sDevVPageAddr);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR BM_GetHeapInfo(void *hDevMemHeap,
+ struct PVRSRV_HEAP_INFO *psHeapInfo)
+{
+ struct BM_HEAP *psBMHeap = (struct 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;
+}
+
+struct MMU_CONTEXT *BM_GetMMUContext(void *hDevMemHeap)
+{
+ struct BM_HEAP *pBMHeap = (struct BM_HEAP *)hDevMemHeap;
+
+ PVR_DPF(PVR_DBG_VERBOSE, "BM_GetMMUContext");
+
+ return pBMHeap->pBMContext->psMMUContext;
+}
+
+struct MMU_CONTEXT *BM_GetMMUContextFromMemContext(void *hDevMemContext)
+{
+ struct BM_CONTEXT *pBMContext = (struct 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 *)((struct BM_HEAP *)hDevMemHeap)->pMMUHeap;
+}
+
+struct PVRSRV_DEVICE_NODE *BM_GetDeviceNode(void *hDevMemContext)
+{
+ PVR_DPF(PVR_DBG_VERBOSE, "BM_GetDeviceNode");
+
+ return ((struct BM_CONTEXT *)hDevMemContext)->psDeviceNode;
+}
+
+void *BM_GetMappingHandle(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVR_DPF(PVR_DBG_VERBOSE, "BM_GetMappingHandle");
+
+ return ((struct BM_BUF *)
+ psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
+}
+
+struct BM_CONTEXT *bm_find_context(struct BM_CONTEXT *head_context,
+ u32 page_dir)
+{
+ struct BM_CONTEXT *context = head_context;
+
+ /* Walk all the contexts until we find the right one */
+ while (context) {
+ if (mmu_get_page_dir(context->psMMUContext) == page_dir)
+ break;
+ context = context->psNext;
+ }
+ return context;
+}
diff --git a/drivers/gpu/pvr/buffer_manager.h b/drivers/gpu/pvr/buffer_manager.h
new file mode 100644
index 00000000000..39472b1ed3e
--- /dev/null
+++ b/drivers/gpu/pvr/buffer_manager.h
@@ -0,0 +1,171 @@
+/**********************************************************************
+ *
+ * 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 _BUFFER_MANAGER_H_
+#define _BUFFER_MANAGER_H_
+
+#include "img_types.h"
+#include "ra.h"
+#include "perproc.h"
+
+
+struct BM_HEAP;
+
+struct BM_MAPPING {
+ enum {
+ hm_wrapped = 1,
+ hm_wrapped_scatter,
+ hm_wrapped_virtaddr,
+ hm_wrapped_scatter_virtaddr,
+ hm_env,
+ hm_contiguous
+ } eCpuMemoryOrigin;
+
+ struct BM_HEAP *pBMHeap;
+ struct RA_ARENA *pArena;
+
+ void *CpuVAddr;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+ struct IMG_DEV_VIRTADDR DevVAddr;
+ struct IMG_SYS_PHYADDR *psSysAddr;
+ size_t uSize;
+ void *hOSMemHandle;
+ u32 ui32Flags;
+};
+
+struct BM_BUF {
+ void **CpuVAddr;
+ void *hOSMemHandle;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+ struct IMG_DEV_VIRTADDR DevVAddr;
+
+ struct BM_MAPPING *pMapping;
+ u32 ui32RefCount;
+};
+
+struct BM_HEAP {
+ u32 ui32Attribs;
+ struct BM_CONTEXT *pBMContext;
+ struct RA_ARENA *pImportArena;
+ struct RA_ARENA *pLocalDevMemArena;
+ struct RA_ARENA *pVMArena;
+ struct DEV_ARENA_DESCRIPTOR sDevArena;
+ struct MMU_HEAP *pMMUHeap;
+
+ struct BM_HEAP *psNext;
+};
+
+struct BM_CONTEXT {
+ struct MMU_CONTEXT *psMMUContext;
+ struct BM_HEAP *psBMHeap;
+ struct BM_HEAP *psBMSharedHeap;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct HASH_TABLE *pBufferHash;
+ void *hResItem;
+ u32 ui32RefCount;
+ struct BM_CONTEXT *psNext;
+};
+
+#define BP_POOL_MASK 0x7
+
+#define BP_CONTIGUOUS (1 << 3)
+#define BP_PARAMBUFFER (1 << 4)
+
+#define BM_MAX_DEVMEM_ARENAS 2
+
+void *BM_CreateContext(struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct IMG_DEV_PHYADDR *psPDDevPAddr,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_BOOL *pbCreated);
+
+void BM_DestroyContext(void *hBMContext);
+
+static inline void pvr_get_ctx(struct BM_CONTEXT *ctx)
+{
+ WARN_ON(!ctx->ui32RefCount);
+ ctx->ui32RefCount++;
+}
+
+static inline bool pvr_put_ctx(struct BM_CONTEXT *ctx)
+{
+ BUG_ON(!ctx->ui32RefCount);
+ ctx->ui32RefCount--;
+ if (!ctx->ui32RefCount) {
+ BM_DestroyContext(ctx);
+
+ return true;
+ }
+
+ return false;
+}
+
+void *BM_CreateHeap(void *hBMContext,
+ struct DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+void BM_DestroyHeap(void *hDevMemHeap);
+IMG_BOOL BM_Reinitialise(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_BOOL BM_Alloc(void *hDevMemHeap,
+ struct IMG_DEV_VIRTADDR *psDevVAddr,
+ size_t uSize, u32 *pui32Flags, u32 uDevVAddrAlignment, void **phBuf);
+
+IMG_BOOL BM_Wrap(void *hDevMemHeap,
+ u32 ui32Size,
+ u32 ui32Offset,
+ IMG_BOOL bPhysContig,
+ struct IMG_SYS_PHYADDR *psSysAddr,
+ void *pvCPUVAddr, u32 *pui32Flags, void **phBuf);
+
+void BM_Free(void *hBuf, u32 ui32Flags);
+void *BM_HandleToCpuVaddr(void *hBuf);
+struct IMG_DEV_VIRTADDR BM_HandleToDevVaddr(void *hBuf);
+
+struct IMG_SYS_PHYADDR BM_HandleToSysPaddr(void *hBuf);
+
+void *BM_HandleToOSMemHandle(void *hBuf);
+
+IMG_BOOL BM_ContiguousStatistics(u32 uFlags, u32 *pTotalBytes,
+ u32 *pAvailableBytes);
+
+enum PVRSRV_ERROR BM_GetPhysPageAddr(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ struct IMG_DEV_VIRTADDR sDevVPageAddr,
+ struct IMG_DEV_PHYADDR *psDevPAddr);
+
+enum PVRSRV_ERROR BM_GetHeapInfo(void *hDevMemHeap,
+ struct PVRSRV_HEAP_INFO *psHeapInfo);
+
+struct MMU_CONTEXT *BM_GetMMUContext(void *hDevMemHeap);
+
+struct MMU_CONTEXT *BM_GetMMUContextFromMemContext(void *hDevMemContext);
+
+void *BM_GetMMUHeap(void *hDevMemHeap);
+
+struct PVRSRV_DEVICE_NODE *BM_GetDeviceNode(void *hDevMemContext);
+
+void *BM_GetMappingHandle(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+struct BM_CONTEXT *bm_find_context(struct BM_CONTEXT *head_context,
+ u32 page_dir);
+#endif
diff --git a/drivers/gpu/pvr/bufferclass_example.c b/drivers/gpu/pvr/bufferclass_example.c
new file mode 100644
index 00000000000..4f7a8eaccd1
--- /dev/null
+++ b/drivers/gpu/pvr/bufferclass_example.c
@@ -0,0 +1,266 @@
+/**********************************************************************
+ *
+ * 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 "bufferclass_example.h"
+
+static void *gpvAnchor;
+static IMG_BOOL(*pfnGetPVRJTable)(struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *);
+
+struct BC_EXAMPLE_DEVINFO *GetAnchorPtr(void)
+{
+ return (struct BC_EXAMPLE_DEVINFO *)gpvAnchor;
+}
+
+static void SetAnchorPtr(struct BC_EXAMPLE_DEVINFO *psDevInfo)
+{
+ gpvAnchor = (void *) psDevInfo;
+}
+
+static enum PVRSRV_ERROR OpenBCDevice(void **phDevice)
+{
+ struct BC_EXAMPLE_DEVINFO *psDevInfo;
+
+ psDevInfo = GetAnchorPtr();
+
+ *phDevice = (void *) psDevInfo;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR CloseBCDevice(void *hDevice)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR GetBCBuffer(void *hDevice,
+ u32 ui32BufferNumber,
+ struct PVRSRV_SYNC_DATA *psSyncData,
+ void **phBuffer)
+{
+ struct BC_EXAMPLE_DEVINFO *psDevInfo;
+
+ if (!hDevice || !phBuffer)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct BC_EXAMPLE_DEVINFO *)hDevice;
+
+ if (ui32BufferNumber < psDevInfo->sBufferInfo.ui32BufferCount) {
+ psDevInfo->psSystemBuffer[ui32BufferNumber].psSyncData =
+ psSyncData;
+ *phBuffer =
+ (void *) &psDevInfo->psSystemBuffer[ui32BufferNumber];
+ } else {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR GetBCInfo(void *hDevice, struct BUFFER_INFO *psBCInfo)
+{
+ struct BC_EXAMPLE_DEVINFO *psDevInfo;
+
+ if (!hDevice || !psBCInfo)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct BC_EXAMPLE_DEVINFO *)hDevice;
+
+ *psBCInfo = psDevInfo->sBufferInfo;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR GetBCBufferAddr(void *hDevice, void *hBuffer,
+ struct IMG_SYS_PHYADDR **ppsSysAddr,
+ u32 *pui32ByteSize, void __iomem **ppvCpuVAddr,
+ void **phOSMapInfo, IMG_BOOL *pbIsContiguous)
+{
+ struct BC_EXAMPLE_BUFFER *psBuffer;
+
+ if (!hDevice || !hBuffer || !ppsSysAddr || !pui32ByteSize)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psBuffer = (struct BC_EXAMPLE_BUFFER *)hBuffer;
+
+ *ppsSysAddr = &psBuffer->sPageAlignSysAddr;
+ *ppvCpuVAddr = psBuffer->sCPUVAddr;
+
+ *pui32ByteSize = psBuffer->ui32Size;
+
+ *phOSMapInfo = NULL;
+ *pbIsContiguous = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR BC_Example_Init(void)
+{
+ struct BC_EXAMPLE_DEVINFO *psDevInfo;
+ struct IMG_CPU_PHYADDR sSystemBufferCPUPAddr;
+ u32 i;
+
+ psDevInfo = GetAnchorPtr();
+
+ if (psDevInfo == NULL) {
+
+ psDevInfo = (struct BC_EXAMPLE_DEVINFO *)
+ BCAllocKernelMem(sizeof(struct BC_EXAMPLE_DEVINFO));
+
+ if (!psDevInfo)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ SetAnchorPtr((void *) psDevInfo);
+
+ psDevInfo->ui32RefCount = 0;
+
+ if (BCOpenPVRServices(&psDevInfo->hPVRServices) != PVRSRV_OK)
+ return PVRSRV_ERROR_INIT_FAILURE;
+ if (BCGetLibFuncAddr
+ (psDevInfo->hPVRServices, "PVRGetBufferClassJTable",
+ &pfnGetPVRJTable) != PVRSRV_OK)
+ return PVRSRV_ERROR_INIT_FAILURE;
+
+ if (!(*pfnGetPVRJTable) (&psDevInfo->sPVRJTable))
+ return PVRSRV_ERROR_INIT_FAILURE;
+
+ psDevInfo->ui32NumBuffers = 0;
+
+ psDevInfo->psSystemBuffer =
+ BCAllocKernelMem(sizeof(struct BC_EXAMPLE_BUFFER) *
+ BC_EXAMPLE_NUM_BUFFERS);
+
+ if (!psDevInfo->psSystemBuffer)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ psDevInfo->sBufferInfo.pixelformat = BC_EXAMPLE_PIXELFORMAT;
+ psDevInfo->sBufferInfo.ui32Width = BC_EXAMPLE_WIDTH;
+ psDevInfo->sBufferInfo.ui32Height = BC_EXAMPLE_HEIGHT;
+ psDevInfo->sBufferInfo.ui32ByteStride = BC_EXAMPLE_STRIDE;
+ psDevInfo->sBufferInfo.ui32BufferDeviceID = BC_EXAMPLE_DEVICEID;
+ psDevInfo->sBufferInfo.ui32Flags =
+ PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE |
+ PVRSRV_BC_FLAGS_YUVCSC_BT601;
+
+ for (i = 0; i < BC_EXAMPLE_NUM_BUFFERS; i++) {
+ u32 ui32Size =
+ BC_EXAMPLE_HEIGHT * BC_EXAMPLE_STRIDE;
+
+ if (psDevInfo->sBufferInfo.pixelformat ==
+ PVRSRV_PIXEL_FORMAT_NV12)
+
+ ui32Size +=
+ ((BC_EXAMPLE_STRIDE >> 1) *
+ (BC_EXAMPLE_HEIGHT >> 1) << 1);
+
+ if (BCAllocContigMemory(ui32Size,
+ &psDevInfo->psSystemBuffer[i].
+ hMemHandle,
+ &psDevInfo->psSystemBuffer[i].
+ sCPUVAddr,
+ &sSystemBufferCPUPAddr) !=
+ PVRSRV_OK)
+ break;
+
+ psDevInfo->ui32NumBuffers++;
+
+ psDevInfo->psSystemBuffer[i].ui32Size = ui32Size;
+ psDevInfo->psSystemBuffer[i].sSysAddr =
+ CpuPAddrToSysPAddrBC(sSystemBufferCPUPAddr);
+ psDevInfo->psSystemBuffer[i].sPageAlignSysAddr.uiAddr =
+ (psDevInfo->psSystemBuffer[i].sSysAddr.
+ uiAddr & 0xFFFFF000);
+ psDevInfo->psSystemBuffer[i].psSyncData = NULL;
+ }
+
+ psDevInfo->sBufferInfo.ui32BufferCount =
+ psDevInfo->ui32NumBuffers;
+
+ psDevInfo->sBCJTable.ui32TableSize =
+ sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE);
+ psDevInfo->sBCJTable.pfnOpenBCDevice = OpenBCDevice;
+ psDevInfo->sBCJTable.pfnCloseBCDevice = CloseBCDevice;
+ psDevInfo->sBCJTable.pfnGetBCBuffer = GetBCBuffer;
+ psDevInfo->sBCJTable.pfnGetBCInfo = GetBCInfo;
+ psDevInfo->sBCJTable.pfnGetBufferAddr = GetBCBufferAddr;
+
+ if (psDevInfo->sPVRJTable.
+ pfnPVRSRVRegisterBCDevice(&psDevInfo->sBCJTable,
+ &psDevInfo->ui32DeviceID) !=
+ PVRSRV_OK)
+ return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
+ }
+
+ psDevInfo->ui32RefCount++;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR BC_Example_Deinit(void)
+{
+ struct BC_EXAMPLE_DEVINFO *psDevInfo;
+ u32 i;
+ psDevInfo = GetAnchorPtr();
+
+ if (psDevInfo == NULL)
+ return PVRSRV_ERROR_GENERIC;
+
+ psDevInfo->ui32RefCount--;
+
+ if (psDevInfo->ui32RefCount == 0) {
+
+ struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable =
+ &psDevInfo->sPVRJTable;
+
+ if (psJTable->
+ pfnPVRSRVRemoveBCDevice(psDevInfo->ui32DeviceID) !=
+ PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
+
+ if (BCClosePVRServices(psDevInfo->hPVRServices) != PVRSRV_OK) {
+ psDevInfo->hPVRServices = NULL;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ for (i = 0; i < psDevInfo->ui32NumBuffers; i++)
+ BCFreeContigMemory(psDevInfo->psSystemBuffer[i].
+ ui32Size,
+ psDevInfo->psSystemBuffer[i].
+ hMemHandle,
+ psDevInfo->psSystemBuffer[i].
+ sCPUVAddr,
+ SysPAddrToCpuPAddrBC(psDevInfo->
+ psSystemBuffer
+ [i].sSysAddr));
+
+ BCFreeKernelMem(psDevInfo);
+
+ SetAnchorPtr(NULL);
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/pvr/bufferclass_example.h b/drivers/gpu/pvr/bufferclass_example.h
new file mode 100644
index 00000000000..c9dd0946b1d
--- /dev/null
+++ b/drivers/gpu/pvr/bufferclass_example.h
@@ -0,0 +1,104 @@
+/**********************************************************************
+ *
+ * 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 __BC_EXAMPLE_H__
+#define __BC_EXAMPLE_H__
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kernelbuffer.h"
+
+extern IMG_BOOL PVRGetBufferClassJTable(
+ struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+#define BC_EXAMPLE_NUM_BUFFERS 3
+
+#define YUV420 1
+#ifdef YUV420
+
+#define BC_EXAMPLE_WIDTH 320
+#define BC_EXAMPLE_HEIGHT 160
+#define BC_EXAMPLE_STRIDE 320
+#define BC_EXAMPLE_PIXELFORMAT PVRSRV_PIXEL_FORMAT_NV12
+
+#else
+
+#define BC_EXAMPLE_WIDTH 320
+#define BC_EXAMPLE_HEIGHT 160
+#define BC_EXAMPLE_STRIDE (320 * 2)
+#define BC_EXAMPLE_PIXELFORMAT PVRSRV_PIXEL_FORMAT_RGB565
+
+#endif
+
+#define BC_EXAMPLE_DEVICEID 0
+
+struct BC_EXAMPLE_BUFFER {
+ u32 ui32Size;
+ void *hMemHandle;
+ struct IMG_SYS_PHYADDR sSysAddr;
+ struct IMG_SYS_PHYADDR sPageAlignSysAddr;
+ void __iomem *sCPUVAddr;
+ struct PVRSRV_SYNC_DATA *psSyncData;
+ struct BC_EXAMPLE_BUFFER *psNext;
+};
+
+struct BC_EXAMPLE_DEVINFO {
+ u32 ui32DeviceID;
+ struct BC_EXAMPLE_BUFFER *psSystemBuffer;
+ struct BUFFER_INFO sBufferInfo;
+ u32 ui32NumBuffers;
+ struct PVRSRV_BC_BUFFER2SRV_KMJTABLE sPVRJTable;
+ struct PVRSRV_BC_SRV2BUFFER_KMJTABLE sBCJTable;
+ void *hPVRServices;
+ u32 ui32RefCount;
+};
+
+enum PVRSRV_ERROR BC_Example_Init(void);
+enum PVRSRV_ERROR BC_Example_Deinit(void);
+
+enum PVRSRV_ERROR BCOpenPVRServices(void **phPVRServices);
+enum PVRSRV_ERROR BCClosePVRServices(void *hPVRServices);
+
+void *BCAllocKernelMem(u32 ui32Size);
+void BCFreeKernelMem(void *pvMem);
+
+enum PVRSRV_ERROR BCAllocContigMemory(u32 ui32Size, void **phMemHandle,
+ void __iomem **pLinAddr,
+ struct IMG_CPU_PHYADDR *pPhysAddr);
+void BCFreeContigMemory(u32 ui32Size, void *hMemHandle, void __iomem *LinAddr,
+ struct IMG_CPU_PHYADDR PhysAddr);
+
+struct IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC(struct IMG_CPU_PHYADDR cpu_paddr);
+struct IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC(struct IMG_SYS_PHYADDR sys_paddr);
+
+void *MapPhysAddr(struct IMG_SYS_PHYADDR sSysAddr, u32 ui32Size);
+void UnMapPhysAddr(void *pvAddr, u32 ui32Size);
+
+enum PVRSRV_ERROR BCGetLibFuncAddr(void *hExtDrv, char *szFunctionName,
+ IMG_BOOL (**ppfnFuncTable)(struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *));
+struct BC_EXAMPLE_DEVINFO *GetAnchorPtr(void);
+
+#endif
diff --git a/drivers/gpu/pvr/bufferclass_example_linux.c b/drivers/gpu/pvr/bufferclass_example_linux.c
new file mode 100644
index 00000000000..924a27ead18
--- /dev/null
+++ b/drivers/gpu/pvr/bufferclass_example_linux.c
@@ -0,0 +1,202 @@
+/**********************************************************************
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <linux/dma-mapping.h>
+
+#include "kernelbuffer.h"
+#include "bufferclass_example.h"
+#include "bufferclass_example_linux.h"
+#include "bufferclass_example_private.h"
+#include "pvrmodule.h"
+
+#define DEVNAME "bc_example"
+#define DRVNAME DEVNAME
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+static int AssignedMajorNumber;
+
+#define unref__ __attribute__ ((unused))
+
+
+
+void *BCAllocKernelMem(u32 ui32Size)
+{
+ return kmalloc(ui32Size, GFP_KERNEL);
+}
+
+void BCFreeKernelMem(void *pvMem)
+{
+ kfree(pvMem);
+}
+
+enum PVRSRV_ERROR BCAllocContigMemory(u32 ui32Size, void *unref__ * phMemHandle,
+ void __iomem **pLinAddr,
+ struct IMG_CPU_PHYADDR *pPhysAddr)
+{
+ dma_addr_t dma;
+ void *pvLinAddr;
+
+ pvLinAddr = dma_alloc_coherent(NULL, ui32Size, &dma, GFP_KERNEL);
+
+ if (pvLinAddr == NULL)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ pPhysAddr->uiAddr = dma;
+ *pLinAddr = (void __force __iomem *)pvLinAddr;
+
+ return PVRSRV_OK;
+}
+
+void BCFreeContigMemory(u32 ui32Size, void *unref__ hMemHandle,
+ void __iomem *LinAddr, struct IMG_CPU_PHYADDR PhysAddr)
+{
+ dma_free_coherent(NULL, ui32Size, (void __force *)LinAddr,
+ (dma_addr_t)PhysAddr.uiAddr);
+}
+
+struct IMG_SYS_PHYADDR CpuPAddrToSysPAddrBC(struct IMG_CPU_PHYADDR cpu_paddr)
+{
+ struct IMG_SYS_PHYADDR sys_paddr;
+
+ sys_paddr.uiAddr = cpu_paddr.uiAddr;
+ return sys_paddr;
+}
+
+struct IMG_CPU_PHYADDR SysPAddrToCpuPAddrBC(struct IMG_SYS_PHYADDR sys_paddr)
+{
+
+ struct IMG_CPU_PHYADDR cpu_paddr;
+
+ cpu_paddr.uiAddr = sys_paddr.uiAddr;
+ return cpu_paddr;
+}
+
+enum PVRSRV_ERROR BCOpenPVRServices(void **phPVRServices)
+{
+
+ *phPVRServices = NULL;
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR BCClosePVRServices(void *unref__ hPVRServices)
+{
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR BCGetLibFuncAddr(void *unref__ hExtDrv, char *szFunctionName,
+ IMG_BOOL (**ppfnFuncTable)(struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *))
+{
+ if (strcmp("PVRGetBufferClassJTable", szFunctionName) != 0)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ *ppfnFuncTable = PVRGetBufferClassJTable;
+
+ return PVRSRV_OK;
+}
+
+static int BC_Example_Bridge(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int err = -EFAULT;
+ int command = _IOC_NR(cmd);
+ struct BC_Example_ioctl_package __user *psBridge =
+ (struct BC_Example_ioctl_package __user *)arg;
+
+ if (!access_ok
+ (VERIFY_WRITE, psBridge, sizeof(struct BC_Example_ioctl_package)))
+ return err;
+
+ switch (command) {
+ case _IOC_NR(BC_Example_ioctl_fill_buffer):
+ if (FillBuffer(psBridge->inputparam) == -1)
+ return err;
+ break;
+ case _IOC_NR(BC_Example_ioctl_get_buffer_count):
+ if (GetBufferCount(&psBridge->outputparam) == -1)
+ return err;
+ break;
+ default:
+ return err;
+ }
+
+ return 0;
+}
+
+static const struct file_operations bufferclass_example_fops = {
+ .ioctl = BC_Example_Bridge,
+};
+
+static int __init BC_Example_ModInit(void)
+{
+ AssignedMajorNumber =
+ register_chrdev(0, DEVNAME, &bufferclass_example_fops);
+
+ if (AssignedMajorNumber <= 0) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Example_ModInit: unable to get major number\n");
+
+ goto ExitDisable;
+ }
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ printk(KERN_ERR DRVNAME ": BC_Example_ModInit: major device %d\n",
+ AssignedMajorNumber);
+#endif
+
+
+ if (BC_Example_Init() != PVRSRV_OK) {
+ printk(KERN_ERR DRVNAME
+ ": BC_Example_ModInit: can't init device\n");
+ goto ExitUnregister;
+ }
+
+ return 0;
+
+ExitUnregister:
+ unregister_chrdev(AssignedMajorNumber, DEVNAME);
+ExitDisable:
+ return -EBUSY;
+}
+
+static void __exit BC_Example_ModCleanup(void)
+{
+ unregister_chrdev(AssignedMajorNumber, DEVNAME);
+
+ if (BC_Example_Deinit() != PVRSRV_OK)
+ printk(KERN_ERR DRVNAME
+ ": BC_Example_ModCleanup: can't deinit device\n");
+
+}
+
+module_init(BC_Example_ModInit);
+module_exit(BC_Example_ModCleanup);
diff --git a/drivers/gpu/pvr/bufferclass_example_linux.h b/drivers/gpu/pvr/bufferclass_example_linux.h
new file mode 100644
index 00000000000..8e17fdf7650
--- /dev/null
+++ b/drivers/gpu/pvr/bufferclass_example_linux.h
@@ -0,0 +1,46 @@
+/**********************************************************************
+ *
+ * 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 __BC_EXAMPLE_LINUX_H__
+#define __BC_EXAMPLE_LINUX_H__
+
+#include <linux/ioctl.h>
+
+struct BC_Example_ioctl_package {
+ int inputparam;
+ int outputparam;
+
+};
+
+#define BC_EXAMPLE_IOC_GID 'g'
+
+#define BC_EXAMPLE_IOWR(INDEX) \
+ _IOWR(BC_EXAMPLE_IOC_GID, INDEX, struct BC_Example_ioctl_package)
+
+#define BC_Example_ioctl_fill_buffer BC_EXAMPLE_IOWR(0)
+#define BC_Example_ioctl_get_buffer_count BC_EXAMPLE_IOWR(1)
+
+#endif
diff --git a/drivers/gpu/pvr/bufferclass_example_private.c b/drivers/gpu/pvr/bufferclass_example_private.c
new file mode 100644
index 00000000000..360524e23fe
--- /dev/null
+++ b/drivers/gpu/pvr/bufferclass_example_private.c
@@ -0,0 +1,194 @@
+/**********************************************************************
+ *
+ * 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 "bufferclass_example.h"
+#include "bufferclass_example_private.h"
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+static void FillYUV420Image(void __iomem *pvDest, int width, int height,
+ int bytestride)
+{
+ static int iPhase;
+ int i, j;
+ unsigned char u, v, y;
+ unsigned char *pui8y = (unsigned char __force *)pvDest;
+ unsigned short *pui16uv;
+ unsigned int count = 0;
+
+ for (j = 0; j < height; j++)
+ for (i = 0; i < width; i++) {
+ y = (((i + iPhase) >> 6) % (2) == 0) ? 0x7f : 0x00;
+
+ pui8y[count++] = y;
+ }
+
+ pui16uv = (unsigned short *)
+ ((unsigned char __force *)pvDest + (width * height));
+ count = 0;
+
+ for (j = 0; j < height; j += 2)
+ for (i = 0; i < width; i += 2) {
+ u = (j < (height / 2)) ?
+ ((i < (width / 2)) ? 0xFF : 0x33) :
+ ((i < (width / 2)) ? 0x33 : 0xAA);
+ v = (j < (height / 2)) ?
+ ((i < (width / 2)) ? 0xAC : 0x0) :
+ ((i < (width / 2)) ? 0x03 : 0xEE);
+
+ pui16uv[count++] = (v << 8) | u;
+
+ }
+
+ iPhase++;
+}
+
+static void FillYUV422Image(void __iomem *pvDest, int width, int height,
+ int bytestride)
+{
+ static int iPhase;
+ int x, y;
+ unsigned char u, v, y0, y1;
+ unsigned int *pui32yuv = (unsigned int __force *)pvDest;
+ unsigned int count = 0;
+
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x += 2) {
+ u = (y < (height / 2)) ?
+ ((x < (width / 2)) ? 0xFF : 0x33) :
+ ((x < (width / 2)) ? 0x33 : 0xAA);
+ v = (y < (height / 2)) ?
+ ((x < (width / 2)) ? 0xAA : 0x0) :
+ ((x < (width / 2)) ? 0x03 : 0xEE);
+
+ y0 = y1 =
+ (((x + iPhase) >> 6) % (2) == 0) ? 0x7f : 0x00;
+
+ pui32yuv[count++] =
+ (y1 << 24) | (v << 16) | (y0 << 8) | u;
+
+ }
+
+ iPhase++;
+}
+
+static void FillRGB565Image(void __iomem *pvDest, int width, int height,
+ int bytestride)
+{
+ int i, Count;
+ unsigned long *pui32Addr = (unsigned long __force *)pvDest;
+ unsigned short *pui16Addr = (unsigned short __force *)pvDest;
+ unsigned long Colour32;
+ unsigned short Colour16;
+ static unsigned char Colour8;
+
+ Colour16 = (Colour8 >> 3) | ((Colour8 >> 2) << 5) |
+ ((Colour8 >> 3) << 11);
+ Colour32 = Colour16 | Colour16 << 16;
+
+ Count = (height * bytestride) >> 2;
+
+ for (i = 0; i < Count; i++)
+ pui32Addr[i] = Colour32;
+
+ Count = height;
+
+ pui16Addr = (unsigned short *)
+ ((unsigned char __force *)pvDest + (2 * Colour8));
+
+ for (i = 0; i < Count; i++) {
+ *pui16Addr = 0xF800;
+
+ pui16Addr =
+ (unsigned short *)((unsigned char *)pui16Addr + bytestride);
+ }
+ Count = bytestride >> 2;
+
+ pui32Addr = (unsigned long *)((unsigned char __force *)pvDest +
+ (bytestride * (MIN(height - 1, 0xFF) - Colour8)));
+
+ for (i = 0; i < Count; i++)
+ pui32Addr[i] = 0x001F001F;
+
+ Colour8 = (Colour8 + 1) % MIN(height - 1, 0xFF);
+}
+
+int FillBuffer(unsigned int ui32BufferIndex)
+{
+ struct BC_EXAMPLE_DEVINFO *psDevInfo = GetAnchorPtr();
+ struct BC_EXAMPLE_BUFFER *psBuffer;
+ struct BUFFER_INFO *psBufferInfo;
+ struct PVRSRV_SYNC_DATA *psSyncData;
+
+ if (psDevInfo == NULL)
+ return -1;
+
+ psBuffer = &psDevInfo->psSystemBuffer[ui32BufferIndex];
+ psBufferInfo = &psDevInfo->sBufferInfo;
+
+ psSyncData = psBuffer->psSyncData;
+
+ if (psSyncData) {
+ if (psSyncData->ui32ReadOpsPending !=
+ psSyncData->ui32ReadOpsComplete)
+ return -1;
+
+ psSyncData->ui32WriteOpsPending++;
+ }
+
+ switch (psBufferInfo->pixelformat) {
+ case PVRSRV_PIXEL_FORMAT_RGB565:
+ default:
+ FillRGB565Image(psBuffer->sCPUVAddr, BC_EXAMPLE_WIDTH,
+ BC_EXAMPLE_HEIGHT, BC_EXAMPLE_STRIDE);
+ break;
+ case PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY:
+ FillYUV422Image(psBuffer->sCPUVAddr, BC_EXAMPLE_WIDTH,
+ BC_EXAMPLE_HEIGHT, BC_EXAMPLE_STRIDE);
+ break;
+ case PVRSRV_PIXEL_FORMAT_NV12:
+ FillYUV420Image(psBuffer->sCPUVAddr, BC_EXAMPLE_WIDTH,
+ BC_EXAMPLE_HEIGHT, BC_EXAMPLE_STRIDE);
+ break;
+ }
+
+ if (psSyncData)
+ psSyncData->ui32WriteOpsComplete++;
+
+ return 0;
+}
+
+int GetBufferCount(unsigned int *pui32BufferCount)
+{
+ struct BC_EXAMPLE_DEVINFO *psDevInfo = GetAnchorPtr();
+
+ if (psDevInfo == NULL)
+ return -1;
+
+ *pui32BufferCount = psDevInfo->sBufferInfo.ui32BufferCount;
+
+ return 0;
+}
diff --git a/drivers/gpu/pvr/bufferclass_example_private.h b/drivers/gpu/pvr/bufferclass_example_private.h
new file mode 100644
index 00000000000..527c782d2ac
--- /dev/null
+++ b/drivers/gpu/pvr/bufferclass_example_private.h
@@ -0,0 +1,33 @@
+/**********************************************************************
+ *
+ * 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 __BC_EXAMPLE_PRIVATE_H__
+#define __BC_EXAMPLE_PRIVATE_H__
+
+int FillBuffer(unsigned int ui32BufferIndex);
+int GetBufferCount(unsigned int *pui32BufferCount);
+
+#endif
diff --git a/drivers/gpu/pvr/dbgdrvif.h b/drivers/gpu/pvr/dbgdrvif.h
new file mode 100644
index 00000000000..d8ace97e331
--- /dev/null
+++ b/drivers/gpu/pvr/dbgdrvif.h
@@ -0,0 +1,318 @@
+/**********************************************************************
+ *
+ * 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 _DBGDRVIF_
+#define _DBGDRVIF_
+
+#include "ioctldef.h"
+
+#define DEBUG_CAPMODE_FRAMED 0x00000001
+#define DEBUG_CAPMODE_CONTINUOUS 0x00000002
+#define DEBUG_CAPMODE_HOTKEY 0x00000004
+
+#define DEBUG_OUTMODE_STANDARDDBG 0x00000001
+#define DEBUG_OUTMODE_MONO 0x00000002
+#define DEBUG_OUTMODE_STREAMENABLE 0x00000004
+#define DEBUG_OUTMODE_ASYNC 0x00000008
+#define DEBUG_OUTMODE_SGXVGA 0x00000010
+
+#define DEBUG_FLAGS_USE_NONPAGED_MEM 0x00000001
+#define DEBUG_FLAGS_NO_BUF_EXPANDSION 0x00000002
+#define DEBUG_FLAGS_ENABLESAMPLE 0x00000004
+
+#define DEBUG_FLAGS_TEXTSTREAM 0x80000000
+
+#define DEBUG_LEVEL_0 0x00000001
+#define DEBUG_LEVEL_1 0x00000003
+#define DEBUG_LEVEL_2 0x00000007
+#define DEBUG_LEVEL_3 0x0000000F
+#define DEBUG_LEVEL_4 0x0000001F
+#define DEBUG_LEVEL_5 0x0000003F
+#define DEBUG_LEVEL_6 0x0000007F
+#define DEBUG_LEVEL_7 0x000000FF
+#define DEBUG_LEVEL_8 0x000001FF
+#define DEBUG_LEVEL_9 0x000003FF
+#define DEBUG_LEVEL_10 0x000007FF
+#define DEBUG_LEVEL_11 0x00000FFF
+
+#define DEBUG_LEVEL_SEL0 0x00000001
+#define DEBUG_LEVEL_SEL1 0x00000002
+#define DEBUG_LEVEL_SEL2 0x00000004
+#define DEBUG_LEVEL_SEL3 0x00000008
+#define DEBUG_LEVEL_SEL4 0x00000010
+#define DEBUG_LEVEL_SEL5 0x00000020
+#define DEBUG_LEVEL_SEL6 0x00000040
+#define DEBUG_LEVEL_SEL7 0x00000080
+#define DEBUG_LEVEL_SEL8 0x00000100
+#define DEBUG_LEVEL_SEL9 0x00000200
+#define DEBUG_LEVEL_SEL10 0x00000400
+#define DEBUG_LEVEL_SEL11 0x00000800
+
+#define DEBUG_SERVICE_IOCTL_BASE 0x800
+#define DEBUG_SERVICE_CREATESTREAM \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x01, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DESTROYSTREAM \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x02, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSTREAM \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x03, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRING \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x04, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READSTRING \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x05, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x06, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READ \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x07, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGMODE \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x08, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGOUTMODE \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x09, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETDEBUGLEVEL \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0A, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETFRAME \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0B, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETFRAME \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0C, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_OVERRIDEMODE \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0D, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_DEFAULTMODE \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0E, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETSERVICETABLE \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x0F, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITE2 \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x10, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITESTRINGCM \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x11, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITECM \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x12, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_SETMARKER \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x13, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_GETMARKER \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x14, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_ISCAPTUREFRAME \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x15, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WRITELF \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x16, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_READLF \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x17, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define DEBUG_SERVICE_WAITFOREVENT \
+ CTL_CODE(FILE_DEVICE_UNKNOWN, DEBUG_SERVICE_IOCTL_BASE + 0x18, \
+ METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+enum DBG_EVENT {
+ DBG_EVENT_STREAM_DATA = 1
+};
+
+struct DBG_IN_CREATESTREAM {
+ u32 ui32Pages;
+ u32 ui32CapMode;
+ u32 ui32OutMode;
+ char *pszName;
+};
+
+struct DBG_IN_FINDSTREAM {
+ IMG_BOOL bResetStream;
+ char *pszName;
+};
+
+struct DBG_IN_WRITESTRING {
+ void *pvStream;
+ u32 ui32Level;
+ char *pszString;
+};
+
+struct DBG_IN_READSTRING {
+ void *pvStream;
+ u32 ui32StringLen;
+ char *pszString;
+};
+
+struct DBG_IN_SETDEBUGMODE {
+ void *pvStream;
+ u32 ui32Mode;
+ u32 ui32Start;
+ u32 ui32End;
+ u32 ui32SampleRate;
+};
+
+struct DBG_IN_SETDEBUGOUTMODE {
+ void *pvStream;
+ u32 ui32Mode;
+};
+
+struct DBG_IN_SETDEBUGLEVEL {
+ void *pvStream;
+ u32 ui32Level;
+};
+
+struct DBG_IN_SETFRAME {
+ void *pvStream;
+ u32 ui32Frame;
+};
+
+struct DBG_IN_WRITE {
+ void *pvStream;
+ u32 ui32Level;
+ u32 ui32TransferSize;
+ u8 *pui8InBuffer;
+};
+
+struct DBG_IN_READ {
+ void *pvStream;
+ IMG_BOOL bReadInitBuffer;
+ u32 ui32OutBufferSize;
+ u8 *pui8OutBuffer;
+};
+
+struct DBG_IN_OVERRIDEMODE {
+ void *pvStream;
+ u32 ui32Mode;
+};
+
+struct DBG_IN_ISCAPTUREFRAME {
+ void *pvStream;
+ IMG_BOOL bCheckPreviousFrame;
+};
+
+struct DBG_IN_SETMARKER {
+ void *pvStream;
+ u32 ui32Marker;
+};
+
+struct DBG_IN_WRITE_LF {
+ u32 ui32Flags;
+ void *pvStream;
+ u32 ui32Level;
+ u32 ui32BufferSize;
+ u8 *pui8InBuffer;
+};
+
+#define WRITELF_FLAGS_RESETBUF 0x00000001
+
+struct DBG_STREAM {
+ struct DBG_STREAM *psNext;
+ struct DBG_STREAM *psInitStream;
+ IMG_BOOL bInitPhaseComplete;
+ u32 ui32Flags;
+ u32 ui32Base;
+ u32 ui32Size;
+ u32 ui32RPtr;
+ u32 ui32WPtr;
+ u32 ui32DataWritten;
+ u32 ui32CapMode;
+ u32 ui32OutMode;
+ u32 ui32DebugLevel;
+ u32 ui32DefaultMode;
+ u32 ui32Start;
+ u32 ui32End;
+ u32 ui32Current;
+ u32 ui32Access;
+ u32 ui32SampleRate;
+ u32 ui32Reserved;
+ u32 ui32Timeout;
+ u32 ui32Marker;
+ char szName[30];
+};
+
+struct DBGKM_SERVICE_TABLE {
+ u32 ui32Size;
+ void *(*pfnCreateStream)(char *pszName, u32 ui32CapMode,
+ u32 ui32OutMode, u32 ui32Flags, u32 ui32Pages);
+ void (*pfnDestroyStream)(struct DBG_STREAM *psStream);
+ void *(*pfnFindStream)(char *pszName, IMG_BOOL bResetInitBuffer);
+ u32 (*pfnWriteString)(struct DBG_STREAM *psStream, char *pszString,
+ u32 ui32Level);
+ u32 (*pfnReadString)(struct DBG_STREAM *psStream, char *pszString,
+ u32 ui32Limit);
+ u32 (*pfnWriteBIN)(struct DBG_STREAM *psStream, u8 *pui8InBuf,
+ u32 ui32InBuffSize, u32 ui32Level);
+ u32 (*pfnReadBIN)(struct DBG_STREAM *psStream,
+ IMG_BOOL bReadInitBuffer, u32 ui32OutBufferSize,
+ u8 *pui8OutBuf);
+ void (*pfnSetCaptureMode)(struct DBG_STREAM *psStream,
+ u32 ui32CapMode, u32 ui32Start, u32 ui32Stop,
+ u32 ui32SampleRate);
+ void (*pfnSetOutputMode)(struct DBG_STREAM *psStream,
+ u32 ui32OutMode);
+ void (*pfnSetDebugLevel)(struct DBG_STREAM *psStream,
+ u32 ui32DebugLevel);
+ void (*pfnSetFrame)(struct DBG_STREAM *psStream,
+ u32 ui32Frame);
+ u32 (*pfnGetFrame)(struct DBG_STREAM *psStream);
+ void (*pfnOverrideMode)(struct DBG_STREAM *psStream,
+ u32 ui32Mode);
+ void (*pfnDefaultMode)(struct DBG_STREAM *psStream);
+ u32 (*pfnDBGDrivWrite2)(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf, u32 ui32InBuffSize, u32 ui32Level);
+ u32 (*pfnWriteStringCM)(struct DBG_STREAM *psStream, char *pszString,
+ u32 ui32Level);
+ u32 (*pfnWriteBINCM)(struct DBG_STREAM *psStream, u8 *pui8InBuf,
+ u32 ui32InBuffSize, u32 ui32Level);
+ void (*pfnSetMarker)(struct DBG_STREAM *psStream, u32 ui32Marker);
+ u32 (*pfnGetMarker)(struct DBG_STREAM *psStream);
+ void (*pfnStartInitPhase) (struct DBG_STREAM *psStream);
+ void (*pfnStopInitPhase) (struct DBG_STREAM *psStream);
+ u32 (*pfnIsCaptureFrame)(struct DBG_STREAM *psStream,
+ IMG_BOOL bCheckPreviousFrame);
+ u32 (*pfnWriteLF)(struct DBG_STREAM *psStream, u8 *pui8InBuf,
+ u32 ui32InBuffSize, u32 ui32Level, u32 ui32Flags);
+ u32 (*pfnReadLF)(struct DBG_STREAM *psStream, u32 ui32OutBuffSize,
+ u8 *pui8OutBuf);
+ u32 (*pfnGetStreamOffset)(struct DBG_STREAM *psStream);
+ void (*pfnSetStreamOffset)(struct DBG_STREAM *psStream,
+ u32 ui32StreamOffset);
+ u32 (*pfnIsLastCaptureFrame)(struct DBG_STREAM *psStream);
+ void (*pfnWaitForEvent) (enum DBG_EVENT eEvent);
+};
+
+extern struct DBGKM_SERVICE_TABLE g_sDBGKMServices;
+
+void DBGDrvGetServiceTable(void **fn_table);
+
+#endif
diff --git a/drivers/gpu/pvr/device.h b/drivers/gpu/pvr/device.h
new file mode 100644
index 00000000000..43a37e00d07
--- /dev/null
+++ b/drivers/gpu/pvr/device.h
@@ -0,0 +1,187 @@
+/**********************************************************************
+ *
+ * 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 __DEVICE_H__
+#define __DEVICE_H__
+
+#include "ra.h"
+#include "resman.h"
+
+struct BM_CONTEXT;
+
+struct MMU_HEAP;
+struct MMU_CONTEXT;
+
+#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG \
+ (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG \
+ (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG \
+ (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG \
+ (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+
+#define DEVICE_MEMORY_HEAP_PERCONTEXT 0
+#define DEVICE_MEMORY_HEAP_KERNEL 1
+#define DEVICE_MEMORY_HEAP_SHARED 2
+#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED 3
+
+#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY 1
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2
+
+struct DEVICE_MEMORY_HEAP_INFO {
+ u32 ui32HeapID;
+ char *pszName;
+ char *pszBSName;
+ struct IMG_DEV_VIRTADDR sDevVAddrBase;
+ u32 ui32HeapSize;
+ u32 ui32Attribs;
+ u32 DevMemHeapType;
+ void *hDevMemHeap;
+ struct RA_ARENA *psLocalDevMemArena;
+
+ u32 ui32DataPageSize;
+
+};
+
+struct DEVICE_MEMORY_INFO {
+ u32 ui32AddressSpaceSizeLog2;
+ u32 ui32Flags;
+ u32 ui32HeapCount;
+ u32 ui32SyncHeapID;
+ u32 ui32MappingHeapID;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ struct BM_CONTEXT *pBMKernelContext;
+ struct BM_CONTEXT *pBMContext;
+};
+
+struct DEV_ARENA_DESCRIPTOR {
+ u32 ui32HeapID;
+ char *pszName;
+ struct IMG_DEV_VIRTADDR BaseDevVAddr;
+ u32 ui32Size;
+ u32 DevMemHeapType;
+
+ u32 ui32DataPageSize;
+
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
+};
+
+struct SYS_DATA;
+
+struct PVRSRV_DEVICE_NODE {
+ struct PVRSRV_DEVICE_IDENTIFIER sDevId;
+ u32 ui32RefCount;
+
+ enum PVRSRV_ERROR (*pfnInitDevice)(void *);
+ enum PVRSRV_ERROR (*pfnDeInitDevice)(void *);
+
+ enum PVRSRV_ERROR (*pfnInitDeviceCompatCheck)(
+ struct PVRSRV_DEVICE_NODE *);
+
+ enum PVRSRV_ERROR (*pfnMMUInitialise)(struct PVRSRV_DEVICE_NODE *,
+ struct MMU_CONTEXT **,
+ struct IMG_DEV_PHYADDR *);
+ void (*pfnMMUFinalise)(struct MMU_CONTEXT *);
+ void (*pfnMMUInsertHeap)(struct MMU_CONTEXT *, struct MMU_HEAP *);
+ struct MMU_HEAP *(*pfnMMUCreate)(struct MMU_CONTEXT *,
+ struct DEV_ARENA_DESCRIPTOR *, struct RA_ARENA **);
+ void (*pfnMMUDelete)(struct MMU_HEAP *);
+ IMG_BOOL (*pfnMMUAlloc)(struct MMU_HEAP *pMMU, size_t uSize, u32 uFlags,
+ u32 uDevVAddrAlignment,
+ struct IMG_DEV_VIRTADDR *pDevVAddr);
+ void (*pfnMMUFree)(struct MMU_HEAP *, struct IMG_DEV_VIRTADDR, u32);
+ void (*pfnMMUEnable)(struct MMU_HEAP *);
+ void (*pfnMMUDisable)(struct MMU_HEAP *);
+ void (*pfnMMUMapPages)(struct MMU_HEAP *pMMU,
+ struct IMG_DEV_VIRTADDR devVAddr,
+ struct IMG_SYS_PHYADDR SysPAddr,
+ size_t uSize, u32 ui32MemFlags, void *hUniqueTag);
+ void (*pfnMMUMapShadow)(struct MMU_HEAP *pMMU,
+ struct IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ size_t uSize, void *CpuVAddr, void *hOSMemHandle,
+ struct IMG_DEV_VIRTADDR *pDevVAddr, u32 ui32MemFlags,
+ void *hUniqueTag);
+ void (*pfnMMUUnmapPages)(struct MMU_HEAP *pMMU,
+ struct IMG_DEV_VIRTADDR dev_vaddr, u32 ui32PageCount,
+ void *hUniqueTag);
+
+ void (*pfnMMUMapScatter)(struct MMU_HEAP *pMMU,
+ struct IMG_DEV_VIRTADDR DevVAddr,
+ struct IMG_SYS_PHYADDR *psSysAddr,
+ size_t uSize, u32 ui32MemFlags, void *hUniqueTag);
+
+ struct IMG_DEV_PHYADDR(*pfnMMUGetPhysPageAddr)(
+ struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR sDevVPageAddr);
+ struct IMG_DEV_PHYADDR(*pfnMMUGetPDDevPAddr)(
+ struct MMU_CONTEXT *pMMUContext);
+
+ IMG_BOOL (*pfnDeviceISR)(void *);
+
+ void *pvISRData;
+ u32 ui32SOCInterruptBit;
+
+ void (*pfnDeviceMISR)(void *);
+ void (*pfnDeviceCommandComplete)(struct PVRSRV_DEVICE_NODE *
+ psDeviceNode);
+
+ IMG_BOOL bReProcessDeviceCommandComplete;
+ struct DEVICE_MEMORY_INFO sDevMemoryInfo;
+ void *pvDevice;
+ u32 ui32pvDeviceSize;
+
+ struct RESMAN_CONTEXT *hResManContext;
+ struct SYS_DATA *psSysData;
+ struct RA_ARENA *psLocalDevMemArena;
+ u32 ui32Flags;
+ struct HASH_TABLE *sync_table;
+ struct PVRSRV_DEVICE_NODE *psNext;
+};
+
+enum PVRSRV_ERROR PVRSRVRegisterDevice(struct SYS_DATA *psSysData,
+ enum PVRSRV_ERROR (*pfnRegisterDevice)(struct PVRSRV_DEVICE_NODE *),
+ u32 ui32SOCInterruptBit, u32 *pui32DeviceIndex);
+
+enum PVRSRV_ERROR PVRSRVInitialiseDevice(u32 ui32DevIndex);
+enum PVRSRV_ERROR PVRSRVFinaliseSystem(IMG_BOOL bInitSuccesful);
+
+enum PVRSRV_ERROR PVRSRVDevInitCompatCheck(struct PVRSRV_DEVICE_NODE
+ *psDeviceNode);
+
+enum PVRSRV_ERROR PVRSRVDeinitialiseDevice(u32 ui32DevIndex);
+
+
+enum PVRSRV_ERROR PollForValueKM(u32 __iomem *pui32LinMemAddr,
+ u32 ui32Value, u32 ui32Mask, u32 ui32Waitus, u32 ui32Tries);
+
+enum PVRSRV_ERROR PVRSRVInit(struct SYS_DATA *psSysData);
+void PVRSRVDeInit(struct SYS_DATA *psSysData);
+IMG_BOOL PVRSRVDeviceLISR(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+IMG_BOOL PVRSRVSystemLISR(void *pvSysData);
+void PVRSRVMISR(void *pvSysData);
+
+#endif
diff --git a/drivers/gpu/pvr/deviceclass.c b/drivers/gpu/pvr/deviceclass.c
new file mode 100644
index 00000000000..c5374e52382
--- /dev/null
+++ b/drivers/gpu/pvr/deviceclass.c
@@ -0,0 +1,1522 @@
+/**********************************************************************
+ *
+ * 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 <linux/module.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "kernelbuffer.h"
+#include "pvr_bridge_km.h"
+
+struct PVRSRV_DC_SRV2DISP_KMJTABLE;
+
+struct PVRSRV_DC_BUFFER {
+ struct PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+};
+
+struct PVRSRV_DC_SWAPCHAIN {
+ void *hExtSwapChain;
+ struct PVRSRV_QUEUE_INFO *psQueue;
+ struct PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ u32 ui32BufferCount;
+ struct PVRSRV_DC_BUFFER *psLastFlipBuffer;
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ void *hResItem;
+};
+
+struct PVRSRV_DISPLAYCLASS_INFO {
+ u32 ui32RefCount;
+ u32 ui32DeviceID;
+ void *hExtDevice;
+ struct PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable;
+ void *hDevMemContext;
+ struct PVRSRV_DC_BUFFER sSystemBuffer;
+};
+
+struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO {
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct RESMAN_ITEM *hResItem;
+};
+
+struct PVRSRV_BC_SRV2BUFFER_KMJTABLE;
+
+struct PVRSRV_BC_BUFFER {
+ struct PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
+ struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+};
+
+struct PVRSRV_BUFFERCLASS_INFO {
+ u32 ui32RefCount;
+ u32 ui32DeviceID;
+ void *hExtDevice;
+ struct PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable;
+ void *hDevMemContext;
+
+ u32 ui32BufferCount;
+ struct PVRSRV_BC_BUFFER *psBuffer;
+
+};
+
+struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO {
+ struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ void *hResItem;
+};
+
+static struct PVRSRV_DISPLAYCLASS_INFO *DCDeviceHandleToDCInfo(void *hDeviceKM)
+{
+ struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ psDCPerContextInfo = (struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)
+ hDeviceKM;
+
+ return psDCPerContextInfo->psDCInfo;
+}
+
+static struct PVRSRV_BUFFERCLASS_INFO *BCDeviceHandleToBCInfo(void *hDeviceKM)
+{
+ struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ psBCPerContextInfo = (struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)
+ hDeviceKM;
+
+ return psBCPerContextInfo->psBCInfo;
+}
+
+enum PVRSRV_ERROR PVRSRVEnumerateDCKM(enum PVRSRV_DEVICE_CLASS DeviceClass,
+ u32 *pui32DevCount, u32 *pui32DevID)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ unsigned ui32DevCount = 0;
+ struct SYS_DATA *psSysData;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVEnumerateDCKM: Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ if ((psDeviceNode->sDevId.eDeviceClass == DeviceClass) &&
+ (psDeviceNode->sDevId.eDeviceType ==
+ PVRSRV_DEVICE_TYPE_EXT)) {
+ ui32DevCount++;
+ if (pui32DevID) {
+ *pui32DevID++ =
+ psDeviceNode->sDevId.ui32DeviceIndex;
+ }
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ if (pui32DevCount) {
+ *pui32DevCount = ui32DevCount;
+ } else if (pui32DevID == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVEnumerateDCKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR PVRSRVRegisterDCDeviceKM(
+ struct PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+ u32 *pui32DeviceID)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo = NULL;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterDCDeviceKM: Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psDCInfo),
+ (void **) &psDCInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDCInfo, 0, sizeof(*psDCInfo));
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE),
+ (void **)&psDCInfo->psFuncTable,
+ NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc");
+ goto ErrorExit;
+ }
+ OSMemSet(psDCInfo->psFuncTable, 0,
+ sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE));
+
+ *psDCInfo->psFuncTable = *psFuncTable;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DEVICE_NODE),
+ (void **) &psDeviceNode, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc");
+ goto ErrorExit;
+ }
+ OSMemSet(psDeviceNode, 0, sizeof(struct 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;
+
+ AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+ psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ SysRegisterExternalDevice(psDeviceNode);
+
+ psDeviceNode->psNext = psSysData->psDeviceNodeList;
+ psSysData->psDeviceNodeList = psDeviceNode;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psDCInfo->psFuncTable)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE),
+ psDCInfo->psFuncTable, NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DISPLAYCLASS_INFO),
+ psDCInfo, NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static enum PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(u32 ui32DevIndex)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_DEVICE_NODE **ppsDeviceNode, *psDeviceNode;
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRemoveDCDeviceKM: Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ ppsDeviceNode = &psSysData->psDeviceNodeList;
+ while (*ppsDeviceNode) {
+ switch ((*ppsDeviceNode)->sDevId.eDeviceClass) {
+ case PVRSRV_DEVICE_CLASS_DISPLAY:
+ {
+ if ((*ppsDeviceNode)->sDevId.ui32DeviceIndex ==
+ ui32DevIndex)
+ goto FoundDevice;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ ppsDeviceNode = &((*ppsDeviceNode)->psNext);
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRemoveDCDeviceKM: requested device %d not present",
+ ui32DevIndex);
+
+ return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+ psDeviceNode = *ppsDeviceNode;
+
+ psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice;
+
+ if (psDCInfo->ui32RefCount == 0) {
+ *ppsDeviceNode = psDeviceNode->psNext;
+ SysRemoveExternalDevice(psDeviceNode);
+ PVR_ASSERT(psDCInfo->ui32RefCount == 0);
+ FreeDeviceID(psSysData, ui32DevIndex);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE),
+ psDCInfo->psFuncTable, NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DISPLAYCLASS_INFO), psDCInfo,
+ NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct 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;
+}
+
+static enum PVRSRV_ERROR PVRSRVRegisterBCDeviceKM(
+ struct PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
+ u32 *pui32DeviceID)
+{
+ struct PVRSRV_BUFFERCLASS_INFO *psBCInfo = NULL;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCInfo),
+ (void **) &psBCInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psBCInfo, 0, sizeof(*psBCInfo));
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ (void **) &psBCInfo->psFuncTable,
+ NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc");
+ goto ErrorExit;
+ }
+ OSMemSet(psBCInfo->psFuncTable, 0,
+ sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE));
+
+ *psBCInfo->psFuncTable = *psFuncTable;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DEVICE_NODE),
+ (void **) &psDeviceNode, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc");
+ goto ErrorExit;
+ }
+ OSMemSet(psDeviceNode, 0, sizeof(struct 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;
+
+ AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
+ psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+ if (pui32DeviceID)
+ *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ psDeviceNode->psNext = psSysData->psDeviceNodeList;
+ psSysData->psDeviceNodeList = psDeviceNode;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psBCInfo->psFuncTable)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE *),
+ psBCInfo->psFuncTable, NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BUFFERCLASS_INFO), psBCInfo, NULL);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
+static enum PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(u32 ui32DevIndex)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_DEVICE_NODE **ppsDevNode, *psDevNode;
+ struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRemoveBCDeviceKM: Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ ppsDevNode = &psSysData->psDeviceNodeList;
+ while (*ppsDevNode) {
+ switch ((*ppsDevNode)->sDevId.eDeviceClass) {
+ case PVRSRV_DEVICE_CLASS_BUFFER:
+ {
+ if ((*ppsDevNode)->sDevId.ui32DeviceIndex ==
+ ui32DevIndex)
+ goto FoundDevice;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ ppsDevNode = &(*ppsDevNode)->psNext;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRemoveBCDeviceKM: requested device %d not present",
+ ui32DevIndex);
+
+ return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+ psDevNode = *(ppsDevNode);
+
+ psBCInfo = (struct PVRSRV_BUFFERCLASS_INFO *)psDevNode->pvDevice;
+
+ if (psBCInfo->ui32RefCount == 0) {
+ *ppsDevNode = psDevNode->psNext;
+ FreeDeviceID(psSysData, ui32DevIndex);
+ psBCInfo =
+ (struct PVRSRV_BUFFERCLASS_INFO *)psDevNode->pvDevice;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BC_SRV2BUFFER_KMJTABLE),
+ psBCInfo->psFuncTable, NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BUFFERCLASS_INFO), psBCInfo,
+ NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct 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;
+}
+
+enum PVRSRV_ERROR PVRSRVCloseDCDeviceKM(void *hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psDCPerContextInfo = (struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)
+ hDeviceKM;
+
+ ResManFreeResByPtr(psDCPerContextInfo->hResItem);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR CloseDCDeviceCallBack(void *pvParam, u32 ui32Param)
+{
+ struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psDCPerContextInfo = (struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)
+ pvParam;
+ psDCInfo = psDCPerContextInfo->psDCInfo;
+
+ psDCInfo->ui32RefCount--;
+ if (psDCInfo->ui32RefCount == 0) {
+ struct PVRSRV_DC_SRV2DISP_KMJTABLE *jtbl;
+
+ jtbl = psDCInfo->psFuncTable;
+
+ jtbl->pfnCloseDCDevice(psDCInfo->hExtDevice);
+
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.
+ psKernelSyncInfo);
+
+ psDCInfo->hDevMemContext = NULL;
+ psDCInfo->hExtDevice = NULL;
+
+ module_put(jtbl->owner);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO),
+ psDCPerContextInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVOpenDCDeviceKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ u32 ui32DeviceID, void *hDevCookie,
+ void **phDeviceKM)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+
+ if (!phDeviceKM || !hDevCookie) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: Invalid params");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ if ((psDeviceNode->sDevId.eDeviceClass ==
+ PVRSRV_DEVICE_CLASS_DISPLAY) &&
+ (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) {
+
+ psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *)
+ psDeviceNode->pvDevice;
+ goto FoundDevice;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVOpenDCDeviceKM: no devnode matching index %d",
+ ui32DeviceID);
+
+ return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psDCPerContextInfo),
+ (void **)&psDCPerContextInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenDCDeviceKM: "
+ "Failed psDCPerContextInfo alloc");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo));
+
+ if (psDCInfo->ui32RefCount++ == 0) {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DC_SRV2DISP_KMJTABLE *jtbl;
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
+
+ jtbl = psDCInfo->psFuncTable;
+ if (!try_module_get(jtbl->owner)) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: can't get DC module");
+ return PVRSRV_ERROR_INVALID_DEVICE;
+ }
+
+ 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--;
+ module_put(jtbl->owner);
+ return eError;
+ }
+
+ eError = jtbl->pfnOpenDCDevice(ui32DeviceID,
+ &psDCInfo->hExtDevice,
+ (struct 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--;
+ module_put(jtbl->owner);
+ PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.
+ sDeviceClassBuffer.psKernelSyncInfo);
+ return eError;
+ }
+ }
+
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ psDCPerContextInfo->hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+ psDCPerContextInfo, 0, CloseDCDeviceCallBack);
+
+ *phDeviceKM = (void *) psDCPerContextInfo;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVEnumDCFormatsKM(void *hDeviceKM,
+ u32 *pui32Count,
+ struct DISPLAY_FORMAT *psFormat)
+{
+ struct 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);
+}
+
+enum PVRSRV_ERROR PVRSRVEnumDCDimsKM(void *hDeviceKM,
+ struct DISPLAY_FORMAT *psFormat,
+ u32 *pui32Count, struct DISPLAY_DIMS *psDim)
+{
+ struct 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);
+}
+
+enum PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(void *hDeviceKM, void **phBuffer)
+{
+ enum PVRSRV_ERROR eError;
+ struct 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;
+}
+
+enum PVRSRV_ERROR PVRSRVGetDCInfoKM(void *hDeviceKM,
+ struct DISPLAY_INFO *psDisplayInfo)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(void *hSwapChain)
+{
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hSwapChain) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVDestroyDCSwapChainKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChain = hSwapChain;
+
+ ResManFreeResByPtr(psSwapChain->hResItem);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR DestroyDCSwapChainCallBack(void *pvParam,
+ u32 ui32Param)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain = pvParam;
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
+ u32 i;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ 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)
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct PVRSRV_DC_SWAPCHAIN),
+ psSwapChain, NULL);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDeviceKM, u32 ui32Flags,
+ struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ u32 ui32BufferCount, u32 ui32OEMFlags,
+ void **phSwapChain, u32 *pui32SwapChainID)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain = NULL;
+ struct PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ struct PVRSRV_QUEUE_INFO *psQueue = NULL;
+ enum PVRSRV_ERROR eError;
+ u32 i;
+
+ if (!hDeviceKM || !psDstSurfAttrib || !psSrcSurfAttrib ||
+ !phSwapChain || !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 (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DC_SWAPCHAIN),
+ (void **) &psSwapChain, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc");
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+ OSMemSet(psSwapChain, 0, sizeof(struct 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.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] =
+ (struct PVRSRV_SYNC_DATA *)psSwapChain->asBuffer[i].
+ sDeviceClassBuffer.psKernelSyncInfo->
+ psSyncDataMemInfoKM->pvLinAddrKM;
+ }
+
+ psSwapChain->ui32BufferCount = ui32BufferCount;
+ psSwapChain->psDCInfo = psDCInfo;
+
+ eError =
+ psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
+ ui32Flags,
+ psDstSurfAttrib,
+ psSrcSurfAttrib,
+ ui32BufferCount,
+ apsSyncData,
+ ui32OEMFlags,
+ &psSwapChain->hExtSwapChain,
+ pui32SwapChainID);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateDCSwapChainKM: "
+ "Failed to create 3rd party SwapChain");
+ goto ErrorExit;
+ }
+
+ *phSwapChain = (void *) psSwapChain;
+
+ psSwapChain->hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN,
+ psSwapChain, 0,
+ DestroyDCSwapChainCallBack);
+
+ return eError;
+
+ErrorExit:
+
+ for (i = 0; i < ui32BufferCount; i++) {
+ if (psSwapChain->asBuffer[i].sDeviceClassBuffer.
+ psKernelSyncInfo) {
+ PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ }
+ }
+
+ if (psQueue)
+ PVRSRVDestroyCommandQueueKM(psQueue);
+
+ if (psSwapChain) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DC_SWAPCHAIN), psSwapChain,
+ NULL);
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVSetDCDstRectKM(void *hDeviceKM, void *hSwapChain,
+ struct IMG_RECT *psRect)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChain) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSetDCDstRectKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain, psRect);
+}
+
+enum PVRSRV_ERROR PVRSRVSetDCSrcRectKM(void *hDeviceKM, void *hSwapChain,
+ struct IMG_RECT *psRect)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChain) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSetDCSrcRectKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain, psRect);
+}
+
+enum PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(void *hDeviceKM, void *hSwapChain,
+ u32 ui32CKColour)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChain) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSetDCDstColourKeyKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain, ui32CKColour);
+}
+
+enum PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(void *hDeviceKM, void *hSwapChain,
+ u32 ui32CKColour)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+
+ if (!hDeviceKM || !hSwapChain) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSetDCSrcColourKeyKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
+
+ return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice,
+ psSwapChain->hExtSwapChain, ui32CKColour);
+}
+
+enum PVRSRV_ERROR PVRSRVGetDCBuffersKM(void *hDeviceKM, void *hSwapChain,
+ u32 *pui32BufferCount, void **phBuffer)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ void *ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+ enum PVRSRV_ERROR eError;
+ u32 i;
+
+ if (!hDeviceKM || !hSwapChain || !phBuffer) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVGetDCBuffersKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
+
+ 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;
+}
+
+enum PVRSRV_ERROR PVRSRVSwapToDCBufferKM(void *hDeviceKM, void *hBuffer,
+ u32 ui32SwapInterval, void *hPrivateTag,
+ u32 ui32ClipRectCount,
+ struct IMG_RECT *psClipRect)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_BUFFER *psBuffer;
+ struct PVRSRV_QUEUE_INFO *psQueue;
+ struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ u32 i;
+ u32 ui32NumSrcSyncs = 1;
+ struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ struct PVRSRV_COMMAND *psCommand;
+
+ if (!hDeviceKM || !hBuffer || !psClipRect) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSwapToDCBufferKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psBuffer = (struct PVRSRV_DC_BUFFER *)hBuffer;
+
+ 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(struct DISPLAYCLASS_FLIP_COMMAND) +
+ (sizeof(struct IMG_RECT) *
+ ui32ClipRectCount));
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSwapToDCBufferKM: Failed to get space in queue");
+ goto Exit;
+ }
+
+ psFlipCmd = (struct 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 =
+ (struct IMG_RECT *)((u8 *) psFlipCmd +
+ sizeof(struct 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(IMG_FALSE) !=
+ 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:
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVSwapToDCSystemKM(void *hDeviceKM, void *hSwapChain)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_QUEUE_INFO *psQueue;
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ u32 ui32NumSrcSyncs = 1;
+ struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2];
+ struct PVRSRV_COMMAND *psCommand;
+
+ if (!hDeviceKM || !hSwapChain) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSwapToDCSystemKM: Invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+ psSwapChain = (struct PVRSRV_DC_SWAPCHAIN *)hSwapChain;
+
+ 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(struct DISPLAYCLASS_FLIP_COMMAND));
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSwapToDCSystemKM: Failed to get space in queue");
+ goto Exit;
+ }
+
+ psFlipCmd = (struct 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(IMG_FALSE) !=
+ 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:
+ return eError;
+}
+
+static enum PVRSRV_ERROR PVRSRVRegisterSystemISRHandler(
+ IMG_BOOL (*pfnISRHandler)(void *),
+ void *pvISRHandlerData,
+ u32 ui32ISRSourceMask,
+ u32 ui32DeviceID)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_DEVICE_NODE *psDevNode;
+
+ PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask);
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterSystemISRHandler: "
+ "Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDevNode = psSysData->psDeviceNodeList;
+ while (psDevNode) {
+ if (psDevNode->sDevId.ui32DeviceIndex == ui32DeviceID)
+ break;
+ psDevNode = psDevNode->psNext;
+ }
+
+ 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(u32 ui32State)
+{
+ struct PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSetDCState: Failed to get SysData");
+ return;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode != NULL) {
+ if (psDeviceNode->sDevId.eDeviceClass ==
+ PVRSRV_DEVICE_CLASS_DISPLAY) {
+ psDCInfo = (struct PVRSRV_DISPLAYCLASS_INFO *)
+ psDeviceNode->pvDevice;
+ if (psDCInfo->psFuncTable->pfnSetDCState &&
+ psDCInfo->hExtDevice)
+ psDCInfo->psFuncTable->pfnSetDCState(
+ psDCInfo->hExtDevice,
+ ui32State);
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+}
+
+IMG_BOOL PVRGetDisplayClassJTable(struct PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(struct PVRSRV_DC_DISP2SRV_KMJTABLE);
+ psJTable->pfnPVRSRVRegisterDCDevice = PVRSRVRegisterDCDeviceKM;
+ psJTable->pfnPVRSRVRemoveDCDevice = PVRSRVRemoveDCDeviceKM;
+ psJTable->pfnPVRSRVOEMFunction = SysOEMFunction;
+ psJTable->pfnPVRSRVRegisterCmdProcList = PVRSRVRegisterCmdProcListKM;
+ psJTable->pfnPVRSRVRemoveCmdProcList = PVRSRVRemoveCmdProcListKM;
+ psJTable->pfnPVRSRVCmdComplete = PVRSRVCommandCompleteKM;
+ psJTable->pfnPVRSRVRegisterSystemISRHandler =
+ PVRSRVRegisterSystemISRHandler;
+ psJTable->pfnPVRSRVRegisterPowerDevice = PVRSRVRegisterPowerDevice;
+
+ return IMG_TRUE;
+}
+EXPORT_SYMBOL(PVRGetDisplayClassJTable);
+
+enum PVRSRV_ERROR PVRSRVCloseBCDeviceKM(void *hDeviceKM,
+ IMG_BOOL bResManCallback)
+{
+ struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+
+ PVR_UNREFERENCED_PARAMETER(bResManCallback);
+
+ psBCPerContextInfo = (struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)
+ hDeviceKM;
+
+ ResManFreeResByPtr(psBCPerContextInfo->hResItem);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR CloseBCDeviceCallBack(void *pvParam, u32 ui32Param)
+{
+ struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psBCPerContextInfo = (struct 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)
+ PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+
+ if (psBCInfo->psBuffer)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BC_BUFFER),
+ psBCInfo->psBuffer, NULL);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO),
+ psBCPerContextInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVOpenBCDeviceKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ u32 ui32DeviceID, void *hDevCookie,
+ void **phDeviceKM)
+{
+ struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+ u32 i;
+ enum PVRSRV_ERROR eError;
+
+ if (!phDeviceKM || !hDevCookie) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Invalid params");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: Failed to get SysData");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ if ((psDeviceNode->sDevId.eDeviceClass ==
+ PVRSRV_DEVICE_CLASS_BUFFER) &&
+ (psDeviceNode->sDevId.ui32DeviceIndex == ui32DeviceID)) {
+
+ psBCInfo = (struct PVRSRV_BUFFERCLASS_INFO *)
+ psDeviceNode->pvDevice;
+ goto FoundDevice;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVOpenBCDeviceKM: No devnode matching index %d",
+ ui32DeviceID);
+
+ return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBCPerContextInfo),
+ (void **)&psBCPerContextInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: "
+ "Failed psBCPerContextInfo alloc");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo));
+
+ if (psBCInfo->ui32RefCount++ == 0) {
+ struct BUFFER_INFO sBufferInfo;
+
+ psDeviceNode = (struct 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(struct PVRSRV_BC_BUFFER) *
+ sBufferInfo.ui32BufferCount,
+ (void **) &psBCInfo->psBuffer,
+ NULL);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVOpenBCDeviceKM: "
+ "Failed to allocate BC buffers");
+ return eError;
+ }
+ OSMemSet(psBCInfo->psBuffer, 0,
+ sizeof(struct 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;
+ }
+
+ 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:
+
+ for (i = 0; i < psBCInfo->ui32BufferCount; i++) {
+ if (psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) {
+ PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].
+ sDeviceClassBuffer.
+ psKernelSyncInfo);
+ }
+ }
+
+ if (psBCInfo->psBuffer) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_BC_BUFFER), psBCInfo->psBuffer,
+ NULL);
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVGetBCInfoKM(void *hDeviceKM,
+ struct BUFFER_INFO *psBufferInfo)
+{
+ struct PVRSRV_BUFFERCLASS_INFO *psBCInfo;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVGetBCBufferKM(void *hDeviceKM, u32 ui32BufferIndex,
+ void **phBuffer)
+{
+ struct 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;
+}
+
+IMG_BOOL PVRGetBufferClassJTable(struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
+{
+ psJTable->ui32TableSize = sizeof(struct PVRSRV_BC_BUFFER2SRV_KMJTABLE);
+
+ psJTable->pfnPVRSRVRegisterBCDevice = PVRSRVRegisterBCDeviceKM;
+ psJTable->pfnPVRSRVRemoveBCDevice = PVRSRVRemoveBCDeviceKM;
+
+ return IMG_TRUE;
+}
+EXPORT_SYMBOL(PVRGetBufferClassJTable);
+
diff --git a/drivers/gpu/pvr/devicemem.c b/drivers/gpu/pvr/devicemem.c
new file mode 100644
index 00000000000..3912f2bc117
--- /dev/null
+++ b/drivers/gpu/pvr/devicemem.c
@@ -0,0 +1,1208 @@
+/**********************************************************************
+ *
+ * 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"
+
+#include <linux/pagemap.h>
+
+static enum PVRSRV_ERROR AllocDeviceMem(void *hDevCookie, void *hDevMemHeap,
+ u32 ui32Flags, u32 ui32Size, u32 ui32Alignment,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+struct RESMAN_MAP_DEVICE_MEM_DATA {
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
+};
+
+static inline void get_page_details(u32 vaddr, size_t byte_size,
+ u32 *page_offset_out, int *page_count_out)
+{
+ size_t host_page_size;
+ u32 page_offset;
+ int page_count;
+
+ host_page_size = PAGE_SIZE;
+ page_offset = vaddr & (host_page_size - 1);
+ page_count = PAGE_ALIGN(byte_size + page_offset) / host_page_size;
+
+ *page_offset_out = page_offset;
+ *page_count_out = page_count;
+}
+
+static inline int get_page_count(u32 vaddr, size_t byte_size)
+{
+ u32 page_offset;
+ int page_count;
+
+ get_page_details(vaddr, byte_size, &page_offset, &page_count);
+
+ return page_count;
+}
+
+enum PVRSRV_ERROR PVRSRVGetDeviceMemHeapsKM(void *hDevCookie,
+ struct PVRSRV_HEAP_INFO *psHeapInfo)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ u32 ui32HeapCount;
+ struct 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 = (struct 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++) {
+ OSMemSet(psHeapInfo + i, 0, sizeof(*psHeapInfo));
+ psHeapInfo[i].ui32HeapID = (u32) PVRSRV_UNDEFINED_HEAP_ID;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVCreateDeviceMemContextKM(void *hDevCookie,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void **phDevMemContext,
+ u32 *pui32ClientHeapCount,
+ struct PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbCreated, IMG_BOOL *pbShared)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ u32 ui32HeapCount, ui32ClientHeapCount = 0;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ void *hDevMemContext;
+ void *hDevMemHeap;
+ struct 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 = (struct 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;
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+ 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;
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+ *phDevMemContext = hDevMemContext;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVDestroyDeviceMemContextKM(void *hDevCookie,
+ void *hDevMemContext,
+ IMG_BOOL *pbDestroyed)
+{
+ int destroyed;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ destroyed = pvr_put_ctx(hDevMemContext);
+ if (pbDestroyed)
+ *pbDestroyed = destroyed ? IMG_TRUE : IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVGetDeviceMemHeapInfoKM(void *hDevCookie,
+ void *hDevMemContext,
+ u32 *pui32ClientHeapCount,
+ struct PVRSRV_HEAP_INFO *psHeapInfo,
+ IMG_BOOL *pbShared)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ u32 ui32HeapCount, ui32ClientHeapCount = 0;
+ struct 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 = (struct 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;
+ pbShared[ui32ClientHeapCount] = IMG_TRUE;
+ 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;
+ pbShared[ui32ClientHeapCount] = IMG_FALSE;
+
+ ui32ClientHeapCount++;
+ break;
+ }
+ }
+ *pui32ClientHeapCount = ui32ClientHeapCount;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR AllocDeviceMem(void *hDevCookie, void *hDevMemHeap,
+ u32 ui32Flags, u32 ui32Size,
+ u32 ui32Alignment,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ void *hBuffer;
+
+ struct PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ *ppsMemInfo = NULL;
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO),
+ (void **) &psMemInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "AllocDeviceMem: Failed to alloc memory for block");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
+
+ bBMError = BM_Alloc(hDevMemHeap, NULL, ui32Size,
+ &psMemInfo->ui32Flags, ui32Alignment, &hBuffer);
+
+ if (!bBMError) {
+ PVR_DPF(PVR_DBG_ERROR, "AllocDeviceMem: BM_Alloc Failed");
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct 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 enum PVRSRV_ERROR FreeDeviceMem(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ void *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);
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct PVRSRV_KERNEL_MEM_INFO),
+ psMemInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVAllocSyncInfoKM(void *hDevCookie, void *hDevMemContext,
+ struct PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo)
+{
+ void *hSyncDevMemHeap;
+ struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ struct BM_CONTEXT *pBMContext;
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ struct PVRSRV_SYNC_DATA *psSyncData;
+
+ eError = OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct PVRSRV_KERNEL_SYNC_INFO),
+ (void **) &psKernelSyncInfo, NULL);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVAllocSyncInfoKM: Failed to alloc memory");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ pBMContext = (struct BM_CONTEXT *)hDevMemContext;
+ psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
+
+ hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->
+ ui32SyncHeapID].hDevMemHeap;
+
+ eError = AllocDeviceMem(hDevCookie, hSyncDevMemHeap,
+ PVRSRV_MEM_CACHE_CONSISTENT,
+ sizeof(struct 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(struct 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,
+ 0, MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
+#endif
+
+ psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr =
+ psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr +
+ offsetof(struct PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
+ psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr =
+ psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr +
+ offsetof(struct PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+
+ psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = NULL;
+
+ *ppsKernelSyncInfo = psKernelSyncInfo;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVFreeSyncInfoKM(
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo,
+ NULL);
+
+ return PVRSRV_OK;
+}
+
+static inline
+void get_syncinfo(struct PVRSRV_KERNEL_SYNC_INFO *syncinfo)
+{
+ syncinfo->refcount++;
+}
+
+static inline
+void put_syncinfo(struct PVRSRV_KERNEL_SYNC_INFO *syncinfo)
+{
+ struct PVRSRV_DEVICE_NODE *dev = syncinfo->dev_cookie;
+
+ syncinfo->refcount--;
+
+ if (!syncinfo->refcount) {
+ HASH_Remove(dev->sync_table,
+ syncinfo->phys_addr.uiAddr);
+ PVRSRVFreeSyncInfoKM(syncinfo);
+ }
+}
+
+static inline
+enum PVRSRV_ERROR alloc_or_reuse_syncinfo(void *dev_cookie,
+ void *mem_context_handle,
+ struct PVRSRV_KERNEL_SYNC_INFO **syncinfo,
+ struct IMG_SYS_PHYADDR *phys_addr)
+{
+ enum PVRSRV_ERROR error;
+ struct PVRSRV_DEVICE_NODE *dev;
+
+ dev = (struct PVRSRV_DEVICE_NODE *) dev_cookie;
+
+ *syncinfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ HASH_Retrieve(dev->sync_table,
+ phys_addr->uiAddr);
+
+ if (!*syncinfo) {
+ /* Dont' have one so create one */
+ error = PVRSRVAllocSyncInfoKM(dev_cookie, mem_context_handle,
+ syncinfo);
+
+ if (error != PVRSRV_OK)
+ return error;
+
+ /* Setup our extra data */
+ (*syncinfo)->phys_addr.uiAddr = phys_addr->uiAddr;
+ (*syncinfo)->dev_cookie = dev_cookie;
+ (*syncinfo)->refcount = 1;
+
+ if (!HASH_Insert(dev->sync_table, phys_addr->uiAddr,
+ (u32) *syncinfo)) {
+ PVR_DPF(PVR_DBG_ERROR, "alloc_or_reuse_syncinfo: "
+ "Failed to add syncobject to hash table");
+ return PVRSRV_ERROR_GENERIC;
+ }
+ } else
+ get_syncinfo(*syncinfo);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR FreeDeviceMemCallBack(void *pvParam, u32 ui32Param)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ 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)
+ eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+
+ if (eError == PVRSRV_OK)
+ eError = FreeDeviceMem(psMemInfo);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVFreeDeviceMemKM(void *hDevCookie,
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ if (psMemInfo->sMemBlk.hResItem != NULL)
+ ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+ else
+ FreeDeviceMemCallBack(psMemInfo, 0);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVAllocDeviceMemKM(void *hDevCookie,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevMemHeap, u32 ui32Flags,
+ u32 ui32Size, u32 ui32Alignment,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ enum PVRSRV_ERROR eError;
+ struct BM_HEAP *psBMHeap;
+ void *hDevMemContext;
+
+ if (!hDevMemHeap || (ui32Size == 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 = (struct BM_HEAP *)hDevMemHeap;
+ hDevMemContext = (void *) psBMHeap->pBMContext;
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo);
+ if (eError != PVRSRV_OK)
+ goto free_mainalloc;
+ }
+
+ *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;
+}
+
+enum PVRSRV_ERROR PVRSRVDissociateDeviceMemKM(void *hDevCookie,
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevCookie;
+
+ PVR_UNREFERENCED_PARAMETER(hDevCookie);
+
+ if (!psMemInfo)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ eError = ResManDissociateRes(psMemInfo->sMemBlk.hResItem,
+ psDeviceNode->hResManContext);
+
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVGetFreeDeviceMemKM(u32 ui32Flags, u32 *pui32Total,
+ u32 *pui32Free, u32 *pui32LargestBlock)
+{
+
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+ PVR_UNREFERENCED_PARAMETER(pui32Total);
+ PVR_UNREFERENCED_PARAMETER(pui32Free);
+ PVR_UNREFERENCED_PARAMETER(pui32LargestBlock);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVUnwrapExtMemoryKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR UnwrapExtMemoryCallBack(void *pvParam, u32 ui32Param)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+ void *hOSWrapMem;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+
+ if (psMemInfo->psKernelSyncInfo)
+ put_syncinfo(psMemInfo->psKernelSyncInfo);
+
+ if (psMemInfo->sMemBlk.psIntSysPAddr) {
+ int page_count;
+
+ page_count = get_page_count((u32)psMemInfo->pvLinAddrKM,
+ psMemInfo->ui32AllocSize);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ page_count * sizeof(struct IMG_SYS_PHYADDR),
+ psMemInfo->sMemBlk.psIntSysPAddr, NULL);
+ }
+
+ if (eError == PVRSRV_OK) {
+ psMemInfo->ui32RefCount--;
+ eError = FreeDeviceMem(psMemInfo);
+ }
+
+ if (hOSWrapMem)
+ OSReleasePhysPageAddr(hOSWrapMem);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVWrapExtMemoryKM(void *hDevCookie,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevMemContext, u32 ui32ByteSize,
+ u32 ui32PageOffset, IMG_BOOL bPhysContig,
+ struct IMG_SYS_PHYADDR *psExtSysPAddr,
+ void *pvLinAddr,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL;
+ struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ u32 ui32HostPageSize = HOST_PAGESIZE();
+ void *hDevMemHeap = NULL;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ void *hBuffer;
+ struct PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ struct BM_HEAP *psBMHeap;
+ enum PVRSRV_ERROR eError;
+ void *pvPageAlignedCPUVAddr;
+ struct IMG_SYS_PHYADDR *psIntSysPAddr = NULL;
+ void *hOSWrapMem = NULL;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ int page_count = 0;
+ u32 i;
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevCookie;
+ PVR_ASSERT(psDeviceNode != NULL);
+
+ if (psDeviceNode == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVWrapExtMemoryKM: invalid parameter");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (pvLinAddr) {
+ get_page_details((u32)pvLinAddr, ui32ByteSize,
+ &ui32PageOffset, &page_count);
+ pvPageAlignedCPUVAddr = (void *)((u8 *) pvLinAddr -
+ ui32PageOffset);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ page_count * sizeof(struct IMG_SYS_PHYADDR),
+ (void **)&psIntSysPAddr, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: "
+ "Failed to alloc memory for block");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ eError = OSAcquirePhysPageAddr(pvPageAlignedCPUVAddr,
+ page_count * ui32HostPageSize,
+ psIntSysPAddr, &hOSWrapMem);
+ 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 = IMG_FALSE;
+ }
+
+ psDevMemoryInfo =
+ &((struct 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(struct PVRSRV_KERNEL_MEM_INFO),
+ (void **) &psMemInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVWrapExtMemoryKM: "
+ "Failed to alloc memory for block");
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExitPhase2;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+ 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 = (struct BM_HEAP *)hDevMemHeap;
+ hDevMemContext = (void *) psBMHeap->pBMContext;
+ eError = alloc_or_reuse_syncinfo(hDevCookie,
+ hDevMemContext,
+ &psMemInfo->psKernelSyncInfo,
+ psExtSysPAddr);
+ if (eError != PVRSRV_OK)
+ goto ErrorExitPhase4;
+
+ psMemInfo->ui32RefCount++;
+
+ psMemInfo->sMemBlk.hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_WRAP, psMemInfo, 0,
+ UnwrapExtMemoryCallBack);
+
+ *ppsMemInfo = psMemInfo;
+
+ return PVRSRV_OK;
+
+ErrorExitPhase4:
+ FreeDeviceMem(psMemInfo);
+ psMemInfo = NULL;
+
+ErrorExitPhase3:
+ if (psMemInfo) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo,
+ NULL);
+ }
+
+ErrorExitPhase2:
+ if (hOSWrapMem)
+ OSReleasePhysPageAddr(hOSWrapMem);
+
+ErrorExitPhase1:
+ if (psIntSysPAddr) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ page_count * sizeof(struct IMG_SYS_PHYADDR),
+ psIntSysPAddr, NULL);
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVUnmapDeviceMemoryKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR UnmapDeviceMemoryCallBack(void *pvParam, u32 ui32Param)
+{
+ enum PVRSRV_ERROR eError;
+ struct RESMAN_MAP_DEVICE_MEM_DATA *psMapData = pvParam;
+ int page_count;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ page_count = get_page_count((u32)psMapData->psMemInfo->pvLinAddrKM,
+ psMapData->psMemInfo->ui32AllocSize);
+
+ if (psMapData->psMemInfo->sMemBlk.psIntSysPAddr)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ page_count * sizeof(struct IMG_SYS_PHYADDR),
+ psMapData->psMemInfo->sMemBlk.psIntSysPAddr, NULL);
+
+ eError = FreeDeviceMem(psMapData->psMemInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "UnmapDeviceMemoryCallBack: "
+ "Failed to free DST meminfo");
+ return eError;
+ }
+
+ psMapData->psSrcMemInfo->ui32RefCount--;
+
+ PVR_ASSERT(psMapData->psSrcMemInfo->ui32RefCount != (u32) (-1));
+/*
+ * Don't free the source MemInfo as we didn't allocate it
+ * and it's not our job as the process the allocated
+ * should also free it when it's finished
+ */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA), psMapData, NULL);
+
+ return eError;
+}
+
+static inline int bm_is_continuous(const struct BM_BUF *buf)
+{
+ return buf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr;
+}
+
+enum PVRSRV_ERROR PVRSRVMapDeviceMemoryKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ struct PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ void *hDstDevMemHeap,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo)
+{
+ enum PVRSRV_ERROR eError;
+ u32 ui32PageOffset;
+ u32 ui32HostPageSize = HOST_PAGESIZE();
+ int page_count;
+ int i;
+ struct IMG_SYS_PHYADDR *psSysPAddr = NULL;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ struct BM_BUF *psBuf;
+ struct IMG_DEV_VIRTADDR sDevVAddr;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = NULL;
+ void *hBuffer;
+ struct PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ void *pvPageAlignedCPUVAddr;
+ struct 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;
+
+ get_page_details((u32)psSrcMemInfo->pvLinAddrKM,
+ psSrcMemInfo->ui32AllocSize,
+ &ui32PageOffset, &page_count);
+ pvPageAlignedCPUVAddr =
+ (void *) ((u8 *) psSrcMemInfo->pvLinAddrKM -
+ ui32PageOffset);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ page_count * sizeof(struct IMG_SYS_PHYADDR),
+ (void **) &psSysPAddr, NULL) != 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 - ui32PageOffset;
+ for (i = 0; i < page_count; i++) {
+ eError =
+ BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: "
+ "Failed to retrieve page list from device");
+ goto ErrorExit;
+ }
+
+ psSysPAddr[i] =
+ SysDevPAddrToSysPAddr(psDeviceNode->sDevId.eDeviceType,
+ sDevPAddr);
+
+ sDevVAddr.uiAddr += ui32HostPageSize;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA),
+ (void **)&psMapData, NULL) != 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(struct PVRSRV_KERNEL_MEM_INFO),
+ (void **)&psMemInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryKM: "
+ "Failed to alloc memory for block");
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorExit;
+ }
+
+ OSMemSet(psMemInfo, 0, sizeof(*psMemInfo));
+
+ psMemBlock = &(psMemInfo->sMemBlk);
+
+ bBMError = BM_Wrap(hDstDevMemHeap, psSrcMemInfo->ui32AllocSize,
+ ui32PageOffset, bm_is_continuous(psBuf), 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->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(struct IMG_SYS_PHYADDR), psSysPAddr, NULL);
+ }
+
+ if (psMemInfo) {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO), psMemInfo,
+ NULL);
+ }
+
+ if (psMapData) {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct RESMAN_MAP_DEVICE_MEM_DATA), psMapData,
+ NULL);
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVUnmapDeviceClassMemoryKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(void *pvParam,
+ u32 ui32Param)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ return FreeDeviceMem(psMemInfo);
+}
+
+enum PVRSRV_ERROR PVRSRVMapDeviceClassMemoryKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevMemContext, void *hDeviceClassBuffer,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo,
+ void **phOSMapInfo)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ struct PVRSRV_DEVICECLASS_BUFFER *psDeviceClassBuffer;
+ struct IMG_SYS_PHYADDR *psSysPAddr;
+ void *pvCPUVAddr, *pvPageAlignedCPUVAddr;
+ IMG_BOOL bPhysContig;
+ struct BM_CONTEXT *psBMContext;
+ struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ void *hDevMemHeap = NULL;
+ u32 ui32ByteSize;
+ u32 ui32Offset;
+ u32 ui32PageSize = HOST_PAGESIZE();
+ void *hBuffer;
+ struct PVRSRV_MEMBLK *psMemBlock;
+ IMG_BOOL bBMError;
+ u32 i;
+
+ if (!hDeviceClassBuffer || !ppsMemInfo || !phOSMapInfo ||
+ !hDevMemContext) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVMapDeviceClassMemoryKM: invalid parameters");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceClassBuffer = (struct PVRSRV_DEVICECLASS_BUFFER *)
+ hDeviceClassBuffer;
+
+ eError =
+ psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->
+ hExtDevice,
+ psDeviceClassBuffer->
+ hExtBuffer, &psSysPAddr,
+ &ui32ByteSize,
+ (void __iomem **)&pvCPUVAddr,
+ phOSMapInfo, &bPhysContig);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: "
+ "unable to get buffer address");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psBMContext = (struct 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 *)((u8 *)pvCPUVAddr - ui32Offset);
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO),
+ (void **)&psMemInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVMapDeviceClassMemoryKM: "
+ "Failed to alloc memory for block");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(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(struct 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/gpu/pvr/env_data.h b/drivers/gpu/pvr/env_data.h
new file mode 100644
index 00000000000..7317a51bbdd
--- /dev/null
+++ b/drivers/gpu/pvr/env_data.h
@@ -0,0 +1,57 @@
+/**********************************************************************
+ *
+ * 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 _ENV_DATA_
+#define _ENV_DATA_
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/workqueue.h>
+
+#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
+#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
+
+struct PVR_PCI_DEV {
+ struct pci_dev *psPCIDev;
+ enum HOST_PCI_INIT_FLAGS ePCIFlags;
+ IMG_BOOL abPCIResourceInUse[DEVICE_COUNT_RESOURCE];
+};
+
+struct ENV_DATA {
+ void *pvBridgeData;
+ struct pm_dev *psPowerDevice;
+ IMG_BOOL bLISRInstalled;
+ IMG_BOOL bMISRInstalled;
+ u32 ui32IRQ;
+ void *pvISRCookie;
+ struct workqueue_struct *psMISRWorkqueue;
+ struct work_struct sMISRWork;
+ void *pvSysData;
+ struct workqueue_struct *psPerfWorkqueue;
+ struct delayed_work sPerfWork;
+};
+
+#endif
diff --git a/drivers/gpu/pvr/env_perproc.h b/drivers/gpu/pvr/env_perproc.h
new file mode 100644
index 00000000000..7f092f6565c
--- /dev/null
+++ b/drivers/gpu/pvr/env_perproc.h
@@ -0,0 +1,51 @@
+/**********************************************************************
+ *
+ * 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 __ENV_PERPROC_H__
+#define __ENV_PERPROC_H__
+
+#include "linux/list.h"
+#include "linux/proc_fs.h"
+
+#include "img_types.h"
+
+struct PVRSRV_ENV_PER_PROCESS_DATA {
+ void *hBlockAlloc;
+ struct proc_dir_entry *psProcDir;
+};
+
+void RemovePerProcessProcDir(struct PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+enum PVRSRV_ERROR LinuxMMapPerProcessConnect(
+ struct PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+void LinuxMMapPerProcessDisconnect(
+ struct PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
+
+enum PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(
+ struct PVRSRV_HANDLE_BASE *psHandleBase);
+
+#endif
diff --git a/drivers/gpu/pvr/event.c b/drivers/gpu/pvr/event.c
new file mode 100644
index 00000000000..5ce55aa025b
--- /dev/null
+++ b/drivers/gpu/pvr/event.c
@@ -0,0 +1,274 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "event.h"
+#include "pvr_bridge_km.h"
+
+struct PVRSRV_LINUX_EVENT_OBJECT_LIST {
+ rwlock_t sLock;
+ struct list_head sList;
+
+};
+
+struct PVRSRV_LINUX_EVENT_OBJECT {
+ atomic_t sTimeStamp;
+ u32 ui32TimeStampPrevious;
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ unsigned ui32Stats;
+#endif
+ wait_queue_head_t sWait;
+ struct list_head sList;
+ void *hResItem;
+ struct PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
+};
+
+enum PVRSRV_ERROR LinuxEventObjectListCreate(void **phEventObjectList)
+{
+ struct PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList;
+
+ if (OSAllocMem
+ (PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_LINUX_EVENT_OBJECT_LIST),
+ (void **) &psEvenObjectList, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "LinuxEventObjectCreate: "
+ "failed to allocate memory for event list");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psEvenObjectList->sList);
+
+ rwlock_init(&psEvenObjectList->sLock);
+
+ *phEventObjectList = (void **) psEvenObjectList;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR LinuxEventObjectListDestroy(void *hEventObjectList)
+{
+ struct PVRSRV_LINUX_EVENT_OBJECT_LIST *psEvenObjectList =
+ (struct PVRSRV_LINUX_EVENT_OBJECT_LIST *)hEventObjectList;
+
+ if (psEvenObjectList) {
+ if (!list_empty(&psEvenObjectList->sList)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "LinuxEventObjectListDestroy: Event List is not empty");
+ return PVRSRV_ERROR_GENERIC;
+ }
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_LINUX_EVENT_OBJECT_LIST),
+ psEvenObjectList, NULL);
+ }
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR LinuxEventObjectDelete(void *hOSEventObjectList,
+ void *hOSEventObject)
+{
+ if (hOSEventObjectList)
+ if (hOSEventObject) {
+ struct PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject =
+ (struct PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "LinuxEventObjectListDelete: Event object waits: %lu",
+ psLinuxEventObject->ui32Stats);
+#endif
+ ResManFreeResByPtr(psLinuxEventObject->hResItem);
+
+ return PVRSRV_OK;
+ }
+ return PVRSRV_ERROR_GENERIC;
+
+}
+
+static enum PVRSRV_ERROR LinuxEventObjectDeleteCallback(void *pvParam,
+ u32 ui32Param)
+{
+ struct PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
+ struct PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList =
+ psLinuxEventObject->psLinuxEventObjectList;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_del(&psLinuxEventObject->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "LinuxEventObjectDeleteCallback: Event object waits: %lu",
+ psLinuxEventObject->ui32Stats);
+#endif
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject,
+ NULL);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR LinuxEventObjectAdd(void *hOSEventObjectList,
+ void **phOSEventObject)
+{
+ struct PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ struct PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList =
+ (struct PVRSRV_LINUX_EVENT_OBJECT_LIST *)hOSEventObjectList;
+ u32 ui32PID = OSGetCurrentProcessIDKM();
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if (psPerProc == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "LinuxEventObjectAdd: Couldn't find per-process data");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_LINUX_EVENT_OBJECT),
+ (void **) &psLinuxEventObject, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "LinuxEventObjectAdd: failed to allocate memory ");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ INIT_LIST_HEAD(&psLinuxEventObject->sList);
+
+ atomic_set(&psLinuxEventObject->sTimeStamp, 0);
+ psLinuxEventObject->ui32TimeStampPrevious = 0;
+
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ psLinuxEventObject->ui32Stats = 0;
+#endif
+ init_waitqueue_head(&psLinuxEventObject->sWait);
+
+ psLinuxEventObject->psLinuxEventObjectList = psLinuxEventObjectList;
+
+ psLinuxEventObject->hResItem =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_EVENT_OBJECT, psLinuxEventObject, 0,
+ &LinuxEventObjectDeleteCallback);
+
+ write_lock_bh(&psLinuxEventObjectList->sLock);
+ list_add(&psLinuxEventObject->sList, &psLinuxEventObjectList->sList);
+ write_unlock_bh(&psLinuxEventObjectList->sLock);
+
+ *phOSEventObject = psLinuxEventObject;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR LinuxEventObjectSignal(void *hOSEventObjectList)
+{
+ struct PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
+ struct PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList =
+ (struct PVRSRV_LINUX_EVENT_OBJECT_LIST *)hOSEventObjectList;
+ struct list_head *psListEntry, *psListEntryTemp, *psList;
+ psList = &psLinuxEventObjectList->sList;
+
+ list_for_each_safe(psListEntry, psListEntryTemp, psList) {
+
+ psLinuxEventObject =
+ (struct PVRSRV_LINUX_EVENT_OBJECT *)list_entry(psListEntry,
+ struct PVRSRV_LINUX_EVENT_OBJECT,
+ sList);
+
+ atomic_inc(&psLinuxEventObject->sTimeStamp);
+ wake_up_interruptible(&psLinuxEventObject->sWait);
+ }
+
+ return PVRSRV_OK;
+
+}
+
+enum PVRSRV_ERROR LinuxEventObjectWait(void *hOSEventObject, u32 ui32MSTimeout)
+{
+ u32 ui32TimeStamp;
+ DEFINE_WAIT(sWait);
+
+ struct PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject =
+ (struct PVRSRV_LINUX_EVENT_OBJECT *)hOSEventObject;
+
+ u32 ui32TimeOutJiffies = msecs_to_jiffies(ui32MSTimeout);
+
+ do {
+ prepare_to_wait(&psLinuxEventObject->sWait, &sWait,
+ TASK_INTERRUPTIBLE);
+ ui32TimeStamp = atomic_read(&psLinuxEventObject->sTimeStamp);
+
+ if (psLinuxEventObject->ui32TimeStampPrevious != ui32TimeStamp)
+ break;
+
+ pvr_unlock();
+
+ ui32TimeOutJiffies =
+ (u32) schedule_timeout((s32) ui32TimeOutJiffies);
+
+ pvr_lock();
+
+ if (pvr_is_disabled()) {
+ ui32TimeOutJiffies = 1;
+ break;
+ }
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ psLinuxEventObject->ui32Stats++;
+#endif
+
+ } while (ui32TimeOutJiffies);
+
+ finish_wait(&psLinuxEventObject->sWait, &sWait);
+
+ psLinuxEventObject->ui32TimeStampPrevious = ui32TimeStamp;
+
+ return ui32TimeOutJiffies ? PVRSRV_OK : PVRSRV_ERROR_TIMEOUT;
+
+}
diff --git a/drivers/gpu/pvr/event.h b/drivers/gpu/pvr/event.h
new file mode 100644
index 00000000000..54de8089191
--- /dev/null
+++ b/drivers/gpu/pvr/event.h
@@ -0,0 +1,35 @@
+/**********************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
+
+enum PVRSRV_ERROR LinuxEventObjectListCreate(void **phEventObjectList);
+enum PVRSRV_ERROR LinuxEventObjectListDestroy(void *hEventObjectList);
+enum PVRSRV_ERROR LinuxEventObjectAdd(void *hOSEventObjectList,
+ void **phOSEventObject);
+enum PVRSRV_ERROR LinuxEventObjectDelete(void *hOSEventObjectList,
+ void *hOSEventObject);
+enum PVRSRV_ERROR LinuxEventObjectSignal(void *hOSEventObjectList);
+enum PVRSRV_ERROR LinuxEventObjectWait(void *hOSEventObject, u32 ui32MSTimeout);
+
diff --git a/drivers/gpu/pvr/handle.c b/drivers/gpu/pvr/handle.c
new file mode 100644
index 00000000000..f1c8f83bc5e
--- /dev/null
+++ b/drivers/gpu/pvr/handle.c
@@ -0,0 +1,1442 @@
+/**********************************************************************
+ *
+ * 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 "handle.h"
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+#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) \
+ ((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) ((IMG_BOOL)(((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 {
+ enum PVRSRV_HANDLE_TYPE eType;
+ void *pvData;
+ u32 ui32NextIndexPlusOne;
+ enum ePVRSRVInternalHandleFlag eInternalFlag;
+ enum PVRSRV_HANDLE_ALLOC_FLAG eFlag;
+
+ u32 ui32Index;
+ struct sHandleList sChildren;
+ struct sHandleList sSiblings;
+};
+
+struct PVRSRV_HANDLE_BASE {
+ void *hBaseBlockAlloc;
+
+ void *hHandBlockAlloc;
+
+ struct sHandle *psHandleArray;
+ struct HASH_TABLE *psHashTab;
+ u32 ui32FreeHandCount;
+ u32 ui32FirstFreeIndex;
+
+ u32 ui32MaxIndexPlusOne;
+
+ u32 ui32TotalHandCount;
+ u32 ui32LastFreeIndexPlusOne;
+ u32 ui32HandBatchSize;
+ u32 ui32TotalHandCountPreBatch;
+ u32 ui32FirstBatchIndexPlusOne;
+ u32 ui32BatchHandAllocFailures;
+
+ IMG_BOOL bPurgingEnabled;
+};
+
+enum eHandKey {
+ HAND_KEY_DATA = 0,
+ HAND_KEY_TYPE,
+ HAND_KEY_PARENT,
+ HAND_KEY_LEN
+};
+
+struct PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+static inline void HandleListInit(u32 ui32Index, struct sHandleList *psList,
+ void *hParent)
+{
+ psList->ui32Next = ui32Index;
+ psList->ui32Prev = ui32Index;
+ psList->hParent = hParent;
+}
+
+static inline void InitParentList(struct 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 inline void InitChildEntry(struct PVRSRV_HANDLE_BASE *psBase,
+ struct sHandle *psHandle)
+{
+ HandleListInit(HANDLE_PTR_TO_INDEX(psBase, psHandle),
+ &psHandle->sSiblings, NULL);
+}
+
+static inline IMG_BOOL HandleListIsEmpty(u32 ui32Index,
+ struct sHandleList *psList)
+{
+ IMG_BOOL bIsEmpty;
+
+ bIsEmpty = (IMG_BOOL) (psList->ui32Next == ui32Index);
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+ {
+ IMG_BOOL bIsEmpty2;
+
+ bIsEmpty2 = (IMG_BOOL) (psList->ui32Prev == ui32Index);
+ PVR_ASSERT(bIsEmpty == bIsEmpty2);
+ }
+#endif
+
+ return bIsEmpty;
+}
+
+#ifdef CONFIG_PVR_DEBUG
+static inline IMG_BOOL NoChildren(struct 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 inline IMG_BOOL NoParent(struct PVRSRV_HANDLE_BASE *psBase,
+ struct sHandle *psHandle)
+{
+ if (HandleListIsEmpty
+ (HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings)) {
+ PVR_ASSERT(psHandle->sSiblings.hParent == NULL);
+
+ return IMG_TRUE;
+ } else {
+ PVR_ASSERT(psHandle->sSiblings.hParent != NULL);
+ }
+ return IMG_FALSE;
+}
+#endif
+static inline 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 inline void HandleListInsertBefore(struct PVRSRV_HANDLE_BASE *psBase,
+ u32 ui32InsIndex, struct sHandleList *psIns,
+ size_t uiParentOffset, u32 ui32EntryIndex,
+ struct sHandleList *psEntry,
+ size_t 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 inline void AdoptChild(struct PVRSRV_HANDLE_BASE *psBase,
+ struct sHandle *psParent, struct sHandle *psChild)
+{
+ u32 ui32Parent =
+ HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent);
+
+ PVR_ASSERT(ui32Parent ==
+ (u32) 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 inline void HandleListRemove(struct PVRSRV_HANDLE_BASE *psBase,
+ u32 ui32EntryIndex, struct sHandleList *psEntry,
+ size_t uiEntryOffset, size_t 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 inline void UnlinkFromParent(struct 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 inline enum PVRSRV_ERROR HandleListIterate(
+ struct PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead,
+ size_t uiParentOffset, size_t uiEntryOffset,
+ enum PVRSRV_ERROR(*pfnIterFunc)(struct 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);
+ enum 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 inline enum PVRSRV_ERROR IterateOverChildren(
+ struct PVRSRV_HANDLE_BASE *psBase,
+ struct sHandle *psParent,
+ enum PVRSRV_ERROR(*pfnIterFunc)
+ (struct PVRSRV_HANDLE_BASE *, struct sHandle *))
+{
+ return HandleListIterate(psBase, &psParent->sChildren,
+ offsetof(struct sHandle, sChildren),
+ offsetof(struct sHandle, sSiblings),
+ pfnIterFunc);
+}
+
+static inline enum PVRSRV_ERROR GetHandleStructure(
+ struct PVRSRV_HANDLE_BASE *psBase,
+ struct sHandle **ppsHandle, void *hHandle,
+ enum 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 inline void *ParentIfPrivate(struct sHandle *psHandle)
+{
+ return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
+ ParentHandle(psHandle) : NULL;
+}
+
+static inline void InitKey(u32 aKey[HAND_KEY_LEN],
+ struct PVRSRV_HANDLE_BASE *psBase,
+ void *pvData, enum PVRSRV_HANDLE_TYPE eType,
+ void *hParent)
+{
+ PVR_UNREFERENCED_PARAMETER(psBase);
+
+ aKey[HAND_KEY_DATA] = (u32) pvData;
+ aKey[HAND_KEY_TYPE] = (u32) eType;
+ aKey[HAND_KEY_PARENT] = (u32) hParent;
+}
+
+static void FreeHandleArray(struct PVRSRV_HANDLE_BASE *psBase)
+{
+ if (psBase->psHandleArray != NULL) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psBase->ui32TotalHandCount *
+ sizeof(struct sHandle),
+ psBase->psHandleArray,
+ psBase->hHandBlockAlloc);
+ psBase->psHandleArray = NULL;
+ }
+}
+
+static enum PVRSRV_ERROR FreeHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ struct sHandle *psHandle)
+{
+ u32 aKey[HAND_KEY_LEN];
+ u32 ui32Index = HANDLE_PTR_TO_INDEX(psBase, psHandle);
+ enum 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));
+ PVR_UNREFERENCED_PARAMETER(hHandle);
+ }
+
+ 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 enum PVRSRV_ERROR FreeAllHandles(struct PVRSRV_HANDLE_BASE *psBase)
+{
+ u32 i;
+ enum 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 enum PVRSRV_ERROR FreeHandleBase(struct PVRSRV_HANDLE_BASE *psBase)
+{
+ enum 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;
+ }
+
+ FreeHandleArray(psBase);
+
+ if (psBase->psHashTab != NULL)
+ HASH_Delete(psBase->psHashTab);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBase), psBase,
+ psBase->hBaseBlockAlloc);
+
+ return PVRSRV_OK;
+}
+
+static inline void *FindHandle(struct PVRSRV_HANDLE_BASE *psBase, void *pvData,
+ enum PVRSRV_HANDLE_TYPE eType, void *hParent)
+{
+ u32 aKey[HAND_KEY_LEN];
+
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+
+ InitKey(aKey, psBase, pvData, eType, hParent);
+
+ return (void *)HASH_Retrieve_Extended(psBase->psHashTab, aKey);
+}
+
+static enum 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;
+ enum PVRSRV_ERROR eError;
+
+ if (ui32NewSize == ui32OldSize)
+ return PVRSRV_OK;
+
+ if (ui32NewSize != 0) {
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32NewSize, &pvNewMem, &hNewBlockAlloc);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "ReallocMem: Couldn't allocate new memory area (%d)",
+ eError);
+ return eError;
+ }
+ if (ui32OldSize != 0)
+ OSMemCopy(pvNewMem, pvOldMem, ui32CopySize);
+ }
+
+ if (ui32OldSize != 0)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32OldSize, pvOldMem,
+ hOldBlockAlloc);
+
+ *ppvMem = pvNewMem;
+ *phBlockAlloc = hNewBlockAlloc;
+
+ return PVRSRV_OK;
+}
+
+static inline enum PVRSRV_ERROR ReallocHandleArray(struct PVRSRV_HANDLE_BASE
+ *psBase, u32 ui32NewCount,
+ u32 ui32OldCount)
+{
+ return ReallocMem((void **)&psBase->psHandleArray,
+ &psBase->hHandBlockAlloc,
+ ui32NewCount * sizeof(struct sHandle),
+ ui32OldCount * sizeof(struct sHandle));
+}
+
+static enum PVRSRV_ERROR IncreaseHandleArraySize(struct PVRSRV_HANDLE_BASE
+ *psBase, u32 ui32Delta)
+{
+ enum 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 enum PVRSRV_ERROR EnsureFreeHandles(struct PVRSRV_HANDLE_BASE *psBase,
+ u32 ui32Free)
+{
+ enum 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 enum PVRSRV_ERROR AllocHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phHandle, void *pvData,
+ enum PVRSRV_HANDLE_TYPE eType,
+ enum PVRSRV_HANDLE_ALLOC_FLAG eFlag,
+ void *hParent)
+{
+ u32 ui32NewIndex;
+ struct sHandle *psNewHandle = NULL;
+ void *hHandle;
+ u32 aKey[HAND_KEY_LEN];
+ enum 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);
+
+ 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);
+ PVR_ASSERT(NoChildren(psBase, psNewHandle));
+
+ InitChildEntry(psBase, psNewHandle);
+ PVR_ASSERT(NoParent(psBase, psNewHandle));
+
+ 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;
+}
+
+enum PVRSRV_ERROR PVRSRVAllocHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phHandle, void *pvData,
+ enum PVRSRV_HANDLE_TYPE eType,
+ enum PVRSRV_HANDLE_ALLOC_FLAG eFlag)
+{
+ void *hHandle;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVAllocSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phHandle, void *pvData,
+ enum PVRSRV_HANDLE_TYPE eType,
+ enum PVRSRV_HANDLE_ALLOC_FLAG eFlag,
+ void *hParent)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ enum 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;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVFindHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phHandle, void *pvData,
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVLookupHandleAnyType(struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData,
+ enum PVRSRV_HANDLE_TYPE *peType,
+ void *hHandle)
+{
+ struct sHandle *psHandle;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVLookupHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVLookupSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType,
+ void *hAncestor)
+{
+ struct sHandle *psPHand;
+ struct sHandle *psCHand;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVGetParentHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phParent, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(
+ struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVReleaseHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void *hHandle, enum PVRSRV_HANDLE_TYPE eType)
+{
+ struct sHandle *psHandle;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVNewHandleBatch(struct PVRSRV_HANDLE_BASE *psBase,
+ u32 ui32BatchSize)
+{
+ enum 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 enum PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(
+ struct PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
+{
+ u32 ui32IndexPlusOne;
+ IMG_BOOL 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 = IMG_FALSE;
+ }
+
+ 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)) {
+ enum 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 CONFIG_PVR_DEBUG_EXTRA
+ 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;
+}
+
+enum PVRSRV_ERROR PVRSRVCommitHandleBatch(struct PVRSRV_HANDLE_BASE *psBase)
+{
+ return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
+}
+
+void PVRSRVReleaseHandleBatch(struct PVRSRV_HANDLE_BASE *psBase)
+{
+ (void)PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
+}
+
+enum PVRSRV_ERROR PVRSRVSetMaxHandle(struct 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(struct PVRSRV_HANDLE_BASE *psBase)
+{
+ return psBase->ui32MaxIndexPlusOne;
+}
+
+enum PVRSRV_ERROR PVRSRVEnableHandlePurging(struct 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 = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVPurgeHandles(struct 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;
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVAllocHandleBase(struct PVRSRV_HANDLE_BASE **ppsBase)
+{
+ struct PVRSRV_HANDLE_BASE *psBase;
+ void *hBlockAlloc;
+ enum PVRSRV_ERROR eError;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*psBase), (void **)&psBase, &hBlockAlloc);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocHandleBase: "
+ "Couldn't allocate handle base (%d)",
+ eError);
+ return eError;
+ }
+ OSMemSet(psBase, 0, sizeof(*psBase));
+
+ psBase->psHashTab =
+ HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE,
+ HAND_KEY_LEN * sizeof(u32),
+ 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;
+}
+
+enum PVRSRV_ERROR PVRSRVFreeHandleBase(struct PVRSRV_HANDLE_BASE *psBase)
+{
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVHandleInit(void)
+{
+ enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVHandleDeInit(void)
+{
+ enum 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;
+}
diff --git a/drivers/gpu/pvr/handle.h b/drivers/gpu/pvr/handle.h
new file mode 100644
index 00000000000..668e5d8ceb1
--- /dev/null
+++ b/drivers/gpu/pvr/handle.h
@@ -0,0 +1,150 @@
+/**********************************************************************
+ *
+ * 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 __HANDLE_H__
+#define __HANDLE_H__
+
+#include "img_types.h"
+#include "hash.h"
+#include "resman.h"
+
+enum PVRSRV_HANDLE_TYPE {
+ PVRSRV_HANDLE_TYPE_NONE = 0,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA,
+ PVRSRV_HANDLE_TYPE_DEV_NODE,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_HEAP,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ PVRSRV_HANDLE_TYPE_BUF_INFO,
+ PVRSRV_HANDLE_TYPE_DISP_BUFFER,
+ PVRSRV_HANDLE_TYPE_BUF_BUFFER,
+ PVRSRV_HANDLE_TYPE_SGX_HW_RENDER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_TRANSFER_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SGX_HW_2D_CONTEXT,
+ PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
+ PVRSRV_HANDLE_TYPE_MEM_INFO_REF,
+ PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO,
+ PVRSRV_HANDLE_TYPE_SHARED_EVENT_OBJECT,
+ PVRSRV_HANDLE_TYPE_EVENT_OBJECT_CONNECT,
+ PVRSRV_HANDLE_TYPE_MMAP_INFO,
+ PVRSRV_HANDLE_TYPE_SOC_TIMER
+};
+
+enum PVRSRV_HANDLE_ALLOC_FLAG {
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 0x01,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 0x02,
+
+ PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 0x04
+};
+
+struct PVRSRV_HANDLE_BASE;
+struct PVRSRV_HANDLE_BASE;
+
+extern struct PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
+
+#define KERNEL_HANDLE_BASE (gpsKernelHandleBase)
+
+enum PVRSRV_ERROR PVRSRVAllocHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phHandle, void *pvData,
+ enum PVRSRV_HANDLE_TYPE eType,
+ enum PVRSRV_HANDLE_ALLOC_FLAG eFlag);
+
+enum PVRSRV_ERROR PVRSRVAllocSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phHandle,
+ void *pvData,
+ enum PVRSRV_HANDLE_TYPE eType,
+ enum PVRSRV_HANDLE_ALLOC_FLAG eFlag,
+ void *hParent);
+
+enum PVRSRV_ERROR PVRSRVFindHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phHandle, void *pvData,
+ enum PVRSRV_HANDLE_TYPE eType);
+
+enum PVRSRV_ERROR PVRSRVLookupHandleAnyType(struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData,
+ enum PVRSRV_HANDLE_TYPE *peType,
+ void *hHandle);
+
+enum PVRSRV_ERROR PVRSRVLookupHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType);
+
+enum PVRSRV_ERROR PVRSRVLookupSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType, void *hAncestor);
+
+enum PVRSRV_ERROR PVRSRVGetParentHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void **phParent, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType);
+
+enum PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(
+ struct PVRSRV_HANDLE_BASE *psBase,
+ void **ppvData, void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType);
+
+enum PVRSRV_ERROR PVRSRVReleaseHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ void *hHandle,
+ enum PVRSRV_HANDLE_TYPE eType);
+
+enum PVRSRV_ERROR PVRSRVNewHandleBatch(struct PVRSRV_HANDLE_BASE *psBase,
+ u32 ui32BatchSize);
+
+enum PVRSRV_ERROR PVRSRVCommitHandleBatch(struct PVRSRV_HANDLE_BASE *psBase);
+
+void PVRSRVReleaseHandleBatch(struct PVRSRV_HANDLE_BASE *psBase);
+
+enum PVRSRV_ERROR PVRSRVSetMaxHandle(struct PVRSRV_HANDLE_BASE *psBase,
+ u32 ui32MaxHandle);
+
+u32 PVRSRVGetMaxHandle(struct PVRSRV_HANDLE_BASE *psBase);
+
+enum PVRSRV_ERROR PVRSRVEnableHandlePurging(struct PVRSRV_HANDLE_BASE *psBase);
+
+enum PVRSRV_ERROR PVRSRVPurgeHandles(struct PVRSRV_HANDLE_BASE *psBase);
+
+enum PVRSRV_ERROR PVRSRVAllocHandleBase(struct PVRSRV_HANDLE_BASE **ppsBase);
+
+enum PVRSRV_ERROR PVRSRVFreeHandleBase(struct PVRSRV_HANDLE_BASE *psBase);
+
+enum PVRSRV_ERROR PVRSRVHandleInit(void);
+
+enum PVRSRV_ERROR PVRSRVHandleDeInit(void);
+
+
+#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
+ (void)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
+
+#define PVRSRVAllocSubHandleNR(psBase, phHandle, pvData, eType, eFlag, hParent)\
+ (void)PVRSRVAllocSubHandle(psBase, phHandle, pvData, eType, \
+ eFlag, hParent)
+
+#endif
diff --git a/drivers/gpu/pvr/hash.c b/drivers/gpu/pvr/hash.c
new file mode 100644
index 00000000000..56eacb7e107
--- /dev/null
+++ b/drivers/gpu/pvr/hash.c
@@ -0,0 +1,379 @@
+/**********************************************************************
+ *
+ * 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[];
+};
+struct BUCKET;
+
+struct HASH_TABLE {
+ struct BUCKET **ppBucketTable;
+ u32 uSize;
+ u32 uCount;
+ u32 uMinimumSize;
+ u32 uKeySize;
+ u32 (*pfnHashFunc)(size_t uKeySize, void *pkey, u32 uHashTabLen);
+ IMG_BOOL (*pfnKeyComp)(size_t uKeySize, void *pKey1, void *pkey2);
+};
+
+u32 HASH_Func_Default(size_t uKeySize, void *pKey, u32 uHashTabLen)
+{
+ u32 *p = (u32 *) pKey;
+ u32 uKeyLen = uKeySize / sizeof(u32);
+ u32 ui;
+ u32 uHashKey = 0;
+
+ PVR_UNREFERENCED_PARAMETER(uHashTabLen);
+
+ 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;
+}
+
+IMG_BOOL HASH_Key_Comp_Default(size_t 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 IMG_FALSE;
+
+ return IMG_TRUE;
+}
+
+static enum PVRSRV_ERROR _ChainInsert(struct HASH_TABLE *pHash,
+ struct BUCKET *pBucket,
+ struct 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 enum PVRSRV_ERROR _Rehash(struct HASH_TABLE *pHash,
+ struct BUCKET **ppOldTable, u32 uOldSize,
+ struct BUCKET **ppNewTable, u32 uNewSize)
+{
+ u32 uIndex;
+ for (uIndex = 0; uIndex < uOldSize; uIndex++) {
+ struct BUCKET *pBucket;
+ pBucket = ppOldTable[uIndex];
+ while (pBucket != NULL) {
+ struct 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 IMG_BOOL _Resize(struct HASH_TABLE *pHash, u32 uNewSize)
+{
+ if (uNewSize != pHash->uSize) {
+ struct 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);
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct BUCKET *) * uNewSize,
+ (void **) &ppNewTable, NULL) != PVRSRV_OK)
+ return IMG_FALSE;
+
+ for (uIndex = 0; uIndex < uNewSize; uIndex++)
+ ppNewTable[uIndex] = NULL;
+
+ if (_Rehash(pHash, pHash->ppBucketTable, pHash->uSize,
+ ppNewTable, uNewSize) != PVRSRV_OK)
+ return IMG_FALSE;
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct BUCKET *) * pHash->uSize,
+ pHash->ppBucketTable, NULL);
+ pHash->ppBucketTable = ppNewTable;
+ pHash->uSize = uNewSize;
+ }
+ return IMG_TRUE;
+}
+
+struct HASH_TABLE *HASH_Create_Extended(u32 uInitialLen, size_t uKeySize,
+ u32 (*pfnHashFunc)(size_t uKeySize, void *pkey,
+ u32 uHashTabLen),
+ IMG_BOOL (*pfnKeyComp)(size_t uKeySize,
+ void *pKey1,
+ void *pkey2))
+{
+ struct HASH_TABLE *pHash;
+ u32 uIndex;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "HASH_Create_Extended: InitialSize=0x%x",
+ uInitialLen);
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct HASH_TABLE),
+ (void **) &pHash, NULL) != PVRSRV_OK)
+ return NULL;
+
+ pHash->uCount = 0;
+ pHash->uSize = uInitialLen;
+ pHash->uMinimumSize = uInitialLen;
+ pHash->uKeySize = uKeySize;
+ pHash->pfnHashFunc = pfnHashFunc;
+ pHash->pfnKeyComp = pfnKeyComp;
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct BUCKET *) * pHash->uSize,
+ (void **) &pHash->ppBucketTable, NULL) != PVRSRV_OK) {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct HASH_TABLE),
+ pHash, NULL);
+ return NULL;
+ }
+
+ for (uIndex = 0; uIndex < pHash->uSize; uIndex++)
+ pHash->ppBucketTable[uIndex] = NULL;
+ return pHash;
+}
+
+struct HASH_TABLE *HASH_Create(u32 uInitialLen)
+{
+ return HASH_Create_Extended(uInitialLen, sizeof(u32),
+ &HASH_Func_Default, &HASH_Key_Comp_Default);
+}
+
+void HASH_Delete(struct HASH_TABLE *pHash)
+{
+ if (pHash != NULL) {
+ PVR_DPF(PVR_DBG_MESSAGE, "HASH_Delete");
+
+ PVR_ASSERT(pHash->uCount == 0);
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct BUCKET *) * pHash->uSize,
+ pHash->ppBucketTable, NULL);
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(struct HASH_TABLE),
+ pHash, NULL);
+ }
+}
+
+IMG_BOOL HASH_Insert_Extended(struct HASH_TABLE *pHash, void *pKey, u32 v)
+{
+ struct 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 IMG_FALSE;
+ }
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct BUCKET) + pHash->uKeySize,
+ (void **) &pBucket, NULL) != PVRSRV_OK)
+ return IMG_FALSE;
+
+ pBucket->v = v;
+ OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
+ if (_ChainInsert(pHash, pBucket, pHash->ppBucketTable, pHash->uSize) !=
+ PVRSRV_OK) {
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct BUCKET) + pHash->uKeySize,
+ pBucket, NULL);
+ return IMG_FALSE;
+ }
+
+ pHash->uCount++;
+
+ if (pHash->uCount << 1 > pHash->uSize)
+ _Resize(pHash, pHash->uSize << 1);
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL HASH_Insert(struct 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(struct HASH_TABLE *pHash, void *pKey)
+{
+ struct BUCKET **ppBucket;
+ u32 uIndex;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "HASH_Remove: Hash=%08X, pKey=%08X", pHash,
+ pKey);
+
+ PVR_ASSERT(pHash != NULL);
+
+ if (pHash == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "FreeResourceByPtr: invalid parameter");
+ 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)) {
+ struct BUCKET *pBucket = *ppBucket;
+ u32 v = pBucket->v;
+ (*ppBucket) = pBucket->pNext;
+
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct 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(struct 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(struct HASH_TABLE *pHash, void *pKey)
+{
+ struct BUCKET **ppBucket;
+ u32 uIndex;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "HASH_Retrieve: Hash=%08X, pKey=%08X", pHash,
+ pKey);
+
+ PVR_ASSERT(pHash != NULL);
+
+ if (pHash == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "HASH_Retrieve_Extended: invalid parameter");
+ 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)) {
+ struct 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(struct 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);
+}
+
diff --git a/drivers/gpu/pvr/hash.h b/drivers/gpu/pvr/hash.h
new file mode 100644
index 00000000000..d0319ad89e1
--- /dev/null
+++ b/drivers/gpu/pvr/hash.h
@@ -0,0 +1,51 @@
+/**********************************************************************
+ *
+ * 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 _HASH_H_
+#define _HASH_H_
+
+#include "img_types.h"
+#include "osfunc.h"
+
+struct HASH_TABLE;
+u32 HASH_Func_Default(size_t uKeySize, void *pKey, u32 uHashTabLen);
+IMG_BOOL HASH_Key_Comp_Default(size_t uKeySize, void *pKey1, void *pKey2);
+struct HASH_TABLE *HASH_Create_Extended(u32 uInitialLen, size_t uKeySize,
+ u32 (*pfnHashFunc)(size_t uKeySize, void *pkey,
+ u32 uHashTabLen),
+ IMG_BOOL (*pfnKeyComp)(size_t uKeySize,
+ void *pKey1,
+ void *pkey2));
+struct HASH_TABLE *HASH_Create(u32 uInitialLen);
+void HASH_Delete(struct HASH_TABLE *pHash);
+IMG_BOOL HASH_Insert_Extended(struct HASH_TABLE *pHash, void *pKey, u32 v);
+IMG_BOOL HASH_Insert(struct HASH_TABLE *pHash, u32 k, u32 v);
+u32 HASH_Remove_Extended(struct HASH_TABLE *pHash, void *pKey);
+u32 HASH_Remove(struct HASH_TABLE *pHash, u32 k);
+u32 HASH_Retrieve_Extended(struct HASH_TABLE *pHash, void *pKey);
+u32 HASH_Retrieve(struct HASH_TABLE *pHash, u32 k);
+
+#endif
diff --git a/drivers/gpu/pvr/img_defs.h b/drivers/gpu/pvr/img_defs.h
new file mode 100644
index 00000000000..b0a25c2223f
--- /dev/null
+++ b/drivers/gpu/pvr/img_defs.h
@@ -0,0 +1,46 @@
+/**********************************************************************
+ *
+ * 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(__IMG_DEFS_H__)
+#define __IMG_DEFS_H__
+
+#include "img_types.h"
+
+#define IMG_SUCCESS 0
+
+#define IMG_NO_REG 1
+
+#ifndef PVR_UNREFERENCED_PARAMETER
+#define PVR_UNREFERENCED_PARAMETER(param) (param) = (param)
+#endif
+
+#ifdef __GNUC__
+#define unref__ __attribute__ ((unused))
+#else
+#define unref__
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/img_types.h b/drivers/gpu/pvr/img_types.h
new file mode 100644
index 00000000000..c52ba6ce952
--- /dev/null
+++ b/drivers/gpu/pvr/img_types.h
@@ -0,0 +1,69 @@
+/**********************************************************************
+ *
+ * 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 __IMG_TYPES_H__
+#define __IMG_TYPES_H__
+
+#include <linux/types.h>
+
+#if !defined(IMG_UINT32_MAX)
+#define IMG_UINT32_MAX 0xFFFFFFFFUL
+#endif
+
+typedef enum tag_img_bool {
+ IMG_FALSE = 0,
+ IMG_TRUE = 1,
+ IMG_FORCE_ALIGN = 0x7FFFFFFF
+} IMG_BOOL, *IMG_PBOOL;
+
+struct IMG_CPU_PHYADDR {
+ u32 uiAddr;
+};
+
+struct IMG_DEV_VIRTADDR {
+ u32 uiAddr;
+};
+
+struct IMG_DEV_PHYADDR {
+ u32 uiAddr;
+};
+
+struct IMG_SYS_PHYADDR {
+ u32 uiAddr;
+};
+
+struct SYSTEM_ADDR {
+
+ u32 ui32PageCount;
+ union {
+ struct IMG_SYS_PHYADDR sContig;
+ struct IMG_SYS_PHYADDR asNonContig[1];
+ } u;
+};
+
+#include "img_defs.h"
+
+#endif
diff --git a/drivers/gpu/pvr/ioctldef.h b/drivers/gpu/pvr/ioctldef.h
new file mode 100644
index 00000000000..36a16846781
--- /dev/null
+++ b/drivers/gpu/pvr/ioctldef.h
@@ -0,0 +1,93 @@
+/**********************************************************************
+ *
+ * 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 __IOCTLDEF_H__
+#define __IOCTLDEF_H__
+
+#define MAKEIOCTLINDEX(i) (((i) >> 2) & 0xFFF)
+
+#define DEVICE_TYPE ULONG
+
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+
+#define CTL_CODE( DeviceType, Function, Method, Access) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS 0x0001
+#define FILE_WRITE_ACCESS 0x0002
+
+#endif
diff --git a/drivers/gpu/pvr/kernelbuffer.h b/drivers/gpu/pvr/kernelbuffer.h
new file mode 100644
index 00000000000..da69d7e5c87
--- /dev/null
+++ b/drivers/gpu/pvr/kernelbuffer.h
@@ -0,0 +1,55 @@
+/**********************************************************************
+ *
+ * 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(__KERNELBUFFER_H__)
+#define __KERNELBUFFER_H__
+
+#include "servicesext.h"
+
+struct PVRSRV_BC_SRV2BUFFER_KMJTABLE {
+ u32 ui32TableSize;
+ enum PVRSRV_ERROR (*pfnOpenBCDevice)(void **);
+ enum PVRSRV_ERROR (*pfnCloseBCDevice)(void *);
+ enum PVRSRV_ERROR (*pfnGetBCInfo)(void *, struct BUFFER_INFO *);
+ enum PVRSRV_ERROR (*pfnGetBCBuffer)(void *, u32,
+ struct PVRSRV_SYNC_DATA *, void **);
+ enum PVRSRV_ERROR (*pfnGetBufferAddr)(void *, void *,
+ struct IMG_SYS_PHYADDR **, u32 *,
+ void __iomem **, void **, IMG_BOOL *);
+};
+
+struct PVRSRV_BC_BUFFER2SRV_KMJTABLE {
+ u32 ui32TableSize;
+ enum PVRSRV_ERROR (*pfnPVRSRVRegisterBCDevice)(
+ struct PVRSRV_BC_SRV2BUFFER_KMJTABLE *, u32 *);
+ enum PVRSRV_ERROR (*pfnPVRSRVRemoveBCDevice)(u32);
+};
+
+IMG_BOOL PVRGetBufferClassJTable(
+ struct PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable);
+
+
+#endif
diff --git a/drivers/gpu/pvr/kerneldisplay.h b/drivers/gpu/pvr/kerneldisplay.h
new file mode 100644
index 00000000000..c601906ab14
--- /dev/null
+++ b/drivers/gpu/pvr/kerneldisplay.h
@@ -0,0 +1,104 @@
+/**********************************************************************
+ *
+ * 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(__KERNELDISPLAY_H__)
+#define __KERNELDISPLAY_H__
+
+#include <linux/module.h>
+
+#define DC_FLIP_COMMAND 0
+
+#define DC_STATE_NO_FLUSH_COMMANDS 0
+#define DC_STATE_FLUSH_COMMANDS 1
+
+struct PVRSRV_DC_SRV2DISP_KMJTABLE {
+ struct module *owner;
+ u32 ui32TableSize;
+ enum PVRSRV_ERROR (*pfnOpenDCDevice)(u32, void **,
+ struct PVRSRV_SYNC_DATA *);
+ enum PVRSRV_ERROR (*pfnCloseDCDevice)(void *);
+ enum PVRSRV_ERROR (*pfnEnumDCFormats)(void *, u32 *,
+ struct DISPLAY_FORMAT *);
+ enum PVRSRV_ERROR (*pfnEnumDCDims)(void *, struct DISPLAY_FORMAT *,
+ u32 *, struct DISPLAY_DIMS *);
+ enum PVRSRV_ERROR (*pfnGetDCSystemBuffer)(void *, void **);
+ enum PVRSRV_ERROR (*pfnGetDCInfo)(void *, struct DISPLAY_INFO *);
+ enum PVRSRV_ERROR (*pfnGetBufferAddr)(void *, void *,
+ struct IMG_SYS_PHYADDR **, u32 *,
+ void __iomem **, void **, IMG_BOOL *);
+ enum PVRSRV_ERROR (*pfnCreateDCSwapChain)(void *, u32,
+ struct DISPLAY_SURF_ATTRIBUTES *,
+ struct DISPLAY_SURF_ATTRIBUTES *,
+ u32, struct PVRSRV_SYNC_DATA **,
+ u32, void **, u32 *);
+ enum PVRSRV_ERROR (*pfnDestroyDCSwapChain)(void *, void *);
+ enum PVRSRV_ERROR (*pfnSetDCDstRect)(void *, void *, struct IMG_RECT *);
+ enum PVRSRV_ERROR (*pfnSetDCSrcRect)(void *, void *, struct IMG_RECT *);
+ enum PVRSRV_ERROR (*pfnSetDCDstColourKey)(void *, void *, u32);
+ enum PVRSRV_ERROR (*pfnSetDCSrcColourKey)(void *, void *, u32);
+ enum PVRSRV_ERROR (*pfnGetDCBuffers)(void *, void *, u32 *, void **);
+ void (*pfnSetDCState)(void *, u32);
+};
+
+struct PVRSRV_DC_DISP2SRV_KMJTABLE {
+ u32 ui32TableSize;
+ enum PVRSRV_ERROR (*pfnPVRSRVRegisterDCDevice)(
+ struct PVRSRV_DC_SRV2DISP_KMJTABLE*, u32 *);
+ enum PVRSRV_ERROR (*pfnPVRSRVRemoveDCDevice)(u32);
+ enum PVRSRV_ERROR (*pfnPVRSRVOEMFunction)(u32, void *, u32, void *,
+ u32);
+ enum PVRSRV_ERROR (*pfnPVRSRVRegisterCmdProcList)(u32,
+ IMG_BOOL (**)(void *, u32, void *), u32[][2],
+ u32);
+ enum PVRSRV_ERROR (*pfnPVRSRVRemoveCmdProcList)(u32, u32);
+ void (*pfnPVRSRVCmdComplete)(void *, IMG_BOOL);
+ enum PVRSRV_ERROR (*pfnPVRSRVRegisterSystemISRHandler)(
+ IMG_BOOL (*)(void *), void *, u32, u32);
+ enum PVRSRV_ERROR (*pfnPVRSRVRegisterPowerDevice)(u32,
+ enum PVRSRV_ERROR (*)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE),
+ void *, enum PVR_POWER_STATE, enum PVR_POWER_STATE);
+};
+
+struct DISPLAYCLASS_FLIP_COMMAND {
+ void *hExtDevice;
+ void *hExtSwapChain;
+ void *hExtBuffer;
+ void *hPrivateTag;
+ u32 ui32ClipRectCount;
+ struct IMG_RECT *psClipRect;
+ u32 ui32SwapInterval;
+};
+
+IMG_BOOL PVRGetDisplayClassJTable(struct PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable);
+
+#endif
diff --git a/drivers/gpu/pvr/mem.c b/drivers/gpu/pvr/mem.c
new file mode 100644
index 00000000000..6375cad3cf6
--- /dev/null
+++ b/drivers/gpu/pvr/mem.c
@@ -0,0 +1,130 @@
+/**********************************************************************
+ *
+ * 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 "sgxapi_km.h"
+#include "pvr_bridge_km.h"
+
+static enum PVRSRV_ERROR FreeSharedSysMemCallBack(void *pvParam, u32 ui32Param)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ OSFreePages(psKernelMemInfo->ui32Flags,
+ psKernelMemInfo->ui32AllocSize,
+ psKernelMemInfo->pvLinAddrKM,
+ psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO), psKernelMemInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVAllocSharedSysMemoryKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ u32 ui32Flags, u32 ui32Size,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO),
+ (void **) &psKernelMemInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocSharedSysMemoryKM: "
+ "Failed to alloc memory for meminfo");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ OSMemSet(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(struct PVRSRV_KERNEL_MEM_INFO),
+ psKernelMemInfo, NULL);
+ 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;
+}
+
+enum PVRSRV_ERROR PVRSRVFreeSharedSysMemoryKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psKernelMemInfo->sMemBlk.hResItem)
+ ResManFreeResByPtr(psKernelMemInfo->sMemBlk.hResItem);
+ else
+ eError = FreeSharedSysMemCallBack(psKernelMemInfo, 0);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVDissociateMemFromResmanKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ enum 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/gpu/pvr/mm.c b/drivers/gpu/pvr/mm.c
new file mode 100644
index 00000000000..c0a92f26580
--- /dev/null
+++ b/drivers/gpu/pvr/mm.c
@@ -0,0 +1,1499 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "syscommon.h"
+#include "mutils.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "proc.h"
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+enum DEBUG_MEM_ALLOC_TYPE {
+ DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ DEBUG_MEM_ALLOC_TYPE_IO,
+ DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ DEBUG_MEM_ALLOC_TYPE_COUNT
+};
+
+struct DEBUG_MEM_ALLOC_REC {
+ enum DEBUG_MEM_ALLOC_TYPE eAllocType;
+ void *pvKey;
+ void *pvCpuVAddr;
+ u32 ulCpuPAddr;
+ void *pvPrivateData;
+ u32 ui32Bytes;
+ pid_t pid;
+ char *pszFileName;
+ u32 ui32Line;
+
+ struct DEBUG_MEM_ALLOC_REC *psNext;
+};
+
+static struct DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
+
+static u32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+static u32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
+
+static u32 g_SysRAMWaterMark;
+static u32 g_SysRAMHighWaterMark;
+
+static u32 g_IOMemWaterMark;
+static u32 g_IOMemHighWaterMark;
+
+static void DebugMemAllocRecordAdd(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
+ void *pvKey, void *pvCpuVAddr,
+ u32 ulCpuPAddr, void *pvPrivateData,
+ u32 ui32Bytes, char *pszFileName,
+ u32 ui32Line);
+
+static void DebugMemAllocRecordRemove(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
+ void *pvKey, char *pszFileName,
+ u32 ui32Line);
+
+static char *DebugMemAllocRecordTypeToString(
+ enum DEBUG_MEM_ALLOC_TYPE eAllocType);
+
+static off_t printMemoryRecords(char *buffer, size_t size, off_t off);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+struct DEBUG_LINUX_MEM_AREA_REC {
+ struct LinuxMemArea *psLinuxMemArea;
+ u32 ui32Flags;
+ pid_t pid;
+
+ struct DEBUG_LINUX_MEM_AREA_REC *psNext;
+};
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static struct mutex g_sDebugMutex;
+#endif
+
+static struct DEBUG_LINUX_MEM_AREA_REC *g_LinuxMemAreaRecords;
+static u32 g_LinuxMemAreaCount;
+static u32 g_LinuxMemAreaWaterMark;
+static u32 g_LinuxMemAreaHighWaterMark;
+
+static off_t printLinuxMemAreaRecords(char *buffer, size_t size, off_t off);
+#endif
+
+static struct kmem_cache *psLinuxMemAreaCache;
+
+
+static struct LinuxMemArea *LinuxMemAreaStructAlloc(void);
+static void LinuxMemAreaStructFree(struct LinuxMemArea *psLinuxMemArea);
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static void DebugLinuxMemAreaRecordAdd(struct LinuxMemArea *psLinuxMemArea,
+ u32 ui32Flags);
+static struct DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(
+ struct LinuxMemArea *psLinuxMemArea);
+static void DebugLinuxMemAreaRecordRemove(struct LinuxMemArea *psLinuxMemArea);
+#endif
+
+enum PVRSRV_ERROR LinuxMMInit(void)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ mutex_init(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ int iStatus;
+ iStatus =
+ CreateProcReadEntry("mem_areas", printLinuxMemAreaRecords);
+ if (iStatus != 0)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+ int iStatus;
+ iStatus = CreateProcReadEntry("meminfo", printMemoryRecords);
+ if (iStatus != 0)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+#endif
+ psLinuxMemAreaCache =
+ kmem_cache_create("img-mm", sizeof(struct LinuxMemArea), 0, 0,
+ NULL);
+ if (!psLinuxMemAreaCache) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: failed to allocate kmem_cache",
+ __func__);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ return PVRSRV_OK;
+}
+
+void LinuxMMCleanup(void)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ struct DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord =
+ g_LinuxMemAreaRecords, *psNextRecord;
+
+ if (g_LinuxMemAreaCount)
+ PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: "
+ "There are %d struct LinuxMemArea "
+ "allocation unfreed (%ld bytes)",
+ __func__, g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark);
+
+ while (psCurrentRecord) {
+ struct LinuxMemArea *psLinuxMemArea;
+
+ psNextRecord = psCurrentRecord->psNext;
+ psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+ PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: "
+ "Cleaning up Linux memory area (%p), "
+ "type=%s, size=%ld bytes",
+ __func__, psCurrentRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psCurrentRecord->
+ psLinuxMemArea->
+ eAreaType),
+ psCurrentRecord->psLinuxMemArea->
+ ui32ByteSize);
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ psCurrentRecord = psNextRecord;
+ }
+ RemoveProcEntry("mem_areas");
+ }
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+ struct DEBUG_MEM_ALLOC_REC *psCurrentRecord =
+ g_MemoryRecords, *psNextRecord;
+
+ while (psCurrentRecord) {
+ psNextRecord = psCurrentRecord->psNext;
+ PVR_DPF(PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+ "type=%s CpuVAddr=%p CpuPAddr=0x%08lx, "
+ "allocated @ file=%s,line=%d",
+ __func__,
+ DebugMemAllocRecordTypeToString
+ (psCurrentRecord->eAllocType),
+ psCurrentRecord->pvCpuVAddr,
+ psCurrentRecord->ulCpuPAddr,
+ psCurrentRecord->pszFileName,
+ psCurrentRecord->ui32Line);
+ switch (psCurrentRecord->eAllocType) {
+ case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+ KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+ IOUnmapWrapper((__force __iomem void *)
+ psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IO:
+
+ DebugMemAllocRecordRemove
+ (DEBUG_MEM_ALLOC_TYPE_IO,
+ psCurrentRecord->pvKey, __FILE__,
+ __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+ VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+
+ DebugMemAllocRecordRemove
+ (DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ psCurrentRecord->pvKey, __FILE__,
+ __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+ KMemCacheFreeWrapper(psCurrentRecord->
+ pvPrivateData,
+ psCurrentRecord->
+ pvCpuVAddr);
+ break;
+ default:
+ PVR_ASSERT(0);
+ }
+ psCurrentRecord = psNextRecord;
+ }
+ RemoveProcEntry("meminfo");
+ }
+#endif
+
+ if (psLinuxMemAreaCache) {
+ kmem_cache_destroy(psLinuxMemAreaCache);
+ psLinuxMemAreaCache = NULL;
+ }
+}
+
+void *_KMallocWrapper(u32 ui32ByteSize, char *pszFileName,
+ u32 ui32Line)
+{
+ void *pvRet;
+ pvRet = kmalloc(ui32ByteSize, GFP_KERNEL);
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
+ pvRet, pvRet, 0, NULL, ui32ByteSize,
+ pszFileName, ui32Line);
+#endif
+ return pvRet;
+}
+
+void _KFreeWrapper(void *pvCpuVAddr, char *pszFileName,
+ u32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMALLOC, pvCpuVAddr,
+ pszFileName, ui32Line);
+#endif
+ kfree(pvCpuVAddr);
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static void DebugMemAllocRecordAdd(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
+ void *pvKey, void *pvCpuVAddr,
+ u32 ulCpuPAddr, void *pvPrivateData,
+ u32 ui32Bytes, char *pszFileName,
+ u32 ui32Line)
+{
+ struct DEBUG_MEM_ALLOC_REC *psRecord;
+
+ mutex_lock(&g_sDebugMutex);
+
+ psRecord = kmalloc(sizeof(struct DEBUG_MEM_ALLOC_REC), GFP_KERNEL);
+
+ psRecord->eAllocType = eAllocType;
+ psRecord->pvKey = pvKey;
+ psRecord->pvCpuVAddr = pvCpuVAddr;
+ psRecord->ulCpuPAddr = ulCpuPAddr;
+ psRecord->pvPrivateData = pvPrivateData;
+ psRecord->pid = current->pid;
+ psRecord->ui32Bytes = ui32Bytes;
+ psRecord->pszFileName = pszFileName;
+ psRecord->ui32Line = ui32Line;
+
+ psRecord->psNext = g_MemoryRecords;
+ g_MemoryRecords = psRecord;
+
+ g_WaterMarkData[eAllocType] += ui32Bytes;
+ if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+ g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
+
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC ||
+ eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC ||
+ eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES ||
+ eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE) {
+ g_SysRAMWaterMark += ui32Bytes;
+ if (g_SysRAMWaterMark > g_SysRAMHighWaterMark)
+ g_SysRAMHighWaterMark = g_SysRAMWaterMark;
+ } else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP ||
+ eAllocType == DEBUG_MEM_ALLOC_TYPE_IO) {
+ g_IOMemWaterMark += ui32Bytes;
+ if (g_IOMemWaterMark > g_IOMemHighWaterMark)
+ g_IOMemHighWaterMark = g_IOMemWaterMark;
+ }
+
+ mutex_unlock(&g_sDebugMutex);
+}
+
+static void DebugMemAllocRecordRemove(enum DEBUG_MEM_ALLOC_TYPE eAllocType,
+ void *pvKey, char *pszFileName,
+ u32 ui32Line)
+{
+ struct DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;
+
+ mutex_lock(&g_sDebugMutex);
+
+ for (ppsCurrentRecord = &g_MemoryRecords; *ppsCurrentRecord;
+ ppsCurrentRecord = &((*ppsCurrentRecord)->psNext))
+ if ((*ppsCurrentRecord)->eAllocType == eAllocType &&
+ (*ppsCurrentRecord)->pvKey == pvKey) {
+ struct DEBUG_MEM_ALLOC_REC *psNextRecord;
+
+ psNextRecord = (*ppsCurrentRecord)->psNext;
+ g_WaterMarkData[eAllocType] -=
+ (*ppsCurrentRecord)->ui32Bytes;
+
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC ||
+ eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC ||
+ eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES ||
+ eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE) {
+ g_SysRAMWaterMark -=
+ (*ppsCurrentRecord)->ui32Bytes;
+ } else {
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ || eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
+ g_IOMemWaterMark -=
+ (*ppsCurrentRecord)->ui32Bytes;
+
+ }
+
+ kfree(*ppsCurrentRecord);
+ *ppsCurrentRecord = psNextRecord;
+ goto exit_unlock;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR, "%s: couldn't find an entry for type=%s "
+ "with pvKey=%p (called from %s, line %d\n",
+ __func__, DebugMemAllocRecordTypeToString(eAllocType), pvKey,
+ pszFileName, ui32Line);
+
+exit_unlock:
+ mutex_unlock(&g_sDebugMutex);
+}
+
+static char *DebugMemAllocRecordTypeToString(
+ enum DEBUG_MEM_ALLOC_TYPE eAllocType)
+{
+ char *apszDebugMemoryRecordTypes[] = {
+ "KMALLOC",
+ "VMALLOC",
+ "ALLOC_PAGES",
+ "IOREMAP",
+ "IO",
+ "KMEM_CACHE_ALLOC"
+ };
+ return apszDebugMemoryRecordTypes[eAllocType];
+}
+#endif
+
+void *_VMallocWrapper(u32 ui32Bytes, u32 ui32AllocFlags, char *pszFileName,
+ u32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ void *pvRet;
+
+ switch (ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK) {
+ case PVRSRV_HAP_CACHED:
+ PGProtFlags = PAGE_KERNEL;
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ PGProtFlags = PGPROT_WC(PAGE_KERNEL);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ PGProtFlags = PGPROT_UC(PAGE_KERNEL);
+ break;
+ default:
+ PVR_DPF(PVR_DBG_ERROR,
+ "VMAllocWrapper: unknown mapping flags=0x%08lx",
+ ui32AllocFlags);
+ dump_stack();
+ return NULL;
+ }
+
+ pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
+ pvRet, pvRet, 0, NULL,
+ PAGE_ALIGN(ui32Bytes),
+ pszFileName, ui32Line);
+#endif
+
+ return pvRet;
+}
+
+void _VFreeWrapper(void *pvCpuVAddr, char *pszFileName, u32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMALLOC, pvCpuVAddr,
+ pszFileName, ui32Line);
+#endif
+ vfree(pvCpuVAddr);
+}
+
+struct LinuxMemArea *NewVMallocLinuxMemArea(u32 ui32Bytes, u32 ui32AreaFlags)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ void *pvCpuVAddr;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ goto failed;
+
+ pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
+ if (!pvCpuVAddr)
+ goto failed;
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
+ psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+
+failed:
+ PVR_DPF(PVR_DBG_ERROR, "%s: failed!", __func__);
+ if (psLinuxMemArea)
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ return NULL;
+}
+
+void FreeVMallocLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
+ PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+
+ PVR_DPF(PVR_DBG_MESSAGE, "%s: pvCpuVAddr: %p",
+ __func__,
+ psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+ VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+void __iomem *_IORemapWrapper(struct IMG_CPU_PHYADDR BasePAddr,
+ u32 ui32Bytes, u32 ui32MappingFlags,
+ char *pszFileName, u32 ui32Line)
+{
+ void __iomem *pvIORemapCookie = NULL;
+
+ switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK) {
+ case PVRSRV_HAP_CACHED:
+ pvIORemapCookie = IOREMAP(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ pvIORemapCookie = IOREMAP_WC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ pvIORemapCookie = IOREMAP_UC(BasePAddr.uiAddr, ui32Bytes);
+ break;
+ default:
+ PVR_DPF(PVR_DBG_ERROR,
+ "IORemapWrapper: unknown mapping flags");
+ return NULL;
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvIORemapCookie)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ (__force void *)pvIORemapCookie,
+ (__force void *)pvIORemapCookie,
+ BasePAddr.uiAddr,
+ NULL, ui32Bytes, pszFileName, ui32Line);
+#endif
+
+ return pvIORemapCookie;
+}
+
+void _IOUnmapWrapper(void __iomem *pvIORemapCookie, char *pszFileName,
+ u32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
+ (__force void *)pvIORemapCookie,
+ pszFileName, ui32Line);
+#endif
+ iounmap(pvIORemapCookie);
+}
+
+struct LinuxMemArea *NewIORemapLinuxMemArea(struct IMG_CPU_PHYADDR BasePAddr,
+ u32 ui32Bytes, u32 ui32AreaFlags)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ void __iomem *pvIORemapCookie;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ return NULL;
+
+ pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
+ if (!pvIORemapCookie) {
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ return NULL;
+ }
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IOREMAP;
+ psLinuxMemArea->uData.sIORemap.pvIORemapCookie = pvIORemapCookie;
+ psLinuxMemArea->uData.sIORemap.CPUPhysAddr = BasePAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+void FreeIORemapLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IOREMAP);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ IOUnmapWrapper(psLinuxMemArea->uData.sIORemap.pvIORemapCookie);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+static IMG_BOOL PagesAreContiguous(struct IMG_SYS_PHYADDR *psSysPhysAddr,
+ u32 ui32Bytes)
+{
+ u32 ui32;
+ u32 ui32AddrChk;
+ u32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+ for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
+ ui32 < ui32NumPages; ui32++, ui32AddrChk += PAGE_SIZE)
+ if (psSysPhysAddr[ui32].uiAddr != ui32AddrChk)
+ return IMG_FALSE;
+
+ return IMG_TRUE;
+}
+
+struct LinuxMemArea *NewExternalKVLinuxMemArea(struct IMG_SYS_PHYADDR
+ *pBasePAddr, void *pvCPUVAddr,
+ u32 ui32Bytes,
+ IMG_BOOL bPhysContig,
+ u32 ui32AreaFlags)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ return NULL;
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_EXTERNAL_KV;
+ psLinuxMemArea->uData.sExternalKV.pvExternalKV = pvCPUVAddr;
+ psLinuxMemArea->uData.sExternalKV.bPhysContig = bPhysContig ||
+ PagesAreContiguous(pBasePAddr, ui32Bytes);
+
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig)
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.SysPhysAddr =
+ *pBasePAddr;
+ else
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr =
+ pBasePAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+void FreeExternalKVLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+struct LinuxMemArea *NewIOLinuxMemArea(struct IMG_CPU_PHYADDR BasePAddr,
+ u32 ui32Bytes, u32 ui32AreaFlags)
+{
+ struct LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ return NULL;
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
+ psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IO,
+ (void *)BasePAddr.uiAddr, NULL,
+ BasePAddr.uiAddr, NULL, ui32Bytes, "unknown", 0);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+}
+
+void FreeIOLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_IO);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO,
+ (void *)psLinuxMemArea->uData.sIO.
+ CPUPhysAddr.uiAddr, __FILE__, __LINE__);
+#endif
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+struct LinuxMemArea *NewAllocPagesLinuxMemArea(u32 ui32Bytes,
+ u32 ui32AreaFlags)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ u32 ui32PageCount;
+ struct page **pvPageList;
+ void *hBlockPageList;
+ s32 i;
+ enum PVRSRV_ERROR eError;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ goto failed_area_alloc;
+
+ ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
+ eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount,
+ (void **)&pvPageList, &hBlockPageList);
+ if (eError != PVRSRV_OK)
+ goto failed_page_list_alloc;
+
+ for (i = 0; i < ui32PageCount; i++) {
+ pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+ if (!pvPageList[i])
+ goto failed_alloc_pages;
+
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ pvPageList, NULL, 0, NULL, PAGE_ALIGN(ui32Bytes),
+ "unknown", 0);
+#endif
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
+ psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
+ psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+ return psLinuxMemArea;
+
+failed_alloc_pages:
+ for (i--; i >= 0; i--)
+ __free_pages(pvPageList[i], 0);
+ OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList,
+ hBlockPageList);
+failed_page_list_alloc:
+ LinuxMemAreaStructFree(psLinuxMemArea);
+failed_area_alloc:
+ PVR_DPF(PVR_DBG_ERROR, "%s: failed", __func__);
+
+ return NULL;
+}
+
+void FreeAllocPagesLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
+{
+ u32 ui32PageCount;
+ struct page **pvPageList;
+ void *hBlockPageList;
+ u32 i;
+
+ PVR_ASSERT(psLinuxMemArea);
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
+ hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList,
+ __FILE__, __LINE__);
+#endif
+
+ for (i = 0; i < ui32PageCount; i++)
+ __free_pages(pvPageList[i], 0);
+
+ OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList,
+ hBlockPageList);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+struct page *LinuxMemAreaOffsetToPage(struct LinuxMemArea *psLinuxMemArea,
+ u32 ui32ByteOffset)
+{
+ u32 ui32PageIndex;
+ char *pui8Addr;
+
+ switch (psLinuxMemArea->eAreaType) {
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ return
+ psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+ break;
+ case LINUX_MEM_AREA_VMALLOC:
+ pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ pui8Addr += ui32ByteOffset;
+ return vmalloc_to_page(pui8Addr);
+ break;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return LinuxMemAreaOffsetToPage(psLinuxMemArea->
+ uData.sSubAlloc.psParentLinuxMemArea,
+ psLinuxMemArea->
+ uData.sSubAlloc.ui32ByteOffset +
+ ui32ByteOffset);
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "%s: Unsupported request for "
+ "struct page from struct LinuxMemArea with type=%s",
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType));
+ return NULL;
+ }
+}
+
+void *_KMemCacheAllocWrapper(struct kmem_cache *psCache,
+ gfp_t Flags,
+ char *pszFileName, u32 ui32Line)
+{
+ void *pvRet;
+
+ pvRet = kmem_cache_alloc(psCache, Flags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvRet, pvRet,
+ 0, psCache, kmem_cache_size(psCache),
+ pszFileName, ui32Line);
+#endif
+
+ return pvRet;
+}
+
+void _KMemCacheFreeWrapper(struct kmem_cache *psCache, void *pvObject,
+ char *pszFileName, u32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject,
+ pszFileName, ui32Line);
+#endif
+
+ kmem_cache_free(psCache, pvObject);
+}
+
+const char *KMemCacheNameWrapper(struct kmem_cache *psCache)
+{
+
+ return "";
+}
+
+struct LinuxMemArea *NewSubLinuxMemArea(struct LinuxMemArea
+ *psParentLinuxMemArea, u32 ui32ByteOffset,
+ u32 ui32Bytes)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+
+ PVR_ASSERT((ui32ByteOffset + ui32Bytes) <=
+ psParentLinuxMemArea->ui32ByteSize);
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
+ return NULL;
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_SUB_ALLOC;
+ psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea =
+ psParentLinuxMemArea;
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset = ui32ByteOffset;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = psParentLinuxMemArea->ui32AreaFlags;
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ struct DEBUG_LINUX_MEM_AREA_REC *psParentRecord;
+ psParentRecord =
+ DebugLinuxMemAreaRecordFind(psParentLinuxMemArea);
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea,
+ psParentRecord->ui32Flags);
+ }
+#endif
+
+ return psLinuxMemArea;
+}
+
+static void FreeSubLinuxMemArea(struct LinuxMemArea *psLinuxMemArea)
+{
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+static struct LinuxMemArea *LinuxMemAreaStructAlloc(void)
+{
+ return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
+}
+
+static void LinuxMemAreaStructFree(struct LinuxMemArea *psLinuxMemArea)
+{
+ KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
+
+}
+
+void LinuxMemAreaDeepFree(struct LinuxMemArea *psLinuxMemArea)
+{
+ switch (psLinuxMemArea->eAreaType) {
+ case LINUX_MEM_AREA_VMALLOC:
+ FreeVMallocLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ FreeAllocPagesLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IOREMAP:
+ FreeIORemapLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ FreeExternalKVLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_IO:
+ FreeIOLinuxMemArea(psLinuxMemArea);
+ break;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ FreeSubLinuxMemArea(psLinuxMemArea);
+ break;
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
+ __func__, psLinuxMemArea->eAreaType);
+ }
+}
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static void DebugLinuxMemAreaRecordAdd(struct LinuxMemArea *psLinuxMemArea,
+ u32 ui32Flags)
+{
+ struct DEBUG_LINUX_MEM_AREA_REC *psNewRecord;
+ const char *pi8FlagsString;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC) {
+ g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
+ if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+ g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
+ }
+ g_LinuxMemAreaCount++;
+
+ psNewRecord = kmalloc(sizeof(struct DEBUG_LINUX_MEM_AREA_REC),
+ GFP_KERNEL);
+ if (psNewRecord) {
+ psNewRecord->psLinuxMemArea = psLinuxMemArea;
+ psNewRecord->ui32Flags = ui32Flags;
+ psNewRecord->pid = current->pid;
+ psNewRecord->psNext = g_LinuxMemAreaRecords;
+ g_LinuxMemAreaRecords = psNewRecord;
+ } else {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: failed to allocate linux memory area record.",
+ __func__);
+ }
+
+ pi8FlagsString = HAPFlagsToString(ui32Flags);
+ if (strstr(pi8FlagsString, "UNKNOWN"))
+ PVR_DPF(PVR_DBG_ERROR, "%s: Unexpected flags "
+ "(0x%08lx) associated with psLinuxMemArea @ 0x%08lx",
+ __func__, ui32Flags, psLinuxMemArea);
+
+ mutex_unlock(&g_sDebugMutex);
+}
+
+static struct DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(
+ struct LinuxMemArea *psLinuxMemArea)
+{
+ struct DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord;
+
+ mutex_lock(&g_sDebugMutex);
+
+ for (psCurrentRecord = g_LinuxMemAreaRecords;
+ psCurrentRecord; psCurrentRecord = psCurrentRecord->psNext)
+ if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+ goto exit_unlock;
+
+exit_unlock:
+ mutex_unlock(&g_sDebugMutex);
+
+ return psCurrentRecord;
+}
+
+static void DebugLinuxMemAreaRecordRemove(struct LinuxMemArea *psLinuxMemArea)
+{
+ struct DEBUG_LINUX_MEM_AREA_REC **ppsCurrentRecord;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
+ g_LinuxMemAreaCount--;
+
+ for (ppsCurrentRecord = &g_LinuxMemAreaRecords;
+ *ppsCurrentRecord;
+ ppsCurrentRecord = &((*ppsCurrentRecord)->psNext))
+ if ((*ppsCurrentRecord)->psLinuxMemArea == psLinuxMemArea) {
+ struct DEBUG_LINUX_MEM_AREA_REC *psNextRecord;
+
+ psNextRecord = (*ppsCurrentRecord)->psNext;
+ kfree(*ppsCurrentRecord);
+ *ppsCurrentRecord = psNextRecord;
+ goto exit_unlock;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: couldn't find an entry for psLinuxMemArea=%p\n", __func__,
+ psLinuxMemArea);
+
+exit_unlock:
+ mutex_unlock(&g_sDebugMutex);
+}
+#endif
+
+void *LinuxMemAreaToCpuVAddr(struct LinuxMemArea *psLinuxMemArea)
+{
+ switch (psLinuxMemArea->eAreaType) {
+ case LINUX_MEM_AREA_VMALLOC:
+ return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
+ case LINUX_MEM_AREA_IOREMAP:
+ return (void __force *)
+ psLinuxMemArea->uData.sIORemap.pvIORemapCookie;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.pvExternalKV;
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ char *pAddr =
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.
+ sSubAlloc.
+ psParentLinuxMemArea);
+ if (!pAddr)
+ return NULL;
+ return pAddr +
+ psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset;
+ }
+ default:
+ return NULL;
+ }
+}
+
+struct IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(
+ struct LinuxMemArea *psLinuxMemArea,
+ u32 ui32ByteOffset)
+{
+ struct IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = 0;
+
+ switch (psLinuxMemArea->eAreaType) {
+ case LINUX_MEM_AREA_IOREMAP:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIORemap.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ {
+ if (psLinuxMemArea->uData.sExternalKV.bPhysContig) {
+ CpuPAddr =
+ SysSysPAddrToCpuPAddr(
+ psLinuxMemArea->uData.
+ sExternalKV.uPhysAddr.
+ SysPhysAddr);
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ } else {
+ u32 ui32PageIndex =
+ PHYS_TO_PFN(ui32ByteOffset);
+ struct IMG_SYS_PHYADDR SysPAddr =
+ psLinuxMemArea->uData.sExternalKV.uPhysAddr.
+ pSysPhysAddr[ui32PageIndex];
+
+ CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
+ CpuPAddr.uiAddr +=
+ ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ }
+ break;
+ }
+ case LINUX_MEM_AREA_IO:
+ {
+ CpuPAddr = psLinuxMemArea->uData.sIO.CPUPhysAddr;
+ CpuPAddr.uiAddr += ui32ByteOffset;
+ break;
+ }
+ case LINUX_MEM_AREA_VMALLOC:
+ {
+ char *pCpuVAddr;
+ pCpuVAddr =
+ (char *) psLinuxMemArea->uData.sVmalloc.
+ pvVmallocAddress;
+ pCpuVAddr += ui32ByteOffset;
+ CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
+ break;
+ }
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ {
+ struct page *page;
+ u32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ page =
+ psLinuxMemArea->uData.sPageList.
+ pvPageList[ui32PageIndex];
+ CpuPAddr.uiAddr = page_to_phys(page);
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ break;
+ }
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ {
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psLinuxMemArea->uData.
+ sSubAlloc.
+ psParentLinuxMemArea,
+ psLinuxMemArea->uData.
+ sSubAlloc.ui32ByteOffset +
+ ui32ByteOffset);
+ break;
+ }
+ default:
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Unknown struct LinuxMemArea type (%d)\n",
+ __func__, psLinuxMemArea->eAreaType);
+ }
+
+ PVR_ASSERT(CpuPAddr.uiAddr);
+ return CpuPAddr;
+}
+
+static void inv_cache_vmalloc(const struct LinuxMemArea *mem_area)
+{
+ struct page *pg;
+ void *kaddr;
+ size_t chunk;
+ u32 pg_cnt;
+ u32 pg_ofs;
+ u32 vaddr, vaddr_end;
+
+ extern void ___dma_single_dev_to_cpu(const void *, size_t,
+ enum dma_data_direction);
+
+ vaddr = (u32)mem_area->uData.sVmalloc.pvVmallocAddress;
+ vaddr_end = vaddr + mem_area->ui32ByteSize;
+ pg_cnt = (PAGE_ALIGN(vaddr_end) - (vaddr & PAGE_MASK)) / PAGE_SIZE;
+
+ while (pg_cnt--) {
+ pg = pfn_to_page(VMallocToPhys((void *)vaddr) >> PAGE_SHIFT);
+ kaddr = page_address(pg);
+ pg_ofs = vaddr & ~PAGE_MASK;
+ kaddr += pg_ofs;
+ chunk = min_t(ssize_t, vaddr_end - vaddr, PAGE_SIZE - pg_ofs);
+ ___dma_single_dev_to_cpu(kaddr, chunk, DMA_FROM_DEVICE);
+ vaddr += chunk;
+ }
+}
+
+static void inv_cache_page_list(const struct LinuxMemArea *mem_area)
+{
+ u32 pg_cnt;
+ struct page **pg_list;
+
+ extern void ___dma_single_dev_to_cpu(const void *, size_t,
+ enum dma_data_direction);
+
+ pg_cnt = RANGE_TO_PAGES(mem_area->ui32ByteSize);
+ pg_list = mem_area->uData.sPageList.pvPageList;
+ while (pg_cnt--)
+ ___dma_single_dev_to_cpu(page_address(*pg_list++), PAGE_SIZE,
+ DMA_FROM_DEVICE);
+}
+
+void inv_cache_mem_area(const struct LinuxMemArea *mem_area)
+{
+ switch (mem_area->eAreaType) {
+ case LINUX_MEM_AREA_VMALLOC:
+ inv_cache_vmalloc(mem_area);
+ break;
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ inv_cache_page_list(mem_area);
+ break;
+ case LINUX_MEM_AREA_IOREMAP:
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ case LINUX_MEM_AREA_IO:
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Not implemented for type (%d)\n",
+ __func__, mem_area->eAreaType);
+ BUG();
+ default:
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Unknown LinuxMemArea type (%d)\n",
+ __func__, mem_area->eAreaType);
+ BUG();
+ }
+}
+
+IMG_BOOL LinuxMemAreaPhysIsContig(struct LinuxMemArea *psLinuxMemArea)
+{
+ switch (psLinuxMemArea->eAreaType) {
+ case LINUX_MEM_AREA_IOREMAP:
+ case LINUX_MEM_AREA_IO:
+ return IMG_TRUE;
+
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+ case LINUX_MEM_AREA_VMALLOC:
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return IMG_FALSE;
+
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.
+ psParentLinuxMemArea);
+
+ default:
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Unknown struct LinuxMemArea type (%d)\n",
+ __func__, psLinuxMemArea->eAreaType);
+ break;
+ }
+ return IMG_FALSE;
+}
+
+const char *LinuxMemAreaTypeToString(enum LINUX_MEM_AREA_TYPE eMemAreaType)
+{
+ switch (eMemAreaType) {
+ case LINUX_MEM_AREA_IOREMAP:
+ return "LINUX_MEM_AREA_IOREMAP";
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return "LINUX_MEM_AREA_EXTERNAL_KV";
+ case LINUX_MEM_AREA_IO:
+ return "LINUX_MEM_AREA_IO";
+ case LINUX_MEM_AREA_VMALLOC:
+ return "LINUX_MEM_AREA_VMALLOC";
+ case LINUX_MEM_AREA_SUB_ALLOC:
+ return "LINUX_MEM_AREA_SUB_ALLOC";
+ case LINUX_MEM_AREA_ALLOC_PAGES:
+ return "LINUX_MEM_AREA_ALLOC_PAGES";
+ default:
+ PVR_ASSERT(0);
+ }
+
+ return "";
+}
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static off_t printLinuxMemAreaRecords(char *buffer, size_t count, off_t off)
+{
+ struct DEBUG_LINUX_MEM_AREA_REC *psRecord;
+ off_t Ret;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if (!off) {
+ if (count < 500) {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+ Ret = printAppend(buffer, count, 0,
+ "Number of Linux Memory Areas: %u\n"
+ "At the current water mark these areas "
+ "correspond to %u bytes "
+ "(excluding SUB areas)\n"
+ "At the highest water mark these areas "
+ "corresponded to %u bytes "
+ "(excluding SUB areas)\n"
+ "\nDetails for all Linux Memory Areas:\n"
+ "%s %-24s %s %s %-8s %-5s %s\n",
+ g_LinuxMemAreaCount,
+ g_LinuxMemAreaWaterMark,
+ g_LinuxMemAreaHighWaterMark,
+ "psLinuxMemArea",
+ "LinuxMemType",
+ "CpuVAddr",
+ "CpuPAddr", "Bytes", "Pid", "Flags");
+ goto unlock_and_return;
+ }
+
+ for (psRecord = g_LinuxMemAreaRecords; --off && psRecord;
+ psRecord = psRecord->psNext)
+ ;
+ if (!psRecord) {
+ Ret = END_OF_FILE;
+ goto unlock_and_return;
+ }
+
+ if (count < 500) {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ Ret = printAppend(buffer, count, 0,
+ "%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
+ psRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psRecord->psLinuxMemArea->
+ eAreaType),
+ LinuxMemAreaToCpuVAddr(psRecord->psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psRecord->psLinuxMemArea,
+ 0).uiAddr,
+ psRecord->psLinuxMemArea->ui32ByteSize, psRecord->pid,
+ psRecord->ui32Flags,
+ HAPFlagsToString(psRecord->ui32Flags)
+ );
+
+unlock_and_return:
+ mutex_unlock(&g_sDebugMutex);
+ return Ret;
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static off_t printMemoryRecords(char *buffer, size_t count, off_t off)
+{
+ struct DEBUG_MEM_ALLOC_REC *psRecord;
+ off_t Ret;
+
+ mutex_lock(&g_sDebugMutex);
+
+ if (!off) {
+ if (count < 1000) {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ Ret = printAppend(buffer, count, 0, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via kmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via kmalloc",
+ g_HighWaterMarkData
+ [DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via vmalloc",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via vmalloc",
+ g_HighWaterMarkData
+ [DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via alloc_pages",
+ g_WaterMarkData
+ [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via alloc_pages",
+ g_HighWaterMarkData
+ [DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via ioremap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via ioremap",
+ g_HighWaterMarkData
+ [DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes reserved for "
+ "\"IO\" memory areas",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated for "
+ "\"IO\" memory areas",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes allocated via "
+ "kmem_cache_alloc",
+ g_WaterMarkData
+ [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes allocated via "
+ "kmem_cache_alloc",
+ g_HighWaterMarkData
+ [DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+ Ret = printAppend(buffer, count, Ret, "\n");
+
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "The Current Water Mark for memory allocated from system RAM",
+ g_SysRAMWaterMark);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "The Highest Water Mark for memory allocated from system RAM",
+ g_SysRAMHighWaterMark);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "The Current Water Mark for memory allocated from IO memory",
+ g_IOMemWaterMark);
+ Ret = printAppend(buffer, count, Ret, "%-60s: %d bytes\n",
+ "The Highest Water Mark for memory allocated from IO memory",
+ g_IOMemHighWaterMark);
+
+ Ret = printAppend(buffer, count, Ret, "\n");
+
+ Ret = printAppend(buffer, count, Ret,
+ "Details for all known allocations:\n"
+ "%-16s %-8s %-8s %-10s %-5s %-10s %s\n", "Type",
+ "CpuVAddr", "CpuPAddr", "Bytes", "PID",
+ "PrivateData", "Filename:Line");
+
+
+ goto unlock_and_return;
+ }
+
+ if (count < 1000) {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ for (psRecord = g_MemoryRecords; --off && psRecord;
+ psRecord = psRecord->psNext)
+ ;
+ if (!psRecord) {
+ Ret = END_OF_FILE;
+ goto unlock_and_return;
+ }
+
+ if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ Ret = printAppend(buffer, count, 0,
+ "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr, psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes, psRecord->pid, "NULL",
+ psRecord->pszFileName, psRecord->ui32Line);
+ else
+ Ret = printAppend(buffer, count, 0,
+ "%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
+ DebugMemAllocRecordTypeToString(psRecord->eAllocType),
+ psRecord->pvCpuVAddr, psRecord->ulCpuPAddr,
+ psRecord->ui32Bytes, psRecord->pid,
+ KMemCacheNameWrapper(psRecord->pvPrivateData),
+ psRecord->pszFileName, psRecord->ui32Line);
+
+unlock_and_return:
+ mutex_unlock(&g_sDebugMutex);
+ return Ret;
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+const char *HAPFlagsToString(u32 ui32Flags)
+{
+ static char szFlags[50];
+ s32 i32Pos = 0;
+ u32 ui32CacheTypeIndex, ui32MapTypeIndex;
+ char *apszCacheTypes[] = {
+ "UNCACHED",
+ "CACHED",
+ "WRITECOMBINE",
+ "UNKNOWN"
+ };
+ char *apszMapType[] = {
+ "KERNEL_ONLY",
+ "SINGLE_PROCESS",
+ "MULTI_PROCESS",
+ "FROM_EXISTING_PROCESS",
+ "NO_CPU_VIRTUAL",
+ "UNKNOWN"
+ };
+
+ if (ui32Flags & PVRSRV_HAP_UNCACHED) {
+ ui32CacheTypeIndex = 0;
+ } else if (ui32Flags & PVRSRV_HAP_CACHED) {
+ ui32CacheTypeIndex = 1;
+ } else if (ui32Flags & PVRSRV_HAP_WRITECOMBINE) {
+ ui32CacheTypeIndex = 2;
+ } else {
+ ui32CacheTypeIndex = 3;
+ PVR_DPF(PVR_DBG_ERROR, "%s: unknown cache type (%u)",
+ __func__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK));
+ }
+
+ if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) {
+ ui32MapTypeIndex = 0;
+ } else if (ui32Flags & PVRSRV_HAP_SINGLE_PROCESS) {
+ ui32MapTypeIndex = 1;
+ } else if (ui32Flags & PVRSRV_HAP_MULTI_PROCESS) {
+ ui32MapTypeIndex = 2;
+ } else if (ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS) {
+ ui32MapTypeIndex = 3;
+ } else if (ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL) {
+ ui32MapTypeIndex = 4;
+ } else {
+ ui32MapTypeIndex = 5;
+ PVR_DPF(PVR_DBG_ERROR, "%s: unknown map type (%u)",
+ __func__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK));
+ }
+
+ i32Pos = sprintf(szFlags, "%s|", apszCacheTypes[ui32CacheTypeIndex]);
+ if (i32Pos <= 0) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: sprintf for cache type %u failed (%d)", __func__,
+ ui32CacheTypeIndex, i32Pos);
+ szFlags[0] = 0;
+ } else {
+ sprintf(szFlags + i32Pos, "%s", apszMapType[ui32MapTypeIndex]);
+ }
+
+ return szFlags;
+}
+#endif
diff --git a/drivers/gpu/pvr/mm.h b/drivers/gpu/pvr/mm.h
new file mode 100644
index 00000000000..47c3fbce76a
--- /dev/null
+++ b/drivers/gpu/pvr/mm.h
@@ -0,0 +1,261 @@
+/**********************************************************************
+ *
+ * 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 __IMG_LINUX_MM_H__
+#define __IMG_LINUX_MM_H__
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <linux/io.h>
+
+#define PHYS_TO_PFN(phys) ((phys) >> PAGE_SHIFT)
+#define PFN_TO_PHYS(pfn) ((pfn) << PAGE_SHIFT)
+
+#define RANGE_TO_PAGES(range) \
+ (((range) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+
+#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+
+#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) \
+ remap_pfn_range(vma, addr, pfn, size, prot)
+
+#define IO_REMAP_PFN_RANGE(vma, addr, pfn, size, prot) \
+ io_remap_pfn_range(vma, addr, pfn, size, prot)
+
+#define VM_INSERT_PAGE(vma, addr, page) vm_insert_page(vma, addr, page)
+
+static inline u32 VMallocToPhys(void *pCpuVAddr)
+{
+ return page_to_phys(vmalloc_to_page(pCpuVAddr)) +
+ ADDR_TO_PAGE_OFFSET(pCpuVAddr);
+
+}
+
+enum LINUX_MEM_AREA_TYPE {
+ LINUX_MEM_AREA_IOREMAP,
+ LINUX_MEM_AREA_EXTERNAL_KV,
+ LINUX_MEM_AREA_IO,
+ LINUX_MEM_AREA_VMALLOC,
+ LINUX_MEM_AREA_ALLOC_PAGES,
+ LINUX_MEM_AREA_SUB_ALLOC,
+ LINUX_MEM_AREA_TYPE_COUNT
+};
+
+struct LinuxMemArea;
+
+struct LinuxMemArea {
+ enum LINUX_MEM_AREA_TYPE eAreaType;
+ union _uData {
+ struct _sIORemap {
+ struct IMG_CPU_PHYADDR CPUPhysAddr;
+ void __iomem *pvIORemapCookie;
+ } sIORemap;
+ struct _sExternalKV {
+ IMG_BOOL bPhysContig;
+ union {
+ struct IMG_SYS_PHYADDR SysPhysAddr;
+ struct IMG_SYS_PHYADDR *pSysPhysAddr;
+ } uPhysAddr;
+ void *pvExternalKV;
+ } sExternalKV;
+ struct _sIO {
+ struct IMG_CPU_PHYADDR CPUPhysAddr;
+ } sIO;
+ struct _sVmalloc {
+ void *pvVmallocAddress;
+ } sVmalloc;
+ struct _sPageList {
+ struct page **pvPageList;
+ void *hBlockPageList;
+ } sPageList;
+ struct _sSubAlloc {
+ struct LinuxMemArea *psParentLinuxMemArea;
+ u32 ui32ByteOffset;
+ } sSubAlloc;
+ } uData;
+ u32 ui32ByteSize;
+ u32 ui32AreaFlags;
+ IMG_BOOL bMMapRegistered;
+ struct list_head sMMapItem;
+ struct list_head sMMapOffsetStructList;
+};
+
+struct kmem_cache;
+
+enum PVRSRV_ERROR LinuxMMInit(void);
+
+void LinuxMMCleanup(void);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMallocWrapper(ui32ByteSize) \
+ _KMallocWrapper(ui32ByteSize, __FILE__, __LINE__)
+#else
+#define KMallocWrapper(ui32ByteSize) \
+ _KMallocWrapper(ui32ByteSize, NULL, 0)
+#endif
+void *_KMallocWrapper(u32 ui32ByteSize, char *szFileName, u32 ui32Line);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+void _KFreeWrapper(void *pvCpuVAddr, char *pszFileName, u32 ui32Line);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) \
+ _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMallocWrapper(ui32Bytes, ui32AllocFlags) \
+ _VMallocWrapper(ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+void *_VMallocWrapper(u32 ui32Bytes, u32 ui32AllocFlags, char *pszFileName,
+ u32 ui32Line);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, NULL, 0)
+#endif
+void _VFreeWrapper(void *pvCpuVAddr, char *pszFileName, u32 ui32Line);
+
+struct LinuxMemArea *NewVMallocLinuxMemArea(u32 ui32Bytes, u32 ui32AreaFlags);
+
+void FreeVMallocLinuxMemArea(struct LinuxMemArea *psLinuxMemArea);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
+#else
+#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
+ _IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, NULL, 0)
+#endif
+void __iomem *_IORemapWrapper(struct IMG_CPU_PHYADDR BasePAddr, u32 ui32Bytes,
+ u32 ui32MappingFlags, char *pszFileName,
+ u32 ui32Line);
+
+struct LinuxMemArea *NewIORemapLinuxMemArea(struct IMG_CPU_PHYADDR BasePAddr,
+ u32 ui32Bytes, u32 ui32AreaFlags);
+
+void FreeIORemapLinuxMemArea(struct LinuxMemArea *psLinuxMemArea);
+
+struct LinuxMemArea *NewExternalKVLinuxMemArea(
+ struct IMG_SYS_PHYADDR *pBasePAddr, void *pvCPUVAddr,
+ u32 ui32Bytes, IMG_BOOL bPhysContig, u32 ui32AreaFlags);
+
+void FreeExternalKVLinuxMemArea(struct LinuxMemArea *psLinuxMemArea);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
+#else
+#define IOUnmapWrapper(pvIORemapCookie) \
+ _IOUnmapWrapper(pvIORemapCookie, NULL, 0)
+#endif
+void _IOUnmapWrapper(void __iomem *pvIORemapCookie, char *pszFileName,
+ u32 ui32Line);
+
+struct page *LinuxMemAreaOffsetToPage(struct LinuxMemArea *psLinuxMemArea,
+ u32 ui32ByteOffset);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheAllocWrapper(psCache, Flags) \
+ _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
+#else
+#define KMemCacheAllocWrapper(psCache, Flags) \
+ _KMemCacheAllocWrapper(psCache, Flags, NULL, 0)
+#endif
+
+void *_KMemCacheAllocWrapper(struct kmem_cache *psCache, gfp_t Flags,
+ char *pszFileName, u32 ui32Line);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define KMemCacheFreeWrapper(psCache, pvObject) \
+ _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
+#else
+#define KMemCacheFreeWrapper(psCache, pvObject) \
+ _KMemCacheFreeWrapper(psCache, pvObject, NULL, 0)
+#endif
+void _KMemCacheFreeWrapper(struct kmem_cache *psCache, void *pvObject,
+ char *pszFileName, u32 ui32Line);
+
+const char *KMemCacheNameWrapper(struct kmem_cache *psCache);
+
+struct LinuxMemArea *NewIOLinuxMemArea(struct IMG_CPU_PHYADDR BasePAddr,
+ u32 ui32Bytes, u32 ui32AreaFlags);
+
+void FreeIOLinuxMemArea(struct LinuxMemArea *psLinuxMemArea);
+
+struct LinuxMemArea *NewAllocPagesLinuxMemArea(u32 ui32Bytes,
+ u32 ui32AreaFlags);
+
+void FreeAllocPagesLinuxMemArea(struct LinuxMemArea *psLinuxMemArea);
+
+struct LinuxMemArea *NewSubLinuxMemArea(
+ struct LinuxMemArea *psParentLinuxMemArea,
+ u32 ui32ByteOffset, u32 ui32Bytes);
+
+void LinuxMemAreaDeepFree(struct LinuxMemArea *psLinuxMemArea);
+
+void *LinuxMemAreaToCpuVAddr(struct LinuxMemArea *psLinuxMemArea);
+
+struct IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(
+ struct LinuxMemArea *psLinuxMemArea,
+ u32 ui32ByteOffset);
+
+#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) \
+ PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, \
+ ui32ByteOffset).uiAddr)
+
+void inv_cache_mem_area(const struct LinuxMemArea *mem_area);
+
+IMG_BOOL LinuxMemAreaPhysIsContig(struct LinuxMemArea *psLinuxMemArea);
+
+static inline struct LinuxMemArea *LinuxMemAreaRoot(struct LinuxMemArea
+ *psLinuxMemArea)
+{
+ if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ return psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
+ else
+ return psLinuxMemArea;
+}
+
+static inline enum LINUX_MEM_AREA_TYPE LinuxMemAreaRootType(struct LinuxMemArea
+ *psLinuxMemArea)
+{
+ return LinuxMemAreaRoot(psLinuxMemArea)->eAreaType;
+}
+
+const char *LinuxMemAreaTypeToString(enum LINUX_MEM_AREA_TYPE eMemAreaType);
+
+#if defined(CONFIG_PVR_DEBUG_EXTRA) || defined(DEBUG_LINUX_MEM_AREAS)
+const char *HAPFlagsToString(u32 ui32Flags);
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/mmap.c b/drivers/gpu/pvr/mmap.c
new file mode 100644
index 00000000000..1c094aa5574
--- /dev/null
+++ b/drivers/gpu/pvr/mmap.c
@@ -0,0 +1,920 @@
+/**********************************************************************
+ *
+ * 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 <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <asm/shmparam.h>
+#include <asm/pgtable.h>
+#include <linux/sched.h>
+#include <asm/current.h>
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mmap.h"
+#include "mm.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+#include "proc.h"
+#include "handle.h"
+#include "perproc.h"
+#include "env_perproc.h"
+#include "bridged_support.h"
+
+static struct mutex g_sMMapMutex;
+
+static struct kmem_cache *g_psMemmapCache;
+static LIST_HEAD(g_sMMapAreaList);
+static LIST_HEAD(g_sMMapOffsetStructList);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static u32 g_ui32RegisteredAreas;
+static u32 g_ui32TotalByteSize;
+#endif
+
+#define LAST_PHYSICAL_PFN 0x7ffffffful
+#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
+#define LAST_SPECIAL_PFN 0xfffffffful
+
+#define MAX_MMAP_HANDLE 0x7ffffffful
+
+static inline IMG_BOOL PFNIsPhysical(u32 pfn)
+{
+ return pfn <= LAST_PHYSICAL_PFN;
+}
+
+static inline IMG_BOOL PFNIsSpecial(u32 pfn)
+{
+ return pfn >= FIRST_SPECIAL_PFN && pfn <= LAST_SPECIAL_PFN;
+}
+
+static inline void *MMapOffsetToHandle(u32 pfn)
+{
+ if (PFNIsPhysical(pfn)) {
+ PVR_ASSERT(PFNIsPhysical(pfn));
+ return NULL;
+ }
+
+ return (void *)(pfn - FIRST_SPECIAL_PFN);
+}
+
+static inline u32 HandleToMMapOffset(void *hHandle)
+{
+ u32 ulHandle = (u32) hHandle;
+
+ if (PFNIsSpecial(ulHandle)) {
+ PVR_ASSERT(PFNIsSpecial(ulHandle));
+ return 0;
+ }
+
+ return ulHandle + FIRST_SPECIAL_PFN;
+ }
+
+static inline IMG_BOOL LinuxMemAreaUsesPhysicalMap(
+ struct LinuxMemArea *psLinuxMemArea)
+{
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea);
+}
+
+static inline u32 GetCurrentThreadID(void)
+{
+
+ return (u32) current->pid;
+}
+
+static struct KV_OFFSET_STRUCT *CreateOffsetStruct(struct LinuxMemArea
+ *psLinuxMemArea,
+ u32 ui32Offset,
+ u32 ui32RealByteSize)
+{
+ struct KV_OFFSET_STRUCT *psOffsetStruct;
+#if defined(CONFIG_PVR_DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const char *pszName =
+ LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea: 0x%p, ui32AllocFlags: 0x%8lx)",
+ __func__, pszName, psLinuxMemArea,
+ psLinuxMemArea->ui32AreaFlags);
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC
+ || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType !=
+ LINUX_MEM_AREA_SUB_ALLOC);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ psOffsetStruct = KMemCacheAllocWrapper(g_psMemmapCache, GFP_KERNEL);
+ if (psOffsetStruct == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRMMapRegisterArea: "
+ "Couldn't alloc another mapping record from cache");
+ return NULL;
+ }
+
+ psOffsetStruct->ui32MMapOffset = ui32Offset;
+ psOffsetStruct->psLinuxMemArea = psLinuxMemArea;
+ psOffsetStruct->ui32Mapped = 0;
+ psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
+ psOffsetStruct->ui32TID = GetCurrentThreadID();
+ psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+ psOffsetStruct->ui32RefCount = 0;
+ psOffsetStruct->ui32UserVAddr = 0;
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ psOffsetStruct->pszName = pszName;
+#endif
+
+ list_add_tail(&psOffsetStruct->sAreaItem,
+ &psLinuxMemArea->sMMapOffsetStructList);
+
+ return psOffsetStruct;
+}
+
+static void DestroyOffsetStruct(struct KV_OFFSET_STRUCT *psOffsetStruct)
+{
+ list_del(&psOffsetStruct->sAreaItem);
+
+ if (psOffsetStruct->bOnMMapList)
+ list_del(&psOffsetStruct->sMMapItem);
+
+ PVR_DPF(PVR_DBG_MESSAGE, "%s: Table entry: "
+ "psLinuxMemArea=0x%08lX, CpuPAddr=0x%08lX", __func__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuPAddr(psOffsetStruct->psLinuxMemArea, 0));
+
+ KMemCacheFreeWrapper(g_psMemmapCache, psOffsetStruct);
+}
+
+static inline void DetermineUsersSizeAndByteOffset(struct LinuxMemArea
+ *psLinuxMemArea,
+ u32 *pui32RealByteSize,
+ u32 *pui32ByteOffset)
+{
+ u32 ui32PageAlignmentOffset;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+ ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+
+ *pui32ByteOffset = ui32PageAlignmentOffset;
+
+ *pui32RealByteSize =
+ PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+}
+
+enum PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hMHandle, u32 *pui32MMapOffset,
+ u32 *pui32ByteOffset, u32 *pui32RealByteSize,
+ u32 *pui32UserVAddr)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ struct KV_OFFSET_STRUCT *psOffsetStruct;
+ void *hOSMemHandle;
+ enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <=
+ MAX_MMAP_HANDLE);
+
+ eError =
+ PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle,
+ hMHandle);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed",
+ __func__, hMHandle);
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ pui32RealByteSize, pui32ByteOffset);
+
+ list_for_each_entry(psOffsetStruct,
+ &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) {
+ if (psPerProc->ui32PID == psOffsetStruct->ui32PID) {
+ PVR_ASSERT(*pui32RealByteSize ==
+ psOffsetStruct->ui32RealByteSize);
+
+ *pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
+ *pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
+ psOffsetStruct->ui32RefCount++;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+ *pui32UserVAddr = 0;
+
+ if (LinuxMemAreaUsesPhysicalMap(psLinuxMemArea)) {
+ *pui32MMapOffset = LinuxMemAreaToCpuPFN(psLinuxMemArea, 0);
+ PVR_ASSERT(PFNIsPhysical(*pui32MMapOffset));
+ } else {
+ *pui32MMapOffset = HandleToMMapOffset(hMHandle);
+ PVR_ASSERT(PFNIsSpecial(*pui32MMapOffset));
+ }
+
+ psOffsetStruct = CreateOffsetStruct(psLinuxMemArea, *pui32MMapOffset,
+ *pui32RealByteSize);
+ if (psOffsetStruct == NULL) {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exit_unlock;
+ }
+
+ list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
+ psOffsetStruct->bOnMMapList = IMG_TRUE;
+ psOffsetStruct->ui32RefCount++;
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRMMapReleaseMMapData(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hMHandle, IMG_BOOL *pbMUnmap,
+ u32 *pui32RealByteSize, u32 *pui32UserVAddr)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ struct KV_OFFSET_STRUCT *psOffsetStruct;
+ void *hOSMemHandle;
+ enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+ u32 ui32PID = OSGetCurrentProcessIDKM();
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(PVRSRVGetMaxHandle(psPerProc->psHandleBase) <=
+ MAX_MMAP_HANDLE);
+
+ eError = PVRSRVLookupOSMemHandle(psPerProc->psHandleBase, &hOSMemHandle,
+ hMHandle);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: Lookup of handle 0x%lx failed",
+ __func__, hMHandle);
+
+ goto exit_unlock;
+ }
+
+ psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
+
+ list_for_each_entry(psOffsetStruct,
+ &psLinuxMemArea->sMMapOffsetStructList, sAreaItem) {
+ if (psOffsetStruct->ui32PID == ui32PID) {
+ if (psOffsetStruct->ui32RefCount == 0) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: Attempt to "
+ "release mmap data with zero reference "
+ "count for offset struct 0x%p, "
+ "memory area 0x%p",
+ __func__, psOffsetStruct,
+ psLinuxMemArea);
+ eError = PVRSRV_ERROR_GENERIC;
+ goto exit_unlock;
+ }
+
+ psOffsetStruct->ui32RefCount--;
+
+ *pbMUnmap = (psOffsetStruct->ui32RefCount == 0)
+ && (psOffsetStruct->ui32UserVAddr != 0);
+
+ *pui32UserVAddr =
+ (*pbMUnmap) ? psOffsetStruct->ui32UserVAddr : 0;
+ *pui32RealByteSize =
+ (*pbMUnmap) ? psOffsetStruct->ui32RealByteSize : 0;
+
+ eError = PVRSRV_OK;
+ goto exit_unlock;
+ }
+ }
+
+ PVR_DPF(PVR_DBG_ERROR, "%s: Mapping data not found for handle "
+ "0x%lx (memory area 0x%p)",
+ __func__, hMHandle, psLinuxMemArea);
+
+ eError = PVRSRV_ERROR_GENERIC;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+static inline struct KV_OFFSET_STRUCT *FindOffsetStructByOffset(u32 ui32Offset,
+ u32 ui32RealByteSize)
+{
+ struct KV_OFFSET_STRUCT *psOffsetStruct;
+ u32 ui32TID = GetCurrentThreadID();
+ u32 ui32PID = OSGetCurrentProcessIDKM();
+
+ list_for_each_entry(psOffsetStruct, &g_sMMapOffsetStructList,
+ sMMapItem) {
+ if (ui32Offset == psOffsetStruct->ui32MMapOffset &&
+ ui32RealByteSize == psOffsetStruct->ui32RealByteSize &&
+ psOffsetStruct->ui32PID == ui32PID)
+ if (!PFNIsPhysical(ui32Offset) ||
+ psOffsetStruct->ui32TID == ui32TID)
+ return psOffsetStruct;
+ }
+
+ return NULL;
+}
+
+static IMG_BOOL DoMapToUser(struct LinuxMemArea *psLinuxMemArea,
+ struct vm_area_struct *ps_vma, u32 ui32ByteOffset)
+{
+ u32 ui32ByteSize;
+
+ if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
+ return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea), ps_vma,
+ psLinuxMemArea->uData.sSubAlloc.
+ ui32ByteOffset + ui32ByteOffset);
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+ PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
+
+ if (PFNIsPhysical(ps_vma->vm_pgoff)) {
+ int result;
+
+ PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
+ PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset)
+ == ps_vma->vm_pgoff);
+
+ result =
+ IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start,
+ ps_vma->vm_pgoff, ui32ByteSize,
+ ps_vma->vm_page_prot);
+
+ if (result == 0)
+ return IMG_TRUE;
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "%s: Failed to map contiguous physical address "
+ "range (%d), trying non-contiguous path",
+ __func__, result);
+ }
+
+ {
+ u32 ulVMAPos;
+ u32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
+ u32 ui32PA;
+
+ for (ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd;
+ ui32PA += PAGE_SIZE) {
+ u32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+
+ if (!pfn_valid(pfn)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Error - PFN invalid: 0x%lx",
+ __func__, pfn);
+ return IMG_FALSE;
+ }
+ }
+
+ ulVMAPos = ps_vma->vm_start;
+ for (ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd;
+ ui32PA += PAGE_SIZE) {
+ u32 pfn;
+ struct page *psPage;
+ int result;
+
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+ PVR_ASSERT(pfn_valid(pfn));
+
+ psPage = pfn_to_page(pfn);
+
+ result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
+ if (result != 0) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Error - VM_INSERT_PAGE failed (%d)",
+ __func__, result);
+ return IMG_FALSE;
+ }
+ ulVMAPos += PAGE_SIZE;
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+static IMG_BOOL CheckSize(struct LinuxMemArea *psLinuxMemArea, u32 ui32ByteSize)
+{
+ struct IMG_CPU_PHYADDR CpuPAddr;
+ u32 ui32PageAlignmentOffset;
+ u32 ui32RealByteSize;
+ CpuPAddr = LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0);
+ ui32PageAlignmentOffset = ADDR_TO_PAGE_OFFSET(CpuPAddr.uiAddr);
+ ui32RealByteSize =
+ PAGE_ALIGN(psLinuxMemArea->ui32ByteSize + ui32PageAlignmentOffset);
+ if (ui32RealByteSize < ui32ByteSize) {
+ PVR_DPF(PVR_DBG_ERROR, "Cannot mmap %ld bytes from: "
+ "%-8p %-8p %08lx %-8ld %-24s\n",
+ ui32ByteSize, psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0).uiAddr,
+ psLinuxMemArea->ui32ByteSize,
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType));
+ return IMG_FALSE;
+ }
+ return IMG_TRUE;
+}
+
+static void MMapVOpenNoLock(struct vm_area_struct *ps_vma)
+{
+ struct KV_OFFSET_STRUCT *psOffsetStruct =
+ (struct KV_OFFSET_STRUCT *)ps_vma->vm_private_data;
+
+ PVR_ASSERT(psOffsetStruct != NULL);
+ psOffsetStruct->ui32Mapped++;
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+
+ if (psOffsetStruct->ui32Mapped > 1) {
+ PVR_DPF(PVR_DBG_WARNING,
+ "%s: Offset structure 0x%p is being shared "
+ "across processes (psOffsetStruct->ui32Mapped: %lu)",
+ __func__, psOffsetStruct, psOffsetStruct->ui32Mapped);
+ PVR_ASSERT((ps_vma->vm_flags & VM_DONTCOPY) == 0);
+ }
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "%s: psLinuxMemArea 0x%p, KVAddress 0x%p MMapOffset %ld, ui32Mapped %d",
+ __func__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset, psOffsetStruct->ui32Mapped);
+#endif
+
+}
+
+static void MMapVOpen(struct vm_area_struct *ps_vma)
+{
+ mutex_lock(&g_sMMapMutex);
+ MMapVOpenNoLock(ps_vma);
+ mutex_unlock(&g_sMMapMutex);
+}
+
+static void MMapVCloseNoLock(struct vm_area_struct *ps_vma)
+{
+ struct KV_OFFSET_STRUCT *psOffsetStruct =
+ (struct KV_OFFSET_STRUCT *)ps_vma->vm_private_data;
+
+ PVR_ASSERT(psOffsetStruct != NULL);
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ PVR_DPF(PVR_DBG_MESSAGE, "%s: psLinuxMemArea "
+ "0x%p, CpuVAddr 0x%p ui32MMapOffset %ld, ui32Mapped %d",
+ __func__,
+ psOffsetStruct->psLinuxMemArea,
+ LinuxMemAreaToCpuVAddr(psOffsetStruct->psLinuxMemArea),
+ psOffsetStruct->ui32MMapOffset,
+ psOffsetStruct->ui32Mapped);
+#endif
+
+ PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+ psOffsetStruct->ui32Mapped--;
+ if (psOffsetStruct->ui32Mapped == 0) {
+ if (psOffsetStruct->ui32RefCount != 0)
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "%s: psOffsetStruct 0x%p has non-zero "
+ "reference count (ui32RefCount = %lu). "
+ "User mode address of start of mapping: 0x%lx",
+ __func__, psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->ui32UserVAddr);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+ ps_vma->vm_private_data = NULL;
+}
+
+static void MMapVClose(struct vm_area_struct *ps_vma)
+{
+ mutex_lock(&g_sMMapMutex);
+ MMapVCloseNoLock(ps_vma);
+ mutex_unlock(&g_sMMapMutex);
+}
+
+static struct vm_operations_struct MMapIOOps = {
+ .open = MMapVOpen,
+ .close = MMapVClose
+};
+
+int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma)
+{
+ u32 ui32ByteSize;
+ struct KV_OFFSET_STRUCT *psOffsetStruct = NULL;
+ int iRetVal = 0;
+
+ PVR_UNREFERENCED_PARAMETER(pFile);
+
+ mutex_lock(&g_sMMapMutex);
+
+ ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "%s: Received mmap(2) request with ui32MMapOffset 0x%08lx,"
+ " and ui32ByteSize %ld(0x%08lx)", __func__, ps_vma->vm_pgoff,
+ ui32ByteSize, ui32ByteSize);
+
+ if ((ps_vma->vm_flags & VM_WRITE) && !(ps_vma->vm_flags & VM_SHARED)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Cannot mmap non-shareable writable areas",
+ __func__);
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ psOffsetStruct =
+ FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+ if (psOffsetStruct == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Attempted to mmap unregistered area at vm_pgoff %ld",
+ __func__, ps_vma->vm_pgoff);
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+ list_del(&psOffsetStruct->sMMapItem);
+ psOffsetStruct->bOnMMapList = IMG_FALSE;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "%s: Mapped psLinuxMemArea 0x%p\n",
+ __func__, psOffsetStruct->psLinuxMemArea);
+
+ if (!CheckSize(psOffsetStruct->psLinuxMemArea, ui32ByteSize)) {
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ ps_vma->vm_flags |= VM_RESERVED;
+ ps_vma->vm_flags |= VM_IO;
+
+ ps_vma->vm_flags |= VM_DONTEXPAND;
+
+ ps_vma->vm_flags |= VM_DONTCOPY;
+
+ ps_vma->vm_private_data = (void *)psOffsetStruct;
+
+ switch (psOffsetStruct->psLinuxMemArea->
+ ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK) {
+ case PVRSRV_HAP_CACHED:
+
+ break;
+ case PVRSRV_HAP_WRITECOMBINE:
+ ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
+ break;
+ case PVRSRV_HAP_UNCACHED:
+ ps_vma->vm_page_prot = PGPROT_UC(ps_vma->vm_page_prot);
+ break;
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "%s: unknown cache type", __func__);
+ iRetVal = -EINVAL;
+ goto unlock_and_return;
+ }
+
+ ps_vma->vm_ops = &MMapIOOps;
+
+ if (!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0)) {
+ iRetVal = -EAGAIN;
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0);
+
+ psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
+
+ MMapVOpenNoLock(ps_vma);
+
+ PVR_DPF(PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
+ __func__, ps_vma->vm_pgoff);
+
+unlock_and_return:
+ if (iRetVal != 0 && psOffsetStruct != NULL)
+ DestroyOffsetStruct(psOffsetStruct);
+
+ mutex_unlock(&g_sMMapMutex);
+
+ return iRetVal;
+}
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+static off_t PrintMMapReg_helper(char *buffer, size_t size,
+ const struct KV_OFFSET_STRUCT *psOffsetStruct,
+ struct LinuxMemArea *psLinuxMemArea)
+{
+ off_t Ret;
+ u32 ui32RealByteSize;
+ u32 ui32ByteOffset;
+
+ PVR_ASSERT(psOffsetStruct->psLinuxMemArea == psLinuxMemArea);
+
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ &ui32RealByteSize,
+ &ui32ByteOffset);
+
+ Ret = printAppend(buffer, size, 0,
+ "%-8p %08x %-8p %08x %08x "
+ "%-8d %-24s %-5u %-8s %08x(%s)\n",
+ psLinuxMemArea,
+ psOffsetStruct->ui32UserVAddr + ui32ByteOffset,
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea),
+ LinuxMemAreaToCpuPAddr(psLinuxMemArea, 0).uiAddr,
+ psOffsetStruct->ui32MMapOffset,
+ psLinuxMemArea->ui32ByteSize,
+ LinuxMemAreaTypeToString(psLinuxMemArea->eAreaType),
+ psOffsetStruct->ui32PID,
+ psOffsetStruct->pszName,
+ psLinuxMemArea->ui32AreaFlags,
+ HAPFlagsToString(psLinuxMemArea->ui32AreaFlags));
+ return Ret;
+
+}
+
+static off_t PrintMMapRegistrations(char *buffer, size_t size, off_t off)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ off_t Ret;
+
+ mutex_lock(&g_sMMapMutex);
+
+ if (!off) {
+ Ret = printAppend(buffer, size, 0,
+ "Allocations registered for mmap: %u\n"
+ "In total these areas correspond to %u bytes\n"
+ "psLinuxMemArea UserVAddr KernelVAddr "
+ "CpuPAddr MMapOffset ByteLength "
+ "LinuxMemType "
+ "Pid Name Flags\n",
+ g_ui32RegisteredAreas, g_ui32TotalByteSize);
+
+ goto unlock_and_return;
+ }
+
+ if (size < 135) {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ PVR_ASSERT(off != 0);
+ list_for_each_entry(psLinuxMemArea, &g_sMMapAreaList, sMMapItem) {
+ struct KV_OFFSET_STRUCT *psOffsetStruct;
+
+ list_for_each_entry(psOffsetStruct,
+ &psLinuxMemArea->sMMapOffsetStructList,
+ sAreaItem) {
+ off--;
+ if (off == 0) {
+ Ret = PrintMMapReg_helper(buffer, size,
+ psOffsetStruct, psLinuxMemArea);
+ goto unlock_and_return;
+ }
+ }
+ }
+ Ret = END_OF_FILE;
+
+unlock_and_return:
+ mutex_unlock(&g_sMMapMutex);
+ return Ret;
+}
+#endif
+
+enum PVRSRV_ERROR PVRMMapRegisterArea(struct LinuxMemArea *psLinuxMemArea)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+#if defined(CONFIG_PVR_DEBUG) || defined(DEBUG_LINUX_MMAP_AREAS)
+ const char *pszName =
+ LinuxMemAreaTypeToString(LinuxMemAreaRootType(psLinuxMemArea));
+#endif
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "%s(%s, psLinuxMemArea 0x%p, ui32AllocFlags 0x%8lx)",
+ __func__, pszName, psLinuxMemArea,
+ psLinuxMemArea->ui32AreaFlags);
+
+ PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC
+ || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType !=
+ LINUX_MEM_AREA_SUB_ALLOC);
+
+ if (psLinuxMemArea->bMMapRegistered) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: psLinuxMemArea 0x%p is already registered",
+ __func__, psLinuxMemArea);
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit_unlock;
+ }
+
+ list_add_tail(&psLinuxMemArea->sMMapItem, &g_sMMapAreaList);
+
+ psLinuxMemArea->bMMapRegistered = IMG_TRUE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas++;
+
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRMMapRemoveRegisteredArea(
+ struct LinuxMemArea *psLinuxMemArea)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+ struct KV_OFFSET_STRUCT *psOffsetStruct, *psTmpOffsetStruct;
+
+ mutex_lock(&g_sMMapMutex);
+
+ PVR_ASSERT(psLinuxMemArea->bMMapRegistered);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct,
+ &psLinuxMemArea->sMMapOffsetStructList,
+ sAreaItem) {
+ if (psOffsetStruct->ui32Mapped != 0) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: psOffsetStruct "
+ "0x%p for memory area "
+ "0x0x%p is still mapped; "
+ "psOffsetStruct->ui32Mapped %lu",
+ __func__, psOffsetStruct, psLinuxMemArea,
+ psOffsetStruct->ui32Mapped);
+ eError = PVRSRV_ERROR_GENERIC;
+ goto exit_unlock;
+ } else {
+
+ PVR_DPF(PVR_DBG_WARNING,
+ "%s: psOffsetStruct 0x%p was never mapped",
+ __func__, psOffsetStruct);
+ }
+
+ PVR_ASSERT((psOffsetStruct->ui32Mapped == 0)
+ && psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+
+ list_del(&psLinuxMemArea->sMMapItem);
+
+ psLinuxMemArea->bMMapRegistered = IMG_FALSE;
+
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ g_ui32RegisteredAreas--;
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ g_ui32TotalByteSize -= psLinuxMemArea->ui32ByteSize;
+#endif
+
+ eError = PVRSRV_OK;
+
+exit_unlock:
+ mutex_unlock(&g_sMMapMutex);
+ return eError;
+}
+
+enum PVRSRV_ERROR LinuxMMapPerProcessConnect(struct PVRSRV_ENV_PER_PROCESS_DATA
+ *psEnvPerProc)
+{
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ return PVRSRV_OK;
+}
+
+void LinuxMMapPerProcessDisconnect(struct PVRSRV_ENV_PER_PROCESS_DATA
+ *psEnvPerProc)
+{
+ struct KV_OFFSET_STRUCT *psOffsetStruct, *psTmpOffsetStruct;
+ IMG_BOOL bWarn = IMG_FALSE;
+ u32 ui32PID = OSGetCurrentProcessIDKM();
+
+ PVR_UNREFERENCED_PARAMETER(psEnvPerProc);
+
+ mutex_lock(&g_sMMapMutex);
+
+ list_for_each_entry_safe(psOffsetStruct, psTmpOffsetStruct,
+ &g_sMMapOffsetStructList, sMMapItem) {
+ if (psOffsetStruct->ui32PID == ui32PID) {
+ if (!bWarn) {
+ PVR_DPF(PVR_DBG_WARNING, "%s: process has "
+ "unmapped offset structures. "
+ "Removing them",
+ __func__);
+ bWarn = IMG_TRUE;
+ }
+ PVR_ASSERT(psOffsetStruct->ui32Mapped == 0);
+ PVR_ASSERT(psOffsetStruct->bOnMMapList);
+
+ DestroyOffsetStruct(psOffsetStruct);
+ }
+ }
+
+ mutex_unlock(&g_sMMapMutex);
+}
+
+enum PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(struct PVRSRV_HANDLE_BASE
+ *psHandleBase)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ eError = PVRSRVSetMaxHandle(psHandleBase, MAX_MMAP_HANDLE);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: failed to set handle limit (%d)",
+ __func__, eError);
+ return eError;
+ }
+
+ return eError;
+}
+
+void PVRMMapInit(void)
+{
+ mutex_init(&g_sMMapMutex);
+
+ g_psMemmapCache =
+ kmem_cache_create("img-mmap", sizeof(struct KV_OFFSET_STRUCT),
+ 0, 0, NULL);
+ if (!g_psMemmapCache) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: failed to allocate kmem_cache",
+ __func__);
+ goto error;
+ }
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ CreateProcReadEntry("mmap", PrintMMapRegistrations);
+#endif
+
+ return;
+
+error:
+ PVRMMapCleanup();
+ return;
+}
+
+void PVRMMapCleanup(void)
+{
+ enum PVRSRV_ERROR eError;
+
+ if (!list_empty(&g_sMMapAreaList)) {
+ struct LinuxMemArea *psLinuxMemArea, *psTmpMemArea;
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Memory areas are still registered with MMap",
+ __func__);
+
+ PVR_TRACE("%s: Unregistering memory areas", __func__);
+ list_for_each_entry_safe(psLinuxMemArea, psTmpMemArea,
+ &g_sMMapAreaList, sMMapItem) {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: PVRMMapRemoveRegisteredArea failed (%d)",
+ __func__, eError);
+ PVR_ASSERT(eError == PVRSRV_OK);
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ }
+ }
+ PVR_ASSERT(list_empty((&g_sMMapAreaList)));
+
+ RemoveProcEntry("mmap");
+
+ if (g_psMemmapCache) {
+ kmem_cache_destroy(g_psMemmapCache);
+ g_psMemmapCache = NULL;
+ }
+}
diff --git a/drivers/gpu/pvr/mmap.h b/drivers/gpu/pvr/mmap.h
new file mode 100644
index 00000000000..3ab55ff8bc5
--- /dev/null
+++ b/drivers/gpu/pvr/mmap.h
@@ -0,0 +1,74 @@
+/**********************************************************************
+ *
+ * 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(__MMAP_H__)
+#define __MMAP_H__
+
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include "perproc.h"
+#include "mm.h"
+
+struct KV_OFFSET_STRUCT {
+ u32 ui32Mapped;
+ u32 ui32MMapOffset;
+ u32 ui32RealByteSize;
+ struct LinuxMemArea *psLinuxMemArea;
+ u32 ui32TID;
+ u32 ui32PID;
+ IMG_BOOL bOnMMapList;
+ u32 ui32RefCount;
+ u32 ui32UserVAddr;
+#if defined(DEBUG_LINUX_MMAP_AREAS)
+ const char *pszName;
+#endif
+ struct list_head sMMapItem;
+ struct list_head sAreaItem;
+};
+
+void PVRMMapInit(void);
+void PVRMMapCleanup(void);
+
+enum PVRSRV_ERROR PVRMMapRegisterArea(struct LinuxMemArea *psLinuxMemArea);
+
+enum PVRSRV_ERROR PVRMMapRemoveRegisteredArea(
+ struct LinuxMemArea *psLinuxMemArea);
+
+enum PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hMHandle, u32 *pui32MMapOffset,
+ u32 *pui32ByteOffset, u32 *pui32RealByteSize,
+ u32 *pui32UserVAddr);
+
+enum PVRSRV_ERROR PVRMMapReleaseMMapData(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hMHandle, IMG_BOOL *pbMUnmap,
+ u32 *pui32RealByteSize, u32 *pui32UserVAddr);
+
+int PVRMMap(struct file *pFile, struct vm_area_struct *ps_vma);
+
+#endif
diff --git a/drivers/gpu/pvr/mmu.c b/drivers/gpu/pvr/mmu.c
new file mode 100644
index 00000000000..7b9f0afbf3e
--- /dev/null
+++ b/drivers/gpu/pvr/mmu.c
@@ -0,0 +1,1439 @@
+/**********************************************************************
+ *
+ * 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 "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "hash.h"
+#include "ra.h"
+#include "pdump_km.h"
+#include "sgxapi_km.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "mmu.h"
+
+#define UINT32_MAX_VALUE 0xFFFFFFFFUL
+
+struct MMU_PT_INFO {
+ void *hPTPageOSMemHandle;
+ void *PTPageCpuVAddr;
+ u32 ui32ValidPTECount;
+};
+
+struct MMU_CONTEXT {
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ void *pvPDCpuVAddr;
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+ void *hPDOSMemHandle;
+ struct MMU_PT_INFO *apsPTInfoList[1024];
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ struct MMU_CONTEXT *psNext;
+};
+
+struct MMU_HEAP {
+ struct MMU_CONTEXT *psMMUContext;
+
+ u32 ui32PTBaseIndex;
+ u32 ui32PTPageCount;
+ u32 ui32PTEntryCount;
+
+ struct RA_ARENA *psVMArena;
+
+ struct DEV_ARENA_DESCRIPTOR *psDevArena;
+};
+
+
+#if defined(PDUMP)
+static void MMU_PDumpPageTables(struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR DevVAddr, size_t uSize,
+ IMG_BOOL bForUnmap, void *hUniqueTag);
+#endif
+
+#define PAGE_TEST 0
+
+
+void MMU_InvalidateDirectoryCache(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGX_BIF_INVALIDATE_PDCACHE;
+}
+
+static void MMU_InvalidatePageTableCache(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ psDevInfo->ui32CacheControl |= SGX_BIF_INVALIDATE_PTCACHE;
+}
+
+static IMG_BOOL _AllocPageTables(struct MMU_HEAP *pMMUHeap)
+{
+ PVR_DPF(PVR_DBG_MESSAGE, "_AllocPageTables()");
+
+ PVR_ASSERT(pMMUHeap != NULL);
+ PVR_ASSERT(HOST_PAGESIZE() == SGX_MMU_PAGE_SIZE);
+
+ if (pMMUHeap == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "_AllocPageTables: invalid parameter");
+ return IMG_FALSE;
+ }
+
+ pMMUHeap->ui32PTEntryCount =
+ pMMUHeap->psDevArena->ui32Size >> SGX_MMU_PAGE_SHIFT;
+
+ pMMUHeap->ui32PTBaseIndex =
+ (pMMUHeap->psDevArena->BaseDevVAddr.
+ uiAddr & (SGX_MMU_PD_MASK | SGX_MMU_PT_MASK)) >>
+ SGX_MMU_PAGE_SHIFT;
+
+ pMMUHeap->ui32PTPageCount =
+ (pMMUHeap->ui32PTEntryCount + SGX_MMU_PT_SIZE - 1) >>
+ SGX_MMU_PT_SHIFT;
+
+ return IMG_TRUE;
+}
+
+static void _DeferredFreePageTable(struct MMU_HEAP *pMMUHeap, u32 ui32PTIndex)
+{
+ u32 *pui32PDEntry;
+ u32 i;
+ u32 ui32PDIndex;
+ struct SYS_DATA *psSysData;
+ struct MMU_PT_INFO **ppsPTInfoList;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "_DeferredFreePageTables: "
+ "ERROR call to SysAcquireData failed");
+ return;
+ }
+
+ ui32PDIndex =
+ pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT);
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+ PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == NULL ||
+ ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount ==
+ 0);
+ }
+
+ PDUMPCOMMENT("Free page table (page count == %08X)",
+ pMMUHeap->ui32PTPageCount);
+ if (ppsPTInfoList[ui32PTIndex]
+ && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX,
+ ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+
+ switch (pMMUHeap->psDevArena->DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ struct MMU_CONTEXT *psMMUContext =
+ (struct MMU_CONTEXT *)
+ pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
+
+ while (psMMUContext) {
+ pui32PDEntry =
+ (u32 *) psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+ pui32PDEntry[ui32PTIndex] = 0;
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+ (void *) &
+ pui32PDEntry[ui32PTIndex],
+ sizeof(u32), 0, IMG_FALSE,
+ PDUMP_PT_UNIQUETAG,
+ PDUMP_PT_UNIQUETAG);
+ psMMUContext = psMMUContext->psNext;
+ }
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ {
+
+ pui32PDEntry =
+ (u32 *) pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+ pui32PDEntry[ui32PTIndex] = 0;
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+ (void *) &pui32PDEntry[ui32PTIndex],
+ sizeof(u32), 0, IMG_FALSE,
+ PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+ break;
+ }
+ default:
+ {
+ PVR_DPF(PVR_DBG_ERROR,
+ "_DeferredFreePagetable: ERROR invalid heap type");
+ return;
+ }
+ }
+
+ if (ppsPTInfoList[ui32PTIndex] != NULL) {
+ if (ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != NULL) {
+ u32 *pui32Tmp;
+
+ pui32Tmp =
+ (u32 *) ppsPTInfoList[ui32PTIndex]->
+ PTPageCpuVAddr;
+
+ for (i = 0;
+ (i < pMMUHeap->ui32PTEntryCount) && (i < 1024);
+ i++)
+ pui32Tmp[i] = 0;
+
+ if (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->
+ psLocalDevMemArena == NULL) {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ ppsPTInfoList[ui32PTIndex]->
+ PTPageCpuVAddr,
+ ppsPTInfoList[ui32PTIndex]->
+ hPTPageOSMemHandle);
+ } else {
+ struct IMG_SYS_PHYADDR sSysPAddr;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+
+ sCpuPAddr =
+ OSMapLinToCPUPhys(ppsPTInfoList
+ [ui32PTIndex]->
+ PTPageCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+ OSUnMapPhysToLin((void __force __iomem *)
+ ppsPTInfoList[ui32PTIndex]->
+ PTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY,
+ ppsPTInfoList[ui32PTIndex]->
+ hPTPageOSMemHandle);
+
+ RA_Free(pMMUHeap->psDevArena->
+ psDeviceMemoryHeapInfo->
+ psLocalDevMemArena,
+ sSysPAddr.uiAddr, IMG_FALSE);
+ }
+
+ pMMUHeap->ui32PTEntryCount -= i;
+ } else {
+ pMMUHeap->ui32PTEntryCount -= 1024;
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct MMU_PT_INFO),
+ ppsPTInfoList[ui32PTIndex], NULL);
+ ppsPTInfoList[ui32PTIndex] = NULL;
+ } else {
+ pMMUHeap->ui32PTEntryCount -= 1024;
+ }
+
+ PDUMPCOMMENT("Finished free page table (page count == %08X)",
+ pMMUHeap->ui32PTPageCount);
+}
+
+static void _DeferredFreePageTables(struct MMU_HEAP *pMMUHeap)
+{
+ u32 i;
+
+ for (i = 0; i < pMMUHeap->ui32PTPageCount; i++)
+ _DeferredFreePageTable(pMMUHeap, i);
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
+}
+
+static IMG_BOOL _DeferredAllocPagetables(struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR DevVAddr, u32 ui32Size)
+{
+ u32 ui32PTPageCount;
+ u32 ui32PDIndex;
+ u32 i;
+ u32 *pui32PDEntry;
+ struct MMU_PT_INFO **ppsPTInfoList;
+ struct SYS_DATA *psSysData;
+ struct IMG_DEV_VIRTADDR sHighDevVAddr;
+
+ PVR_ASSERT(DevVAddr.uiAddr < (1 << SGX_FEATURE_ADDRESS_SPACE_SIZE));
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return IMG_FALSE;
+
+ ui32PDIndex =
+ DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+ if ((UINT32_MAX_VALUE - DevVAddr.uiAddr) <
+ (ui32Size + (1 << (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT)) - 1)) {
+
+ sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
+ } else {
+ sHighDevVAddr.uiAddr = DevVAddr.uiAddr + ui32Size +
+ (1 << (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT)) - 1;
+ }
+
+ ui32PTPageCount =
+ sHighDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+ ui32PTPageCount -= ui32PDIndex;
+
+ pui32PDEntry = (u32 *) pMMUHeap->psMMUContext->pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ PDUMPCOMMENT("Alloc page table (page count == %08X)", ui32PTPageCount);
+ PDUMPCOMMENT("Page directory mods (page count == %08X)",
+ ui32PTPageCount);
+
+ for (i = 0; i < ui32PTPageCount; i++) {
+ if (ppsPTInfoList[i] == NULL) {
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct MMU_PT_INFO),
+ (void **) &ppsPTInfoList[i], NULL)
+ != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "_DeferredAllocPagetables: "
+ "ERROR call to OSAllocMem failed");
+ return IMG_FALSE;
+ }
+ OSMemSet(ppsPTInfoList[i], 0,
+ sizeof(struct MMU_PT_INFO));
+ }
+
+ if (ppsPTInfoList[i]->hPTPageOSMemHandle == NULL &&
+ ppsPTInfoList[i]->PTPageCpuVAddr == NULL) {
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+
+ PVR_ASSERT(pui32PDEntry[i] == 0);
+
+ if (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->
+ psLocalDevMemArena == NULL) {
+ if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ (void **)&ppsPTInfoList[i]->
+ PTPageCpuVAddr,
+ &ppsPTInfoList[i]->
+ hPTPageOSMemHandle) !=
+ PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "_DeferredAllocPagetables: "
+ "ERROR call to OSAllocPages failed");
+ return IMG_FALSE;
+ }
+
+ if (ppsPTInfoList[i]->PTPageCpuVAddr) {
+ sCpuPAddr =
+ OSMapLinToCPUPhys(ppsPTInfoList[i]->
+ PTPageCpuVAddr);
+ } else {
+ sCpuPAddr =
+ OSMemHandleToCpuPAddr(
+ ppsPTInfoList[i]->
+ hPTPageOSMemHandle,
+ 0);
+ }
+ sDevPAddr =
+ SysCpuPAddrToDevPAddr
+ (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ } else {
+ struct IMG_SYS_PHYADDR sSysPAddr;
+
+ if (RA_Alloc(pMMUHeap->psDevArena->
+ psDeviceMemoryHeapInfo->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE, NULL, 0,
+ SGX_MMU_PAGE_SIZE,
+ &(sSysPAddr.uiAddr)) != IMG_TRUE) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "_DeferredAllocPagetables: "
+ "ERROR call to RA_Alloc failed");
+ return IMG_FALSE;
+ }
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ ppsPTInfoList[i]->PTPageCpuVAddr =
+ (void __force *)
+ OSMapPhysToLin(sCpuPAddr, SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY,
+ &ppsPTInfoList[i]->
+ hPTPageOSMemHandle);
+ if (!ppsPTInfoList[i]->PTPageCpuVAddr) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "_DeferredAllocPagetables: "
+ "ERROR failed to map page tables");
+ return IMG_FALSE;
+ }
+
+ sDevPAddr = SysCpuPAddrToDevPAddr
+ (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+
+ }
+
+
+ OSMemSet(ppsPTInfoList[i]->PTPageCpuVAddr, 0,
+ SGX_MMU_PAGE_SIZE);
+
+ PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX,
+ ppsPTInfoList[i]->PTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PDUMP_PT_UNIQUETAG);
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+ ppsPTInfoList[i]->PTPageCpuVAddr,
+ SGX_MMU_PAGE_SIZE, 0, IMG_TRUE,
+ PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+ switch (pMMUHeap->psDevArena->DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ struct MMU_CONTEXT *psMMUContext =
+ (struct MMU_CONTEXT *)pMMUHeap->
+ psMMUContext->psDevInfo->
+ pvMMUContextList;
+
+ while (psMMUContext) {
+ pui32PDEntry =
+ (u32 *)psMMUContext->
+ pvPDCpuVAddr;
+ pui32PDEntry += ui32PDIndex;
+
+ pui32PDEntry[i] =
+ sDevPAddr.uiAddr |
+ SGX_MMU_PDE_VALID;
+
+ PDUMPMEM2
+ (PVRSRV_DEVICE_TYPE_SGX,
+ (void *)&pui32PDEntry[i],
+ sizeof(u32), 0,
+ IMG_FALSE,
+ PDUMP_PD_UNIQUETAG,
+ PDUMP_PT_UNIQUETAG);
+
+ psMMUContext =
+ psMMUContext->psNext;
+ }
+ break;
+ }
+ case DEVICE_MEMORY_HEAP_PERCONTEXT:
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ {
+ pui32PDEntry[i] = sDevPAddr.uiAddr |
+ SGX_MMU_PDE_VALID;
+
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+ (void *)&pui32PDEntry[i],
+ sizeof(u32), 0,
+ IMG_FALSE, PDUMP_PD_UNIQUETAG,
+ PDUMP_PT_UNIQUETAG);
+
+ break;
+ }
+ default:
+ {
+ PVR_DPF(PVR_DBG_ERROR,
+ "_DeferredAllocPagetables: "
+ "ERROR invalid heap type");
+ return IMG_FALSE;
+ }
+ }
+
+
+ MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->
+ psDevInfo);
+ } else {
+
+ PVR_ASSERT(pui32PDEntry[i] != 0);
+ }
+ }
+
+ return IMG_TRUE;
+}
+
+enum PVRSRV_ERROR MMU_Initialise(struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct MMU_CONTEXT **ppsMMUContext,
+ struct IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ u32 *pui32Tmp;
+ u32 i;
+ void *pvPDCpuVAddr;
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ struct MMU_CONTEXT *psMMUContext;
+ void *hPDOSMemHandle;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "MMU_Initialise");
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Initialise: ERROR call to SysAcquireData failed");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct MMU_CONTEXT), (void **) &psMMUContext, NULL)
+ != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Initialise: ERROR call to OSAllocMem failed");
+ return PVRSRV_ERROR_GENERIC;
+ }
+ OSMemSet(psMMUContext, 0, sizeof(struct MMU_CONTEXT));
+
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ psMMUContext->psDevInfo = psDevInfo;
+
+ psMMUContext->psDeviceNode = psDeviceNode;
+
+ if (psDeviceNode->psLocalDevMemArena == NULL) {
+ if (OSAllocPages
+ (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE, SGX_MMU_PAGE_SIZE, &pvPDCpuVAddr,
+ &hPDOSMemHandle) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: "
+ "ERROR call to OSAllocPages failed");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ if (pvPDCpuVAddr)
+ sCpuPAddr = OSMapLinToCPUPhys(pvPDCpuVAddr);
+ else
+ sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
+ sPDDevPAddr =
+ SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
+ } else {
+ struct IMG_SYS_PHYADDR sSysPAddr;
+
+ if (RA_Alloc(psDeviceNode->psLocalDevMemArena,
+ SGX_MMU_PAGE_SIZE, NULL, 0, SGX_MMU_PAGE_SIZE,
+ &(sSysPAddr.uiAddr)) != IMG_TRUE) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: "
+ "ERROR call to RA_Alloc failed");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
+ sPDDevPAddr =
+ SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
+ pvPDCpuVAddr = (void __force *)
+ OSMapPhysToLin(sCpuPAddr, SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY, &hPDOSMemHandle);
+ if (!pvPDCpuVAddr) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_Initialise: "
+ "ERROR failed to map page tables");
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ PDUMPCOMMENT("Alloc page directory");
+
+ PDUMPMALLOCPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr,
+ SGX_MMU_PAGE_SIZE, PDUMP_PD_UNIQUETAG);
+
+ if (pvPDCpuVAddr) {
+ pui32Tmp = (u32 *) pvPDCpuVAddr;
+ } else {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Initialise: pvPDCpuVAddr invalid");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ for (i = 0; i < SGX_MMU_PD_SIZE; i++)
+ pui32Tmp[i] = 0;
+
+ PDUMPCOMMENT("Page directory contents");
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0,
+ IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+ psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
+ psMMUContext->sPDDevPAddr = sPDDevPAddr;
+ psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
+
+ *ppsMMUContext = psMMUContext;
+
+ *psPDDevPAddr = sPDDevPAddr;
+
+ psMMUContext->psNext = (struct MMU_CONTEXT *)
+ psDevInfo->pvMMUContextList;
+ psDevInfo->pvMMUContextList = (void *) psMMUContext;
+
+
+ return PVRSRV_OK;
+}
+
+void MMU_Finalise(struct MMU_CONTEXT *psMMUContext)
+{
+ u32 *pui32Tmp, i;
+ struct SYS_DATA *psSysData;
+ struct MMU_CONTEXT **ppsMMUContext;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Finalise: ERROR call to SysAcquireData failed");
+ return;
+ }
+
+ PDUMPCOMMENT("Free page directory");
+ PDUMPFREEPAGETABLE(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->pvPDCpuVAddr,
+ SGX_MMU_PAGE_SIZE, PDUMP_PT_UNIQUETAG);
+
+ pui32Tmp = (u32 *) psMMUContext->pvPDCpuVAddr;
+
+ for (i = 0; i < SGX_MMU_PD_SIZE; i++)
+ pui32Tmp[i] = 0;
+
+ if (psMMUContext->psDeviceNode->psLocalDevMemArena == NULL) {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ SGX_MMU_PAGE_SIZE,
+ psMMUContext->pvPDCpuVAddr,
+ psMMUContext->hPDOSMemHandle);
+
+ } else {
+ struct IMG_SYS_PHYADDR sSysPAddr;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+
+ sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->pvPDCpuVAddr);
+ sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
+
+ OSUnMapPhysToLin((void __iomem __force *)
+ psMMUContext->pvPDCpuVAddr,
+ SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY,
+ psMMUContext->hPDOSMemHandle);
+
+ RA_Free(psMMUContext->psDeviceNode->psLocalDevMemArena,
+ sSysPAddr.uiAddr, IMG_FALSE);
+
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE, "MMU_Finalise");
+
+ ppsMMUContext =
+ (struct MMU_CONTEXT **) &psMMUContext->psDevInfo->pvMMUContextList;
+ while (*ppsMMUContext) {
+ if (*ppsMMUContext == psMMUContext) {
+
+ *ppsMMUContext = psMMUContext->psNext;
+ break;
+ }
+
+ ppsMMUContext = &((*ppsMMUContext)->psNext);
+ }
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_CONTEXT),
+ psMMUContext, NULL);
+}
+
+void MMU_InsertHeap(struct MMU_CONTEXT *psMMUContext,
+ struct MMU_HEAP *psMMUHeap)
+{
+ u32 *pui32PDCpuVAddr = (u32 *)psMMUContext->pvPDCpuVAddr;
+ u32 *pui32KernelPDCpuVAddr = (u32 *)
+ psMMUHeap->psMMUContext->pvPDCpuVAddr;
+ u32 ui32PDEntry;
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+
+ pui32PDCpuVAddr +=
+ psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT);
+ pui32KernelPDCpuVAddr +=
+ psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT);
+
+ PDUMPCOMMENT("Page directory shared heap range copy");
+
+ for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PTPageCount;
+ ui32PDEntry++) {
+
+ PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
+
+ pui32PDCpuVAddr[ui32PDEntry] =
+ pui32KernelPDCpuVAddr[ui32PDEntry];
+ if (pui32PDCpuVAddr[ui32PDEntry]) {
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+ (void *) &pui32PDCpuVAddr[ui32PDEntry],
+ sizeof(u32), 0, IMG_FALSE,
+ PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
+
+ bInvalidateDirectoryCache = IMG_TRUE;
+ }
+ }
+
+ if (bInvalidateDirectoryCache)
+ MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
+}
+
+static void MMU_UnmapPagesAndFreePTs(struct MMU_HEAP *psMMUHeap,
+ struct IMG_DEV_VIRTADDR sDevVAddr,
+ u32 ui32PageCount, void *hUniqueTag)
+{
+ u32 uPageSize = HOST_PAGESIZE();
+ struct IMG_DEV_VIRTADDR sTmpDevVAddr;
+ u32 i;
+ u32 ui32PDIndex;
+ u32 ui32PTIndex;
+ u32 *pui32Tmp;
+ IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for (i = 0; i < ui32PageCount; i++) {
+ struct MMU_PT_INFO **ppsPTInfoList;
+
+ ui32PDIndex =
+ sTmpDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT);
+
+ ppsPTInfoList =
+ &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ {
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & SGX_MMU_PT_MASK)
+ >> SGX_MMU_PAGE_SHIFT;
+
+ if (!ppsPTInfoList[0]) {
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "MMU_UnmapPagesAndFreePTs: "
+ "Invalid PT for alloc at VAddr:0x%08lX "
+ "(VaddrIni:0x%08lX AllocPage:%u) "
+ "PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,
+ i, ui32PDIndex, ui32PTIndex);
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+
+ continue;
+ }
+
+ pui32Tmp = (u32 *)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+ if (!pui32Tmp)
+ continue;
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID) {
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ } else {
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "MMU_UnmapPagesAndFreePTs: "
+ "Page is already invalid for alloc at "
+ "VAddr:0x%08lX "
+ "(VAddrIni:0x%08lX AllocPage:%u) "
+ "PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,
+ i, ui32PDIndex, ui32PTIndex);
+ }
+
+ PVR_ASSERT((s32)ppsPTInfoList[0]->ui32ValidPTECount >=
+ 0);
+ pui32Tmp[ui32PTIndex] = 0;
+ }
+
+ if (ppsPTInfoList[0]
+ && ppsPTInfoList[0]->ui32ValidPTECount == 0) {
+ _DeferredFreePageTable(psMMUHeap,
+ ui32PDIndex - (psMMUHeap->
+ ui32PTBaseIndex >>
+ SGX_MMU_PT_SHIFT));
+ bInvalidateDirectoryCache = IMG_TRUE;
+ }
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+ }
+
+ if (bInvalidateDirectoryCache) {
+ MMU_InvalidateDirectoryCache(psMMUHeap->psMMUContext->
+ psDevInfo);
+ } else {
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->
+ psDevInfo);
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(psMMUHeap, sDevVAddr, uPageSize * ui32PageCount,
+ IMG_TRUE, hUniqueTag);
+#endif
+}
+
+static void MMU_FreePageTables(void *pvMMUHeap, u32 ui32Start, u32 ui32End,
+ void *hUniqueTag)
+{
+ struct MMU_HEAP *pMMUHeap = (struct MMU_HEAP *)pvMMUHeap;
+ struct IMG_DEV_VIRTADDR Start;
+
+ Start.uiAddr = ui32Start;
+
+ MMU_UnmapPagesAndFreePTs(pMMUHeap, Start,
+ (ui32End - ui32Start) / SGX_MMU_PAGE_SIZE,
+ hUniqueTag);
+}
+
+struct MMU_HEAP *MMU_Create(struct MMU_CONTEXT *psMMUContext,
+ struct DEV_ARENA_DESCRIPTOR *psDevArena,
+ struct RA_ARENA **ppsVMArena)
+{
+ struct MMU_HEAP *pMMUHeap;
+ IMG_BOOL bRes;
+
+ PVR_ASSERT(psDevArena != NULL);
+
+ if (psDevArena == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_Create: invalid parameter");
+ return NULL;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct MMU_HEAP), (void **)&pMMUHeap, NULL)
+ != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Create: ERROR call to OSAllocMem failed");
+ return NULL;
+ }
+
+ pMMUHeap->psMMUContext = psMMUContext;
+ pMMUHeap->psDevArena = psDevArena;
+
+ bRes = _AllocPageTables(pMMUHeap);
+ if (!bRes) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Create: ERROR call to _AllocPageTables failed");
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_HEAP),
+ pMMUHeap, NULL);
+ return NULL;
+ }
+
+ pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
+ psDevArena->BaseDevVAddr.uiAddr,
+ psDevArena->ui32Size, NULL,
+ SGX_MMU_PAGE_SIZE, NULL, NULL,
+ MMU_FreePageTables, pMMUHeap);
+
+ if (pMMUHeap->psVMArena == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Create: ERROR call to RA_Create failed");
+ _DeferredFreePageTables(pMMUHeap);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_HEAP),
+ pMMUHeap, NULL);
+ return NULL;
+ }
+
+ *ppsVMArena = pMMUHeap->psVMArena;
+
+ return pMMUHeap;
+}
+
+void MMU_Delete(struct MMU_HEAP *pMMUHeap)
+{
+ if (pMMUHeap != NULL) {
+ PVR_DPF(PVR_DBG_MESSAGE, "MMU_Delete");
+
+ if (pMMUHeap->psVMArena)
+ RA_Delete(pMMUHeap->psVMArena);
+ _DeferredFreePageTables(pMMUHeap);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct MMU_HEAP),
+ pMMUHeap, NULL);
+ }
+}
+
+IMG_BOOL MMU_Alloc(struct MMU_HEAP *pMMUHeap, size_t uSize, u32 uFlags,
+ u32 uDevVAddrAlignment, struct IMG_DEV_VIRTADDR *psDevVAddr)
+{
+ IMG_BOOL bStatus;
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
+ uSize, uFlags, uDevVAddrAlignment);
+
+ if ((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0) {
+ bStatus = RA_Alloc(pMMUHeap->psVMArena, uSize, NULL, 0,
+ uDevVAddrAlignment, &(psDevVAddr->uiAddr));
+ if (!bStatus) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Alloc: RA_Alloc of VMArena failed");
+ return bStatus;
+ }
+ }
+
+ bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, uSize);
+
+
+ if (!bStatus) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Alloc: _DeferredAllocPagetables failed");
+ if ((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
+ RA_Free(pMMUHeap->psVMArena, psDevVAddr->uiAddr,
+ IMG_FALSE);
+ }
+
+ return bStatus;
+}
+
+void MMU_Free(struct MMU_HEAP *pMMUHeap, struct IMG_DEV_VIRTADDR DevVAddr,
+ u32 ui32Size)
+{
+ PVR_ASSERT(pMMUHeap != NULL);
+
+ if (pMMUHeap == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_Free: invalid parameter");
+ return;
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "MMU_Free: mmu=%08X, dev_vaddr=%08X", pMMUHeap,
+ DevVAddr.uiAddr);
+
+ if ((DevVAddr.uiAddr >= pMMUHeap->psDevArena->BaseDevVAddr.uiAddr) &&
+ (DevVAddr.uiAddr + ui32Size <=
+ pMMUHeap->psDevArena->BaseDevVAddr.uiAddr +
+ pMMUHeap->psDevArena->ui32Size)) {
+ RA_Free(pMMUHeap->psVMArena, DevVAddr.uiAddr, IMG_TRUE);
+ return;
+ }
+
+ BUG();
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_Free: Couldn't find DevVAddr %08X in a DevArena",
+ DevVAddr.uiAddr);
+}
+
+void MMU_Enable(struct MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+void MMU_Disable(struct MMU_HEAP *pMMUHeap)
+{
+ PVR_UNREFERENCED_PARAMETER(pMMUHeap);
+
+}
+
+#if defined(PDUMP)
+static void MMU_PDumpPageTables(struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR DevVAddr,
+ size_t uSize, IMG_BOOL bForUnmap, void *hUniqueTag)
+{
+ u32 ui32NumPTEntries;
+ u32 ui32PTIndex;
+ u32 *pui32PTEntry;
+
+ struct MMU_PT_INFO **ppsPTInfoList;
+ u32 ui32PDIndex;
+ u32 ui32PTDumpCount;
+
+ ui32NumPTEntries =
+ (uSize + SGX_MMU_PAGE_SIZE - 1) >> SGX_MMU_PAGE_SHIFT;
+
+ ui32PDIndex =
+ DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
+
+ ui32PTIndex = (DevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+ PDUMPCOMMENT("Page table mods (num entries == %08X) %s",
+ ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
+
+ while (ui32NumPTEntries > 0) {
+ struct MMU_PT_INFO *psPTInfo = *ppsPTInfoList++;
+
+ if (ui32NumPTEntries <= 1024 - ui32PTIndex)
+ ui32PTDumpCount = ui32NumPTEntries;
+ else
+ ui32PTDumpCount = 1024 - ui32PTIndex;
+
+ if (psPTInfo) {
+ pui32PTEntry = (u32 *)psPTInfo->PTPageCpuVAddr;
+ PDUMPMEM2(PVRSRV_DEVICE_TYPE_SGX,
+ (void *)&pui32PTEntry[ui32PTIndex],
+ ui32PTDumpCount * sizeof(u32), 0,
+ IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
+
+ ui32NumPTEntries -= ui32PTDumpCount;
+
+ ui32PTIndex = 0;
+ }
+
+ PDUMPCOMMENT("Finished page table mods %s",
+ bForUnmap ? "(for unmap)" : "");
+}
+#endif
+
+static void MMU_MapPage(struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR DevVAddr,
+ struct IMG_DEV_PHYADDR DevPAddr, u32 ui32MemFlags)
+{
+ u32 ui32Index;
+ u32 *pui32Tmp;
+ u32 ui32MMUFlags = 0;
+ struct MMU_PT_INFO **ppsPTInfoList;
+
+ if (((PVRSRV_MEM_READ | PVRSRV_MEM_WRITE) & ui32MemFlags) ==
+ (PVRSRV_MEM_READ | PVRSRV_MEM_WRITE))
+ ui32MMUFlags = 0;
+ else if (PVRSRV_MEM_READ & ui32MemFlags)
+ ui32MMUFlags |= SGX_MMU_PTE_READONLY;
+ else if (PVRSRV_MEM_WRITE & ui32MemFlags)
+ ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
+
+ if (PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
+ ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
+
+ if (PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
+ ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
+
+ ui32Index = DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+
+ ui32Index = (DevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+ pui32Tmp = (u32 *) ppsPTInfoList[0]->PTPageCpuVAddr;
+
+
+ if (pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID)
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_MapPage: "
+ "Page is already valid for alloc at "
+ "VAddr:0x%08lX PDIdx:%u PTIdx:%u",
+ DevVAddr.uiAddr,
+ DevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT), ui32Index);
+
+ PVR_ASSERT((pui32Tmp[ui32Index] & SGX_MMU_PTE_VALID) == 0);
+
+ ppsPTInfoList[0]->ui32ValidPTECount++;
+
+ pui32Tmp[ui32Index] = (DevPAddr.uiAddr & SGX_MMU_PTE_ADDR_MASK)
+ | SGX_MMU_PTE_VALID | ui32MMUFlags;
+}
+
+void MMU_MapScatter(struct MMU_HEAP *pMMUHeap, struct IMG_DEV_VIRTADDR DevVAddr,
+ struct IMG_SYS_PHYADDR *psSysAddr, size_t uSize,
+ u32 ui32MemFlags, void *hUniqueTag)
+{
+#if defined(PDUMP)
+ struct IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ u32 uCount, i;
+ struct IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_ASSERT(pMMUHeap != NULL);
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ for (i = 0, uCount = 0; uCount < uSize;
+ i++, uCount += SGX_MMU_PAGE_SIZE) {
+ struct IMG_SYS_PHYADDR sSysAddr;
+
+ sSysAddr = psSysAddr[i];
+
+ DevPAddr =
+ SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
+
+ MMU_MapPage(pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += SGX_MMU_PAGE_SIZE;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "MMU_MapScatter: "
+ "devVAddr=%08X, SysAddr=%08X, size=0x%x/0x%x",
+ DevVAddr.uiAddr, sSysAddr.uiAddr, uCount, uSize);
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE,
+ hUniqueTag);
+#endif
+}
+
+void MMU_MapPages(struct MMU_HEAP *pMMUHeap, struct IMG_DEV_VIRTADDR DevVAddr,
+ struct IMG_SYS_PHYADDR SysPAddr, size_t uSize,
+ u32 ui32MemFlags, void *hUniqueTag)
+{
+ struct IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+ struct IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif
+ u32 uCount;
+ u32 ui32VAdvance = SGX_MMU_PAGE_SIZE;
+ u32 ui32PAdvance = SGX_MMU_PAGE_SIZE;
+
+ PVR_ASSERT(pMMUHeap != NULL);
+
+ PVR_DPF(PVR_DBG_MESSAGE, "MMU_MapPages: "
+ "mmu=%08X, devVAddr=%08X, SysPAddr=%08X, size=0x%x",
+ pMMUHeap, DevVAddr.uiAddr, SysPAddr.uiAddr, uSize);
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+ if (ui32MemFlags & PVRSRV_MEM_DUMMY)
+ ui32PAdvance = 0;
+
+ for (uCount = 0; uCount < uSize; uCount += ui32VAdvance) {
+ MMU_MapPage(pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += ui32VAdvance;
+ DevPAddr.uiAddr += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE,
+ hUniqueTag);
+#endif
+}
+
+void MMU_MapShadow(struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ size_t uByteSize, void *CpuVAddr, void *hOSMemHandle,
+ struct IMG_DEV_VIRTADDR *pDevVAddr, u32 ui32MemFlags,
+ void *hUniqueTag)
+{
+ u32 i;
+ u32 uOffset = 0;
+ struct IMG_DEV_VIRTADDR MapDevVAddr;
+ u32 ui32VAdvance = SGX_MMU_PAGE_SIZE;
+ u32 ui32PAdvance = SGX_MMU_PAGE_SIZE;
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "MMU_MapShadow: %08X, 0x%x, %08X",
+ MapBaseDevVAddr.uiAddr, uByteSize, CpuVAddr);
+
+ PVR_ASSERT(((u32) CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+ PVR_ASSERT(((u32) uByteSize & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+ pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+ if (ui32MemFlags & PVRSRV_MEM_DUMMY)
+ ui32PAdvance = 0;
+
+ MapDevVAddr = MapBaseDevVAddr;
+ for (i = 0; i < uByteSize; i += ui32VAdvance) {
+ struct IMG_CPU_PHYADDR CpuPAddr;
+ struct IMG_DEV_PHYADDR DevPAddr;
+
+ if (CpuVAddr)
+ CpuPAddr =
+ OSMapLinToCPUPhys((void *)((u32)CpuVAddr +
+ uOffset));
+ else
+ CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+ DevPAddr =
+ SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+ PVR_DPF(PVR_DBG_MESSAGE, "0x%x: CpuVAddr=%08X, "
+ "CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+ uOffset, (u32)CpuVAddr + uOffset, CpuPAddr.uiAddr,
+ MapDevVAddr.uiAddr, DevPAddr.uiAddr);
+
+ MMU_MapPage(pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+
+ MapDevVAddr.uiAddr += ui32VAdvance;
+ uOffset += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE,
+ hUniqueTag);
+#endif
+}
+
+void MMU_UnmapPages(struct MMU_HEAP *psMMUHeap,
+ struct IMG_DEV_VIRTADDR sDevVAddr, u32 ui32PageCount,
+ void *hUniqueTag)
+{
+ u32 uPageSize = HOST_PAGESIZE();
+ struct IMG_DEV_VIRTADDR sTmpDevVAddr;
+ u32 i;
+ u32 ui32PDIndex;
+ u32 ui32PTIndex;
+ u32 *pui32Tmp;
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ sTmpDevVAddr = sDevVAddr;
+
+ for (i = 0; i < ui32PageCount; i++) {
+ struct MMU_PT_INFO **ppsPTInfoList;
+
+ ui32PDIndex = sTmpDevVAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT);
+
+ ppsPTInfoList = &psMMUHeap->psMMUContext->
+ apsPTInfoList[ui32PDIndex];
+
+ ui32PTIndex = (sTmpDevVAddr.uiAddr & SGX_MMU_PT_MASK) >>
+ SGX_MMU_PAGE_SHIFT;
+
+ if (!ppsPTInfoList[0]) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_UnmapPages: "
+ "ERROR Invalid PT for alloc at VAddr:0x%08lX "
+ "(VaddrIni:0x%08lX AllocPage:%u) PDIdx:%u "
+ "PTIdx:%u",
+ sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr, i,
+ ui32PDIndex, ui32PTIndex);
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+
+ continue;
+ }
+
+ pui32Tmp = (u32 *)ppsPTInfoList[0]->PTPageCpuVAddr;
+
+ if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
+ ppsPTInfoList[0]->ui32ValidPTECount--;
+ else
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_UnmapPages: Page is already invalid "
+ "for alloc at VAddr:0x%08lX "
+ "(VAddrIni:0x%08lX AllocPage:%u) "
+ "PDIdx:%u PTIdx:%u",
+ sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr, i,
+ ui32PDIndex, ui32PTIndex);
+
+ PVR_ASSERT((s32) ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+
+ pui32Tmp[ui32PTIndex] = 0;
+
+ sTmpDevVAddr.uiAddr += uPageSize;
+ }
+
+ MMU_InvalidatePageTableCache(psMMUHeap->psMMUContext->psDevInfo);
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables(psMMUHeap, sDevVAddr, uPageSize * ui32PageCount,
+ IMG_TRUE, hUniqueTag);
+#endif
+}
+
+struct IMG_DEV_PHYADDR MMU_GetPhysPageAddr(struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR sDevVPageAddr)
+{
+ u32 *pui32PageTable;
+ u32 ui32Index;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ struct MMU_PT_INFO **ppsPTInfoList;
+
+ ui32Index = sDevVPageAddr.uiAddr >> (SGX_MMU_PAGE_SHIFT +
+ SGX_MMU_PT_SHIFT);
+
+ ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
+ if (!ppsPTInfoList[0]) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_GetPhysPageAddr: Not mapped in at 0x%08x",
+ sDevVPageAddr.uiAddr);
+ sDevPAddr.uiAddr = 0;
+ return sDevPAddr;
+ }
+
+ ui32Index =
+ (sDevVPageAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+ pui32PageTable = (u32 *) ppsPTInfoList[0]->PTPageCpuVAddr;
+
+ sDevPAddr.uiAddr = pui32PageTable[ui32Index];
+
+ sDevPAddr.uiAddr &= SGX_MMU_PTE_ADDR_MASK;
+
+ return sDevPAddr;
+}
+
+struct IMG_DEV_PHYADDR MMU_GetPDDevPAddr(struct MMU_CONTEXT *pMMUContext)
+{
+ return pMMUContext->sPDDevPAddr;
+}
+
+enum PVRSRV_ERROR SGXGetPhysPageAddrKM(void *hDevMemHeap,
+ struct IMG_DEV_VIRTADDR sDevVAddr,
+ struct IMG_DEV_PHYADDR *pDevPAddr,
+ struct IMG_CPU_PHYADDR *pCpuPAddr)
+{
+ struct MMU_HEAP *pMMUHeap;
+ struct IMG_DEV_PHYADDR DevPAddr;
+
+ pMMUHeap = (struct MMU_HEAP *)BM_GetMMUHeap(hDevMemHeap);
+
+ DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
+ pCpuPAddr->uiAddr = DevPAddr.uiAddr;
+ pDevPAddr->uiAddr = DevPAddr.uiAddr;
+
+ return (pDevPAddr->uiAddr != 0) ?
+ PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+enum PVRSRV_ERROR SGXGetMMUPDAddrKM(void *hDevCookie,
+ void *hDevMemContext,
+ struct IMG_DEV_PHYADDR *psPDDevPAddr)
+{
+ if (!hDevCookie || !hDevMemContext || !psPDDevPAddr)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ *psPDDevPAddr =
+ ((struct BM_CONTEXT *)hDevMemContext)->psMMUContext->sPDDevPAddr;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR MMU_BIFResetPDAlloc(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct RA_ARENA *psLocalDevMemArena;
+ void *hOSMemHandle = NULL;
+ u8 *pui8MemBlock = NULL;
+ struct IMG_SYS_PHYADDR sMemBlockSysPAddr;
+ struct IMG_CPU_PHYADDR sMemBlockCpuPAddr;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MMU_BIFResetPDAlloc: ERROR call to SysAcquireData failed");
+ return eError;
+ }
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+ if (psLocalDevMemArena == NULL) {
+
+ eError =
+ OSAllocPages(PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY, 3 * SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE, (void **)&pui8MemBlock,
+ &hOSMemHandle);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: "
+ "ERROR call to OSAllocPages failed");
+ return eError;
+ }
+ sMemBlockCpuPAddr = OSMapLinToCPUPhys(pui8MemBlock);
+ } else {
+ if (RA_Alloc(psLocalDevMemArena, 3 * SGX_MMU_PAGE_SIZE,
+ NULL, 0, SGX_MMU_PAGE_SIZE,
+ &(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: "
+ "ERROR call to RA_Alloc failed");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
+ pui8MemBlock = (void __force *)OSMapPhysToLin(sMemBlockCpuPAddr,
+ SGX_MMU_PAGE_SIZE * 3,
+ PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY,
+ &hOSMemHandle);
+ if (!pui8MemBlock) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: "
+ "ERROR failed to map page tables");
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+
+ psDevInfo->hBIFResetPDOSMemHandle = hOSMemHandle;
+ psDevInfo->sBIFResetPDDevPAddr =
+ SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
+ psDevInfo->sBIFResetPTDevPAddr.uiAddr =
+ psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ psDevInfo->sBIFResetPageDevPAddr.uiAddr =
+ psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ psDevInfo->pui32BIFResetPD = (u32 *) pui8MemBlock;
+ psDevInfo->pui32BIFResetPT =
+ (u32 *) (pui8MemBlock + SGX_MMU_PAGE_SIZE);
+
+ OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
+ OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
+
+ OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB,
+ SGX_MMU_PAGE_SIZE);
+
+ return PVRSRV_OK;
+}
+
+void MMU_BIFResetPDFree(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct RA_ARENA *psLocalDevMemArena;
+ struct IMG_SYS_PHYADDR sPDSysPAddr;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "MMU_BIFResetPDFree: "
+ "ERROR call to SysAcquireData failed");
+ return;
+ }
+
+ psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+
+ if (psLocalDevMemArena == NULL) {
+ OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
+ 3 * SGX_MMU_PAGE_SIZE,
+ psDevInfo->pui32BIFResetPD,
+ psDevInfo->hBIFResetPDOSMemHandle);
+ } else {
+ OSUnMapPhysToLin((void __force __iomem *)
+ psDevInfo->pui32BIFResetPD,
+ 3 * SGX_MMU_PAGE_SIZE,
+ PVRSRV_HAP_WRITECOMBINE |
+ PVRSRV_HAP_KERNEL_ONLY,
+ psDevInfo->hBIFResetPDOSMemHandle);
+
+ sPDSysPAddr =
+ SysDevPAddrToSysPAddr(PVRSRV_DEVICE_TYPE_SGX,
+ psDevInfo->sBIFResetPDDevPAddr);
+ RA_Free(psLocalDevMemArena, sPDSysPAddr.uiAddr, IMG_FALSE);
+ }
+}
+
+u32 mmu_get_page_dir(struct MMU_CONTEXT *psMMUContext)
+{
+ return psMMUContext->sPDDevPAddr.uiAddr;
+}
diff --git a/drivers/gpu/pvr/mmu.h b/drivers/gpu/pvr/mmu.h
new file mode 100644
index 00000000000..003f0c56000
--- /dev/null
+++ b/drivers/gpu/pvr/mmu.h
@@ -0,0 +1,86 @@
+/**********************************************************************
+ *
+ * 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 _MMU_H_
+#define _MMU_H_
+
+#include "sgxinfokm.h"
+
+enum PVRSRV_ERROR MMU_Initialise(struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct MMU_CONTEXT **ppsMMUContext,
+ struct IMG_DEV_PHYADDR *psPDDevPAddr);
+
+void MMU_Finalise(struct MMU_CONTEXT *psMMUContext);
+
+void MMU_InsertHeap(struct MMU_CONTEXT *psMMUContext,
+ struct MMU_HEAP *psMMUHeap);
+
+struct MMU_HEAP *MMU_Create(struct MMU_CONTEXT *psMMUContext,
+ struct DEV_ARENA_DESCRIPTOR *psDevArena,
+ struct RA_ARENA **ppsVMArena);
+
+void MMU_Delete(struct MMU_HEAP *pMMU);
+
+IMG_BOOL MMU_Alloc(struct MMU_HEAP *pMMU, size_t uSize, u32 uFlags,
+ u32 uDevVAddrAlignment, struct IMG_DEV_VIRTADDR *pDevVAddr);
+
+void MMU_Free(struct MMU_HEAP *pMMU, struct IMG_DEV_VIRTADDR DevVAddr,
+ u32 ui32Size);
+
+void MMU_Enable(struct MMU_HEAP *pMMU);
+
+void MMU_Disable(struct MMU_HEAP *pMMU);
+
+void MMU_MapPages(struct MMU_HEAP *pMMU, struct IMG_DEV_VIRTADDR devVAddr,
+ struct IMG_SYS_PHYADDR SysPAddr, size_t uSize, u32 ui32MemFlags,
+ void *hUniqueTag);
+
+void MMU_MapShadow(struct MMU_HEAP *pMMU,
+ struct IMG_DEV_VIRTADDR MapBaseDevVAddr, size_t uSize,
+ void *CpuVAddr, void *hOSMemHandle,
+ struct IMG_DEV_VIRTADDR *pDevVAddr, u32 ui32MemFlags,
+ void *hUniqueTag);
+
+void MMU_UnmapPages(struct MMU_HEAP *pMMU, struct IMG_DEV_VIRTADDR dev_vaddr,
+ u32 ui32PageCount, void *hUniqueTag);
+
+void MMU_MapScatter(struct MMU_HEAP *pMMU, struct IMG_DEV_VIRTADDR DevVAddr,
+ struct IMG_SYS_PHYADDR *psSysAddr, size_t uSize,
+ u32 ui32MemFlags, void *hUniqueTag);
+
+struct IMG_DEV_PHYADDR MMU_GetPhysPageAddr(struct MMU_HEAP *pMMUHeap,
+ struct IMG_DEV_VIRTADDR sDevVPageAddr);
+
+struct IMG_DEV_PHYADDR MMU_GetPDDevPAddr(struct MMU_CONTEXT *pMMUContext);
+
+void MMU_InvalidateDirectoryCache(struct PVRSRV_SGXDEV_INFO *psDevInfo);
+
+enum PVRSRV_ERROR MMU_BIFResetPDAlloc(struct PVRSRV_SGXDEV_INFO *psDevInfo);
+
+void MMU_BIFResetPDFree(struct PVRSRV_SGXDEV_INFO *psDevInfo);
+
+u32 mmu_get_page_dir(struct MMU_CONTEXT *pMMUContext);
+#endif
diff --git a/drivers/gpu/pvr/module.c b/drivers/gpu/pvr/module.c
new file mode 100644
index 00000000000..d94efe6a1fe
--- /dev/null
+++ b/drivers/gpu/pvr/module.c
@@ -0,0 +1,294 @@
+/**********************************************************************
+ *
+ * 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 <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+
+#include <linux/platform_device.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "kerneldisplay.h"
+#include "kernelbuffer.h"
+#include "syscommon.h"
+#include "pvrmmap.h"
+#include "mutils.h"
+#include "mm.h"
+#include "mmap.h"
+#include "pvr_debug.h"
+#include "srvkm.h"
+#include "perproc.h"
+#include "handle.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "proc.h"
+#include "pvrmodule.h"
+#include "private_data.h"
+#include "pvr_events.h"
+
+#define DRVNAME "pvrsrvkm"
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+static int debug = DBGPRIV_WARNING;
+#include <linux/moduleparam.h>
+module_param(debug, int, 0);
+#endif
+
+static int pvr_open(struct inode unref__ * inode, struct file *filp)
+{
+ struct PVRSRV_FILE_PRIVATE_DATA *priv;
+ void *block_alloc;
+ int ret = -ENOMEM;
+ enum PVRSRV_ERROR err;
+ u32 pid;
+
+ pvr_lock();
+
+ if (pvr_is_disabled()) {
+ ret = -ENODEV;
+ goto err_unlock;
+ }
+
+ pid = OSGetCurrentProcessIDKM();
+
+ if (PVRSRVProcessConnect(pid) != PVRSRV_OK)
+ goto err_unlock;
+
+ err = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*priv),
+ (void **)&priv, &block_alloc);
+
+ if (err != PVRSRV_OK)
+ goto err_unlock;
+
+ priv->ui32OpenPID = pid;
+ priv->hBlockAlloc = block_alloc;
+ filp->private_data = priv;
+
+ INIT_LIST_HEAD(&priv->event_list);
+ init_waitqueue_head(&priv->event_wait);
+ priv->event_space = 4096; /* set aside 4k for event buffer */
+
+ ret = 0;
+err_unlock:
+ pvr_unlock();
+
+ return ret;
+}
+
+static int pvr_release(struct inode unref__ * inode, struct file *filp)
+{
+ struct PVRSRV_FILE_PRIVATE_DATA *priv;
+
+ pvr_lock();
+
+ priv = filp->private_data;
+
+ pvr_release_events(priv);
+
+ PVRSRVProcessDisconnect(priv->ui32OpenPID);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*priv),
+ priv, priv->hBlockAlloc);
+
+ pvr_unlock();
+
+ return 0;
+}
+
+static const struct file_operations pvr_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = PVRSRV_BridgeDispatchKM,
+ .open = pvr_open,
+ .release = pvr_release,
+ .mmap = PVRMMap,
+ .poll = pvr_poll,
+ .read = pvr_read,
+};
+
+static void pvr_shutdown(struct platform_device *pdev)
+{
+ PVR_TRACE("pvr_shutdown(pdev=%p)", pdev);
+
+ (void)PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D3);
+}
+
+static int pvr_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ PVR_TRACE("pvr_suspend(pdev=%p)", pdev);
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D3) != PVRSRV_OK)
+ return -EINVAL;
+ return 0;
+}
+
+static int pvr_resume(struct platform_device *pdev)
+{
+ PVR_TRACE("pvr_resume(pdev=%p)", pdev);
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_POWER_STATE_D0) != PVRSRV_OK)
+ return -EINVAL;
+ return 0;
+}
+
+static struct miscdevice pvr_miscdevice = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DRVNAME,
+ .fops = &pvr_fops,
+};
+
+static int __devinit pvr_probe(struct platform_device *pdev)
+{
+ struct SYS_DATA *sysdata;
+ int ret;
+
+ PVR_TRACE("pvr_probe(pdev=%p)", pdev);
+
+ if (SysAcquireData(&sysdata) != PVRSRV_OK &&
+ SysInitialise(pdev) != PVRSRV_OK) {
+ ret = -ENODEV;
+ goto err_exit;
+ }
+
+ ret = misc_register(&pvr_miscdevice);
+ if (ret < 0)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ dev_err(&pdev->dev, "probe failed (%d)\n", ret);
+
+ return ret;
+}
+
+static int __devexit pvr_remove(struct platform_device *pdev)
+{
+ struct SYS_DATA *sysdata;
+ int ret;
+
+ PVR_TRACE("pvr_remove(pdev=%p)", pdev);
+
+ ret = misc_deregister(&pvr_miscdevice);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "remove failed (%d)\n", ret);
+ return ret;
+ }
+
+ if (SysAcquireData(&sysdata) == PVRSRV_OK)
+ SysDeinitialise(sysdata);
+
+ return 0;
+}
+
+
+static struct platform_driver pvr_driver = {
+ .driver = {
+ .name = DRVNAME,
+ },
+ .probe = pvr_probe,
+ .remove = __devexit_p(pvr_remove),
+ .suspend = pvr_suspend,
+ .resume = pvr_resume,
+ .shutdown = pvr_shutdown,
+};
+
+static int __init pvr_init(void)
+{
+ int error;
+
+ pvr_dbg_init();
+
+ PVR_TRACE("pvr_init");
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+ PVRDebugSetLevel(debug);
+#endif
+
+ error = CreateProcEntries();
+ if (error < 0)
+ goto err1;
+
+ error = -ENOMEM;
+ if (LinuxMMInit() != PVRSRV_OK)
+ goto err2;
+
+ if (LinuxBridgeInit() != PVRSRV_OK)
+ goto err3;
+
+ PVRMMapInit();
+
+ error = platform_driver_register(&pvr_driver);
+ if (error < 0)
+ goto err4;
+
+ pvr_init_events();
+
+ return 0;
+
+err4:
+ PVRMMapCleanup();
+ LinuxBridgeDeInit();
+err3:
+ LinuxMMCleanup();
+err2:
+ RemoveProcEntries();
+err1:
+ pr_err("%s: failed (%d)\n", __func__, error);
+
+ return error;
+}
+
+static void __exit pvr_cleanup(void)
+{
+ PVR_TRACE("pvr_cleanup");
+
+ pvr_exit_events();
+
+ platform_driver_unregister(&pvr_driver);
+
+ PVRMMapCleanup();
+ LinuxMMCleanup();
+ LinuxBridgeDeInit();
+ RemoveProcEntries();
+
+ PVR_TRACE("pvr_cleanup: unloading");
+
+ pvr_dbg_cleanup();
+}
+
+module_init(pvr_init);
+module_exit(pvr_cleanup);
+
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+MODULE_ALIAS("platform:" DRVNAME);
+
diff --git a/drivers/gpu/pvr/mutils.h b/drivers/gpu/pvr/mutils.h
new file mode 100644
index 00000000000..47279ec6b5d
--- /dev/null
+++ b/drivers/gpu/pvr/mutils.h
@@ -0,0 +1,37 @@
+/**********************************************************************
+ *
+ * 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 __IMG_LINUX_MUTILS_H__
+#define __IMG_LINUX_MUTILS_H__
+
+#define PGPROT_WC(pv) pgprot_writecombine(pv)
+#define PGPROT_UC(pv) pgprot_noncached(pv)
+
+#define IOREMAP(pa, bytes) ioremap_cached(pa, bytes)
+#define IOREMAP_WC(pa, bytes) ioremap_wc(pa, bytes)
+#define IOREMAP_UC(pa, bytes) ioremap_nocache(pa, bytes)
+
+#endif
diff --git a/drivers/gpu/pvr/ocpdefs.h b/drivers/gpu/pvr/ocpdefs.h
new file mode 100644
index 00000000000..12c3b365e01
--- /dev/null
+++ b/drivers/gpu/pvr/ocpdefs.h
@@ -0,0 +1,294 @@
+/****************************************************************************
+ Name : ocpdefs.h
+ Author : PowerVR
+ Copyright : 2009 by Imagination Technologies Limited.
+ All rights reserved. No part of this software, either
+ material or conceptual may be copied or distributed,
+ transmitted, transcribed, stored in a retrieval system or
+ translated into any human or computer language in any form
+ by any means, electronic, mechanical, manual or otherwise,
+ or disclosed to third parties without the express written
+ permission of Imagination Technologies Limited,
+ Home Park Estate, Kings Langley, Hertfordshire,
+ WD4 8LZ, U.K.
+ Description :
+
+ Program Type :
+
+ Modifications :
+
+****************************************************************************/
+
+#ifndef _OCPDEFS_H_
+#define _OCPDEFS_H_
+
+#include "sysconfig.h"
+
+#define SYS_OMAP3430_OCP_REGS_SYS_PHYS_BASE \
+ (SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE + EUR_CR_OCP_REVISION)
+#define SYS_OMAP3430_OCP_REGS_SIZE 0x110
+
+/* Register EUR_CR_OCP_REVISION */
+#define EUR_CR_OCP_REVISION 0xFE00
+#define EUR_CR_OCP_REVISION_REV_MASK 0xFFFFFFFFUL
+#define EUR_CR_OCP_REVISION_REV_SHIFT 0
+#define EUR_CR_OCP_REVISION_REV_SIGNED 0
+
+/* Register EUR_CR_OCP_HWINFO */
+#define EUR_CR_OCP_HWINFO 0xFE04
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_MASK 0x00000003UL
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SHIFT 0
+#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SIGNED 0
+
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_MASK 0x00000004UL
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SHIFT 2
+#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SIGNED 0
+
+/* Register EUR_CR_OCP_SYSCONFIG */
+#define EUR_CR_OCP_SYSCONFIG 0xFE10
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_MASK 0x0000000CUL
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SHIFT 2
+#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SIGNED 0
+
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_MASK 0x00000030UL
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SHIFT 4
+#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_0 */
+#define EUR_CR_OCP_IRQSTATUS_RAW_0 0xFE24
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_1 */
+#define EUR_CR_OCP_IRQSTATUS_RAW_1 0xFE28
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_2 */
+#define EUR_CR_OCP_IRQSTATUS_RAW_2 0xFE2C
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_0 */
+#define EUR_CR_OCP_IRQSTATUS_0 0xFE30
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_0_INIT_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_1 */
+#define EUR_CR_OCP_IRQSTATUS_1 0xFE34
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQSTATUS_2 */
+#define EUR_CR_OCP_IRQSTATUS_2 0xFE38
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_SET_0 */
+#define EUR_CR_OCP_IRQENABLE_SET_0 0xFE3C
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_SET_1 */
+#define EUR_CR_OCP_IRQENABLE_SET_1 0xFE40
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_SET_2 */
+#define EUR_CR_OCP_IRQENABLE_SET_2 0xFE44
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_CLR_0 */
+#define EUR_CR_OCP_IRQENABLE_CLR_0 0xFE48
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_CLR_1 */
+#define EUR_CR_OCP_IRQENABLE_CLR_1 0xFE4C
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SIGNED 0
+
+/* Register EUR_CR_OCP_IRQENABLE_CLR_2 */
+#define EUR_CR_OCP_IRQENABLE_CLR_2 0xFE50
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_MASK 0x00000001UL
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SHIFT 0
+#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SIGNED 0
+
+/* Register EUR_CR_OCP_PAGE_CONFIG */
+#define EUR_CR_OCP_PAGE_CONFIG 0xFF00
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_MASK 0x00000001UL
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SHIFT 0
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SIGNED 0
+
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_MASK 0x00000004UL
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_SHIFT 2
+#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_CHECK_ENABLE_SIGNED 0
+
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_MASK 0x00000018UL
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SHIFT 3
+#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SIGNED 0
+
+/* Register EUR_CR_OCP_INTERRUPT_EVENT */
+#define EUR_CR_OCP_INTERRUPT_EVENT 0xFF04
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_MASK 0x00000001UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SHIFT 0
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_MASK 0x00000002UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_SHIFT 1
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNUSED_TAG_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_MASK 0x00000004UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_SHIFT 2
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_MASK 0x00000008UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_SHIFT 3
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_PAGE_CROSS_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_MASK 0x00000010UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_SHIFT 4
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_READ_TAG_FIFO_OVR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_MASK 0x00000020UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_SHIFT 5
+#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_MEM_REQ_FIFO_OVR_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_MASK 0x00000100UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_SHIFT 8
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_RESP_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_MASK 0x00000200UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_SHIFT 9
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_CMD_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_MASK 0x00000400UL
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SHIFT 10
+#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SIGNED 0
+
+/* Register EUR_CR_OCP_DEBUG_CONFIG */
+#define EUR_CR_OCP_DEBUG_CONFIG 0xFF08
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_MASK 0x00000003UL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SHIFT 0
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_MASK 0x0000000CUL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_SHIFT 2
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_INIT_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_MASK 0x00000010UL
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_SHIFT 4
+#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_PASS_DATA_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_MASK 0x00000020UL
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_SHIFT 5
+#define EUR_CR_OCP_DEBUG_CONFIG_SELECT_INIT_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_MASK 0x80000000UL
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SHIFT 31
+#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SIGNED 0
+
+/* Register EUR_CR_OCP_DEBUG_STATUS */
+#define EUR_CR_OCP_DEBUG_STATUS 0xFF0C
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_MASK 0x00000003UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SHIFT 0
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_MASK 0x00000004UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_SHIFT 2
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SCONNECT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_MASK 0x00000008UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_SHIFT 3
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEREQ_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_MASK 0x00000030UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_SHIFT 4
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SDISCACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_MASK 0x000000C0UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_SHIFT 6
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_SIDLEACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_MASK 0x00000300UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_SHIFT 8
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MCONNECT0_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_MASK 0x00000400UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_SHIFT 10
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT0_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_MASK 0x00000800UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_SHIFT 11
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT1_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_MASK 0x00001000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_SHIFT 12
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_SCONNECT2_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_MASK 0x00006000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_SHIFT 13
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCACK_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_MASK 0x00008000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_SHIFT 15
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MDISCREQ_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_MASK 0x00010000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_SHIFT 16
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MWAIT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_MASK 0x00020000UL
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_SHIFT 17
+#define EUR_CR_OCP_DEBUG_STATUS_INIT_MSTANDBY_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_MASK 0x001C0000UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_SHIFT 18
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_CMD_OUT_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_MASK 0x03E00000UL
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_SHIFT 21
+#define EUR_CR_OCP_DEBUG_STATUS_WHICH_TARGET_REGISTER_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_MASK 0x04000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_SHIFT 26
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_ERROR_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_MASK 0x08000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_SHIFT 27
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_MASK 0x10000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_SHIFT 28
+#define EUR_CR_OCP_DEBUG_STATUS_RESP_FIFO_FULL_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_MASK 0x20000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_SHIFT 29
+#define EUR_CR_OCP_DEBUG_STATUS_TARGET_IDLE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_MASK 0x40000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_SHIFT 30
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_RESP_DEBUG_STATE_SIGNED 0
+
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_MASK 0x80000000UL
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SHIFT 31
+#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SIGNED 0
+
+
+#endif /* _OCPDEFS_H_ */
+
+/*****************************************************************************
+ End of file (ocpdefs.h)
+*****************************************************************************/
diff --git a/drivers/gpu/pvr/oemfuncs.h b/drivers/gpu/pvr/oemfuncs.h
new file mode 100644
index 00000000000..a957a21cf5f
--- /dev/null
+++ b/drivers/gpu/pvr/oemfuncs.h
@@ -0,0 +1,41 @@
+/**********************************************************************
+ *
+ * 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(__OEMFUNCS_H__)
+#define __OEMFUNCS_H__
+
+#include <linux/fs.h>
+
+struct PVRSRV_DC_OEM_JTABLE {
+ long (*pfnOEMBridgeDispatch)(struct file *, unsigned, unsigned long);
+ void *pvDummy1;
+ void *pvDummy2;
+ void *pvDummy3;
+};
+
+#define OEM_GET_EXT_FUNCS (1<<1)
+
+#endif
diff --git a/drivers/gpu/pvr/omaplfb.h b/drivers/gpu/pvr/omaplfb.h
new file mode 100644
index 00000000000..34e7a6d8f16
--- /dev/null
+++ b/drivers/gpu/pvr/omaplfb.h
@@ -0,0 +1,140 @@
+/**********************************************************************
+ *
+ * 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 __OMAPLFB_H__
+#define __OMAPLFB_H__
+
+#define OMAPLCD_IRQ 25
+
+#define OMAPLCD_SYSCONFIG 0x0410
+#define OMAPLCD_CONFIG 0x0444
+#define OMAPLCD_DEFAULT_COLOR0 0x044C
+#define OMAPLCD_TIMING_H 0x0464
+#define OMAPLCD_TIMING_V 0x0468
+#define OMAPLCD_POL_FREQ 0x046C
+#define OMAPLCD_DIVISOR 0x0470
+#define OMAPLCD_SIZE_DIG 0x0478
+#define OMAPLCD_SIZE_LCD 0x047C
+#define OMAPLCD_GFX_POSITION 0x0488
+#define OMAPLCD_GFX_SIZE 0x048C
+#define OMAPLCD_GFX_ATTRIBUTES 0x04a0
+#define OMAPLCD_GFX_FIFO_THRESHOLD 0x04a4
+#define OMAPLCD_GFX_WINDOW_SKIP 0x04b4
+
+#define OMAPLCD_IRQSTATUS 0x0418
+#define OMAPLCD_IRQENABLE 0x041c
+#define OMAPLCD_CONTROL 0x0440
+#define OMAPLCD_GFX_BA0 0x0480
+#define OMAPLCD_GFX_BA1 0x0484
+#define OMAPLCD_GFX_ROW_INC 0x04ac
+#define OMAPLCD_GFX_PIX_INC 0x04b0
+#define OMAPLCD_VID1_BA0 0x04bc
+#define OMAPLCD_VID1_BA1 0x04c0
+#define OMAPLCD_VID1_ROW_INC 0x04d8
+#define OMAPLCD_VID1_PIX_INC 0x04dc
+
+#define OMAP_CONTROL_GODIGITAL (1 << 6)
+#define OMAP_CONTROL_GOLCD (1 << 5)
+#define OMAP_CONTROL_DIGITALENABLE (1 << 1)
+#define OMAP_CONTROL_LCDENABLE (1 << 0)
+
+#define OMAPLCD_INTMASK_VSYNC (1 << 1)
+#define OMAPLCD_INTMASK_OFF 0
+
+struct OMAPLFB_BUFFER {
+ struct IMG_SYS_PHYADDR sSysAddr;
+ void __iomem *sCPUVAddr;
+ u32 ui32BufferSize;
+ struct PVRSRV_SYNC_DATA *psSyncData;
+ struct OMAPLFB_BUFFER *psNext;
+};
+
+struct OMAPLFB_SWAPCHAIN {
+
+ u32 ui32BufferCount;
+ struct OMAPLFB_BUFFER *psBuffer;
+ struct PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable;
+ IMG_BOOL bBlanked;
+};
+
+struct OMAPLFB_FBINFO {
+ struct IMG_SYS_PHYADDR sSysAddr;
+ void __iomem *sCPUVAddr;
+ u32 ui32FBSize;
+ u32 ui32BufferSize;
+ u32 ui32RoundedBufferSize;
+ u32 ui32Width;
+ u32 ui32Height;
+ u32 ui32ByteStride;
+
+ enum PVRSRV_PIXEL_FORMAT ePixelFormat;
+};
+
+struct OMAPLFB_DEVINFO {
+ u32 ui32DeviceID;
+ struct DISPLAY_INFO sDisplayInfo;
+ struct OMAPLFB_BUFFER sSystemBuffer;
+ struct DISPLAY_FORMAT sDisplayFormat;
+ struct DISPLAY_DIMS sDisplayDim;
+ struct PVRSRV_DC_DISP2SRV_KMJTABLE sPVRJTable;
+ struct PVRSRV_DC_SRV2DISP_KMJTABLE sDCJTable;
+ struct OMAPLFB_FBINFO sFBInfo;
+ u32 ui32RefCount;
+ struct OMAPLFB_SWAPCHAIN *psSwapChain;
+ struct IMG_DEV_VIRTADDR sDisplayDevVAddr;
+ struct fb_info *psLINFBInfo;
+ struct notifier_block sLINNotifBlock;
+};
+
+#define OMAPLFB_PAGE_SIZE 4096
+#define OMAPLFB_PAGE_MASK (OMAPLFB_PAGE_SIZE - 1)
+#define OMAPLFB_PAGE_TRUNC (~OMAPLFB_PAGE_MASK)
+
+#define OMAPLFB_PAGE_ROUNDUP(x) (((x) + OMAPLFB_PAGE_MASK) & OMAPLFB_PAGE_TRUNC)
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+#define DEBUG_PRINTK(x) printk x
+#else
+#define DEBUG_PRINTK(x)
+#endif
+
+#define DISPLAY_DEVICE_NAME "PowerVR OMAP Linux Display Driver"
+#define DRVNAME "omaplfb"
+#define DEVNAME DRVNAME
+#define DRIVER_PREFIX DRVNAME
+
+enum PVRSRV_ERROR OMAPLFBInit(void);
+enum PVRSRV_ERROR OMAPLFBDeinit(void);
+
+void OMAPLFBDriverSuspend(void);
+void OMAPLFBDriverResume(void);
+
+void *OMAPLFBAllocKernelMem(u32 ui32Size);
+void OMAPLFBFreeKernelMem(void *pvMem);
+enum PVRSRV_ERROR OMAPLFBGetLibFuncAddr(char *szFunctionName,
+ IMG_BOOL (**ppfnFuncTable)(struct PVRSRV_DC_DISP2SRV_KMJTABLE *));
+
+#endif
diff --git a/drivers/gpu/pvr/omaplfb_displayclass.c b/drivers/gpu/pvr/omaplfb_displayclass.c
new file mode 100644
index 00000000000..73588cc0f3e
--- /dev/null
+++ b/drivers/gpu/pvr/omaplfb_displayclass.c
@@ -0,0 +1,820 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+
+#include <asm/div64.h>
+#include <video/sgx-util.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "omaplfb.h"
+
+static void *gpvAnchor;
+
+static int fb_idx;
+
+#define OMAPLFB_COMMAND_COUNT 1
+
+static IMG_BOOL (*pfnGetPVRJTable)(struct PVRSRV_DC_DISP2SRV_KMJTABLE *);
+
+static struct OMAPLFB_DEVINFO *GetAnchorPtr(void)
+{
+ return (struct OMAPLFB_DEVINFO *)gpvAnchor;
+}
+
+static void SetAnchorPtr(struct OMAPLFB_DEVINFO *psDevInfo)
+{
+ gpvAnchor = (void *) psDevInfo;
+}
+
+static int FrameBufferEvents(struct notifier_block *psNotif,
+ unsigned long event, void *data)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+ struct OMAPLFB_SWAPCHAIN *psSwapChain;
+ struct fb_event *psFBEvent = (struct fb_event *)data;
+
+ if (event != FB_EVENT_BLANK)
+ return 0;
+
+ psDevInfo = GetAnchorPtr();
+ psSwapChain = psDevInfo->psSwapChain;
+ psSwapChain->bBlanked = (*(int *)psFBEvent->data != 0);
+
+ return 0;
+}
+
+static enum PVRSRV_ERROR EnableLFBEventNotification(struct OMAPLFB_DEVINFO
+ *psDevInfo)
+{
+ int res;
+ struct OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
+
+ memset(&psDevInfo->sLINNotifBlock, 0,
+ sizeof(psDevInfo->sLINNotifBlock));
+
+ psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
+
+ psSwapChain->bBlanked = IMG_FALSE;
+
+ res = fb_register_client(&psDevInfo->sLINNotifBlock);
+ if (res != 0) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": fb_register_client failed (%d)", res);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR DisableLFBEventNotification(struct OMAPLFB_DEVINFO
+ *psDevInfo)
+{
+ int res;
+
+ res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
+ if (res != 0) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": fb_unregister_client failed (%d)", res);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR OpenDCDevice(u32 ui32DeviceID, void **phDevice,
+ struct PVRSRV_SYNC_DATA *psSystemBufferSyncData)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+
+ PVR_UNREFERENCED_PARAMETER(ui32DeviceID);
+
+ psDevInfo = GetAnchorPtr();
+
+ psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
+
+ *phDevice = (void *) psDevInfo;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR CloseDCDevice(void *hDevice)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR EnumDCFormats(void *hDevice, u32 *pui32NumFormats,
+ struct DISPLAY_FORMAT *psFormat)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+
+ if (!hDevice || !pui32NumFormats)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+
+ *pui32NumFormats = 1;
+
+ if (psFormat)
+ psFormat[0] = psDevInfo->sDisplayFormat;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR EnumDCDims(void *hDevice,
+ struct DISPLAY_FORMAT *psFormat,
+ u32 *pui32NumDims, struct DISPLAY_DIMS *psDim)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+
+ if (!hDevice || !psFormat || !pui32NumDims)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+
+ *pui32NumDims = 1;
+
+ if (psDim)
+ psDim[0] = psDevInfo->sDisplayDim;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR GetDCSystemBuffer(void *hDevice, void **phBuffer)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+
+ if (!hDevice || !phBuffer)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+
+ *phBuffer = (void *) &psDevInfo->sSystemBuffer;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR GetDCInfo(void *hDevice, struct DISPLAY_INFO *psDCInfo)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+
+ if (!hDevice || !psDCInfo)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+
+ *psDCInfo = psDevInfo->sDisplayInfo;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR GetDCBufferAddr(void *hDevice, void *hBuffer,
+ struct IMG_SYS_PHYADDR **ppsSysAddr,
+ u32 *pui32ByteSize,
+ void __iomem **ppvCpuVAddr,
+ void **phOSMapInfo,
+ IMG_BOOL *pbIsContiguous)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+ struct OMAPLFB_BUFFER *psSystemBuffer;
+
+ if (!hDevice)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+
+ if (!hBuffer)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ psSystemBuffer = (struct OMAPLFB_BUFFER *)hBuffer;
+
+ if (!ppsSysAddr)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ *ppsSysAddr = &psSystemBuffer->sSysAddr;
+
+ if (!pui32ByteSize)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ *pui32ByteSize = psDevInfo->sFBInfo.ui32BufferSize;
+
+ if (ppvCpuVAddr)
+ *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
+
+ if (phOSMapInfo)
+ *phOSMapInfo = (void *) 0;
+
+ if (pbIsContiguous)
+ *pbIsContiguous = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR CreateDCSwapChain(void *hDevice, u32 ui32Flags,
+ struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ u32 ui32BufferCount,
+ struct PVRSRV_SYNC_DATA **ppsSyncData,
+ u32 ui32OEMFlags, void **phSwapChain,
+ u32 *pui32SwapChainID)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+ struct OMAPLFB_SWAPCHAIN *psSwapChain;
+ struct OMAPLFB_BUFFER *psBuffer;
+ u32 i;
+ enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+ PVR_UNREFERENCED_PARAMETER(ui32OEMFlags);
+ PVR_UNREFERENCED_PARAMETER(pui32SwapChainID);
+
+ if (!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib ||
+ !ppsSyncData || !phSwapChain)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+
+ if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+
+ if (psDevInfo->psSwapChain != NULL)
+ return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
+
+ if (ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+
+ if ((psDevInfo->sFBInfo.ui32RoundedBufferSize * ui32BufferCount) >
+ psDevInfo->sFBInfo.ui32FBSize)
+ return PVRSRV_ERROR_TOOMANYBUFFERS;
+
+ if (psDstSurfAttrib->pixelformat !=
+ psDevInfo->sDisplayFormat.pixelformat ||
+ psDstSurfAttrib->sDims.ui32ByteStride !=
+ psDevInfo->sDisplayDim.ui32ByteStride ||
+ psDstSurfAttrib->sDims.ui32Width !=
+ psDevInfo->sDisplayDim.ui32Width ||
+ psDstSurfAttrib->sDims.ui32Height !=
+ psDevInfo->sDisplayDim.ui32Height)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ if (psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat ||
+ psDstSurfAttrib->sDims.ui32ByteStride !=
+ psSrcSurfAttrib->sDims.ui32ByteStride ||
+ psDstSurfAttrib->sDims.ui32Width !=
+ psSrcSurfAttrib->sDims.ui32Width ||
+ psDstSurfAttrib->sDims.ui32Height !=
+ psSrcSurfAttrib->sDims.ui32Height)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+ psSwapChain = (struct OMAPLFB_SWAPCHAIN *)
+ OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_SWAPCHAIN));
+ if (!psSwapChain)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ psBuffer = (struct OMAPLFB_BUFFER *)
+ OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_BUFFER) *
+ ui32BufferCount);
+ if (!psBuffer) {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ErrorFreeSwapChain;
+ }
+
+ psSwapChain->ui32BufferCount = ui32BufferCount;
+ psSwapChain->psBuffer = psBuffer;
+ psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
+
+ for (i = 0; i < ui32BufferCount - 1; i++)
+ psBuffer[i].psNext = &psBuffer[i + 1];
+
+ psBuffer[i].psNext = &psBuffer[0];
+
+ for (i = 0; i < ui32BufferCount; i++) {
+ u32 ui32BufferOffset = i *
+ psDevInfo->sFBInfo.ui32RoundedBufferSize;
+
+ psBuffer[i].psSyncData = ppsSyncData[i];
+
+ psBuffer[i].sSysAddr.uiAddr =
+ psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
+ psBuffer[i].sCPUVAddr =
+ psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
+ }
+
+ psDevInfo->psSwapChain = psSwapChain;
+
+ eError = EnableLFBEventNotification(psDevInfo);
+ if (eError != PVRSRV_OK) {
+ printk(DRIVER_PREFIX
+ ": Couldn't enable framebuffer event notification\n");
+ goto ErrorFreeBuffer;
+ }
+
+ *phSwapChain = (void *) psSwapChain;
+
+ return PVRSRV_OK;
+
+ErrorFreeBuffer:
+ OMAPLFBFreeKernelMem(psBuffer);
+ErrorFreeSwapChain:
+ OMAPLFBFreeKernelMem(psSwapChain);
+
+ return eError;
+}
+
+static enum PVRSRV_ERROR DestroyDCSwapChain(void *hDevice, void *hSwapChain)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+ struct OMAPLFB_SWAPCHAIN *psSwapChain;
+ enum PVRSRV_ERROR eError;
+
+ if (!hDevice || !hSwapChain)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+ psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
+ if (psSwapChain != psDevInfo->psSwapChain)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ eError = DisableLFBEventNotification(psDevInfo);
+ if (eError != PVRSRV_OK)
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": Couldn't disable framebuffer event notification\n");
+
+ psDevInfo->psSwapChain = NULL;
+
+ OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
+ OMAPLFBFreeKernelMem(psSwapChain);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR SetDCDstRect(void *hDevice,
+ void *hSwapChain, struct IMG_RECT *psRect)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(psRect);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static enum PVRSRV_ERROR SetDCSrcRect(void *hDevice,
+ void *hSwapChain, struct IMG_RECT *psRect)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(psRect);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static enum PVRSRV_ERROR SetDCDstColourKey(void *hDevice, void *hSwapChain,
+ u32 ui32CKColour)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(ui32CKColour);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static enum PVRSRV_ERROR SetDCSrcColourKey(void *hDevice, void *hSwapChain,
+ u32 ui32CKColour)
+{
+ PVR_UNREFERENCED_PARAMETER(hDevice);
+ PVR_UNREFERENCED_PARAMETER(hSwapChain);
+ PVR_UNREFERENCED_PARAMETER(ui32CKColour);
+
+ return PVRSRV_ERROR_NOT_SUPPORTED;
+}
+
+static enum PVRSRV_ERROR GetDCBuffers(void *hDevice, void *hSwapChain,
+ u32 *pui32BufferCount, void **phBuffer)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+ struct OMAPLFB_SWAPCHAIN *psSwapChain;
+ u32 i;
+
+ if (!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
+ psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
+ if (psSwapChain != psDevInfo->psSwapChain)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ *pui32BufferCount = psSwapChain->ui32BufferCount;
+
+ for (i = 0; i < psSwapChain->ui32BufferCount; i++)
+ phBuffer[i] = (void *) &psSwapChain->psBuffer[i];
+
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL ProcessFlip(void *hCmdCookie, u32 ui32DataSize, void *pvData)
+{
+ struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
+ struct OMAPLFB_DEVINFO *psDevInfo;
+ struct OMAPLFB_BUFFER *psBuffer;
+ struct OMAPLFB_SWAPCHAIN *psSwapChain;
+
+ if (!hCmdCookie || !pvData)
+ return IMG_FALSE;
+
+ psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)pvData;
+
+ if (psFlipCmd == NULL
+ || sizeof(struct DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
+ return IMG_FALSE;
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)psFlipCmd->hExtDevice;
+
+ psBuffer = (struct OMAPLFB_BUFFER *)psFlipCmd->hExtBuffer;
+ psSwapChain = (struct OMAPLFB_SWAPCHAIN *)psFlipCmd->hExtSwapChain;
+
+ psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
+
+ return IMG_TRUE;
+}
+
+static void CalcSwapChainSize(struct OMAPLFB_DEVINFO *psDevInfo)
+{
+ if (psDevInfo->sFBInfo.ui32RoundedBufferSize)
+ psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers =
+ psDevInfo->sFBInfo.ui32FBSize /
+ psDevInfo->sFBInfo.ui32RoundedBufferSize;
+ else
+ psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 0;
+
+ if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0) {
+ psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
+ psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
+ } else {
+ psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
+ psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
+ }
+
+ psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
+
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Maximum number of swap chain buffers: %u\n",
+ psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
+}
+
+static void SetDevinfo(struct OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
+ unsigned long FBSize;
+
+ FBSize = (psLINFBInfo->screen_size) != 0 ?
+ psLINFBInfo->screen_size : psLINFBInfo->fix.smem_len;
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer physical address: 0x%lx\n",
+ psLINFBInfo->fix.smem_start));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer virtual address: 0x%lx\n",
+ (unsigned long)psLINFBInfo->screen_base));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer size: %lu\n", FBSize));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer virtual width: %u\n",
+ psLINFBInfo->var.xres_virtual));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer virtual height: %u\n",
+ psLINFBInfo->var.yres_virtual));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer width: %u\n", psLINFBInfo->var.xres));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer height: %u\n", psLINFBInfo->var.yres));
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": Framebuffer stride: %u\n",
+ psLINFBInfo->fix.line_length));
+
+ psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
+ psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
+
+ psPVRFBInfo->ui32Width = psLINFBInfo->var.xres_virtual;
+ psPVRFBInfo->ui32ByteStride = psLINFBInfo->fix.line_length;
+ psPVRFBInfo->ui32FBSize = FBSize;
+
+ /* Try double buffering */
+ psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual >> 1;
+ psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
+ psPVRFBInfo->ui32Height;
+ psPVRFBInfo->ui32RoundedBufferSize =
+ sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
+ psPVRFBInfo->ui32BufferSize);
+
+ /* If the buffers aren't aligned assume single buffering */
+ if (psPVRFBInfo->ui32BufferSize != psPVRFBInfo->ui32RoundedBufferSize) {
+ psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual;
+ psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
+ psPVRFBInfo->ui32Height;
+ psPVRFBInfo->ui32RoundedBufferSize =
+ sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
+ psPVRFBInfo->ui32BufferSize);
+ }
+
+ CalcSwapChainSize(psDevInfo);
+
+ if (psLINFBInfo->var.bits_per_pixel == 16) {
+ if ((psLINFBInfo->var.red.length == 5) &&
+ (psLINFBInfo->var.green.length == 6) &&
+ (psLINFBInfo->var.blue.length == 5) &&
+ (psLINFBInfo->var.red.offset == 11) &&
+ (psLINFBInfo->var.green.offset == 5) &&
+ (psLINFBInfo->var.blue.offset == 0) &&
+ (psLINFBInfo->var.red.msb_right == 0))
+ psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
+ else
+ printk("Unknown FB format\n");
+ } else if (psLINFBInfo->var.bits_per_pixel == 32) {
+ if ((psLINFBInfo->var.transp.length == 8) &&
+ (psLINFBInfo->var.red.length == 8) &&
+ (psLINFBInfo->var.green.length == 8) &&
+ (psLINFBInfo->var.blue.length == 8) &&
+ (psLINFBInfo->var.transp.offset == 24) &&
+ (psLINFBInfo->var.red.offset == 16) &&
+ (psLINFBInfo->var.green.offset == 8) &&
+ (psLINFBInfo->var.blue.offset == 0) &&
+ (psLINFBInfo->var.red.msb_right == 0))
+ psPVRFBInfo->ePixelFormat =
+ PVRSRV_PIXEL_FORMAT_ARGB8888;
+ else if ((psLINFBInfo->var.transp.length == 0) &&
+ (psLINFBInfo->var.red.length == 8) &&
+ (psLINFBInfo->var.green.length == 8) &&
+ (psLINFBInfo->var.blue.length == 8) &&
+ (psLINFBInfo->var.transp.offset == 0) &&
+ (psLINFBInfo->var.red.offset == 16) &&
+ (psLINFBInfo->var.green.offset == 8) &&
+ (psLINFBInfo->var.blue.offset == 0) &&
+ (psLINFBInfo->var.red.msb_right == 0))
+ psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB888;
+ else
+ printk(KERN_ERR "Unknown FB format\n");
+ } else {
+ printk(KERN_ERR "Unknown FB format\n");
+ }
+
+ psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
+ psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width;
+ psDevInfo->sDisplayDim.ui32Height = psDevInfo->sFBInfo.ui32Height;
+ psDevInfo->sDisplayDim.ui32ByteStride =
+ psDevInfo->sFBInfo.ui32ByteStride;
+ psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
+ psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
+ psDevInfo->sSystemBuffer.ui32BufferSize =
+ psDevInfo->sFBInfo.ui32RoundedBufferSize;
+}
+
+static struct FB_EVENTS {
+ struct notifier_block notif;
+ struct OMAPLFB_DEVINFO *psDevInfo;
+} gFBEventsData;
+
+static int FBEvents(struct notifier_block *psNotif,
+ unsigned long event, void *data)
+{
+ if (event == FB_EVENT_MODE_CHANGE) {
+ struct FB_EVENTS *psEvents =
+ container_of(psNotif, struct FB_EVENTS, notif);
+ SetDevinfo(psEvents->psDevInfo);
+ }
+ return 0;
+}
+
+static enum PVRSRV_ERROR InitDev(struct OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct fb_info *psLINFBInfo;
+ struct module *psLINFBOwner;
+ struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
+ enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
+
+ console_lock();
+
+ if (fb_idx < 0 || fb_idx >= num_registered_fb) {
+ eError = PVRSRV_ERROR_INVALID_DEVICE;
+ goto errRelSem;
+ }
+
+ psLINFBInfo = registered_fb[fb_idx];
+
+ psLINFBOwner = psLINFBInfo->fbops->owner;
+ if (!try_module_get(psLINFBOwner)) {
+ printk(KERN_INFO DRIVER_PREFIX
+ ": Couldn't get framebuffer module\n");
+
+ goto errRelSem;
+ }
+
+ if (psLINFBInfo->fbops->fb_open != NULL) {
+ int res;
+
+ res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
+ if (res != 0) {
+ printk(KERN_INFO DRIVER_PREFIX
+ ": Couldn't open framebuffer: %d\n", res);
+
+ goto errModPut;
+ }
+ }
+
+ psDevInfo->psLINFBInfo = psLINFBInfo;
+
+ SetDevinfo(psDevInfo);
+
+ gFBEventsData.notif.notifier_call = FBEvents;
+ gFBEventsData.psDevInfo = psDevInfo;
+ fb_register_client(&gFBEventsData.notif);
+
+ psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
+ psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
+
+ eError = PVRSRV_OK;
+ goto errRelSem;
+
+errModPut:
+ module_put(psLINFBOwner);
+errRelSem:
+ console_unlock();
+ return eError;
+}
+
+static void DeInitDev(struct OMAPLFB_DEVINFO *psDevInfo)
+{
+ struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
+ struct module *psLINFBOwner;
+
+ console_lock();
+
+ fb_unregister_client(&gFBEventsData.notif);
+
+ psLINFBOwner = psLINFBInfo->fbops->owner;
+
+ if (psLINFBInfo->fbops->fb_release != NULL)
+ (void)psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
+
+ module_put(psLINFBOwner);
+
+ console_unlock();
+}
+
+enum PVRSRV_ERROR OMAPLFBInit(void)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo;
+
+ psDevInfo = GetAnchorPtr();
+
+ if (psDevInfo == NULL) {
+ IMG_BOOL (*pfnCmdProcList[OMAPLFB_COMMAND_COUNT])
+ (void *, u32, void *);
+ u32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
+
+ psDevInfo = (struct OMAPLFB_DEVINFO *)
+ OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_DEVINFO));
+
+ if (!psDevInfo)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ memset(psDevInfo, 0, sizeof(struct OMAPLFB_DEVINFO));
+
+ SetAnchorPtr((void *) psDevInfo);
+
+ psDevInfo->ui32RefCount = 0;
+
+ if (InitDev(psDevInfo) != PVRSRV_OK)
+ return PVRSRV_ERROR_INIT_FAILURE;
+
+ if (OMAPLFBGetLibFuncAddr("PVRGetDisplayClassJTable",
+ &pfnGetPVRJTable) != PVRSRV_OK)
+ return PVRSRV_ERROR_INIT_FAILURE;
+
+ if (!(*pfnGetPVRJTable) (&psDevInfo->sPVRJTable))
+ return PVRSRV_ERROR_INIT_FAILURE;
+
+ psDevInfo->psSwapChain = NULL;
+
+ CalcSwapChainSize(psDevInfo);
+
+ strncpy(psDevInfo->sDisplayInfo.szDisplayName,
+ DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
+
+ psDevInfo->sDCJTable.ui32TableSize =
+ sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE);
+ psDevInfo->sDCJTable.owner = THIS_MODULE;
+ psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
+ psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
+ psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
+ psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
+ psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
+ psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
+ psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
+ psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
+ psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
+ psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
+ psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
+ psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
+ psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
+ psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
+ psDevInfo->sDCJTable.pfnSetDCState = NULL;
+
+ if (psDevInfo->sPVRJTable.
+ pfnPVRSRVRegisterDCDevice(&psDevInfo->sDCJTable,
+ &psDevInfo->ui32DeviceID) !=
+ PVRSRV_OK)
+ return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
+
+ pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
+
+ aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
+ aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
+
+ if (psDevInfo->sPVRJTable.
+ pfnPVRSRVRegisterCmdProcList(psDevInfo->ui32DeviceID,
+ &pfnCmdProcList[0],
+ aui32SyncCountList,
+ OMAPLFB_COMMAND_COUNT) !=
+ PVRSRV_OK) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": Can't register callback\n");
+ return PVRSRV_ERROR_CANT_REGISTER_CALLBACK;
+ }
+
+ }
+
+ psDevInfo->ui32RefCount++;
+
+ return PVRSRV_OK;
+
+}
+
+enum PVRSRV_ERROR OMAPLFBDeinit(void)
+{
+ struct OMAPLFB_DEVINFO *psDevInfo, *psDevFirst;
+
+ psDevFirst = GetAnchorPtr();
+ psDevInfo = psDevFirst;
+
+ if (psDevInfo == NULL)
+ return PVRSRV_ERROR_GENERIC;
+
+ psDevInfo->ui32RefCount--;
+
+ if (psDevInfo->ui32RefCount == 0) {
+ struct PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable =
+ &psDevInfo->sPVRJTable;
+ if (psDevInfo->sPVRJTable.
+ pfnPVRSRVRemoveCmdProcList(psDevInfo->ui32DeviceID,
+ OMAPLFB_COMMAND_COUNT) !=
+ PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
+
+ if (psJTable->
+ pfnPVRSRVRemoveDCDevice(psDevInfo->ui32DeviceID) !=
+ PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
+
+ DeInitDev(psDevInfo);
+
+ OMAPLFBFreeKernelMem(psDevInfo);
+ }
+
+ SetAnchorPtr(NULL);
+
+ return PVRSRV_OK;
+}
+
diff --git a/drivers/gpu/pvr/omaplfb_linux.c b/drivers/gpu/pvr/omaplfb_linux.c
new file mode 100644
index 00000000000..bba3bbd345f
--- /dev/null
+++ b/drivers/gpu/pvr/omaplfb_linux.c
@@ -0,0 +1,168 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/module.h>
+
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+
+#include <linux/platform_device.h>
+
+#include <linux/io.h>
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "kerneldisplay.h"
+#include "omaplfb.h"
+#include "pvrmodule.h"
+
+#include <video/omapdss.h>
+
+MODULE_SUPPORTED_DEVICE(DEVNAME);
+
+#define unref__ __attribute__ ((unused))
+
+void *OMAPLFBAllocKernelMem(u32 ui32Size)
+{
+ return kmalloc(ui32Size, GFP_KERNEL);
+}
+
+void OMAPLFBFreeKernelMem(void *pvMem)
+{
+ kfree(pvMem);
+}
+
+enum PVRSRV_ERROR OMAPLFBGetLibFuncAddr(char *szFunctionName,
+ IMG_BOOL (**ppfnFuncTable)(struct PVRSRV_DC_DISP2SRV_KMJTABLE *))
+{
+ if (strcmp("PVRGetDisplayClassJTable", szFunctionName) != 0)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ *ppfnFuncTable = PVRGetDisplayClassJTable;
+
+ return PVRSRV_OK;
+}
+
+static int OMAPLFBDriverSuspend_Entry(struct platform_device unref__ * pDevice,
+ pm_message_t unref__ state)
+{
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": OMAPLFBDriverSuspend_Entry\n"));
+ return 0;
+}
+
+static int OMAPLFBDriverResume_Entry(struct platform_device unref__ * pDevice)
+{
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": OMAPLFBDriverResume_Entry\n"));
+ return 0;
+}
+
+static void OMAPLFBDriverShutdown_Entry(struct platform_device unref__ *
+ pDevice)
+{
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": OMAPLFBDriverShutdown_Entry\n"));
+}
+
+static void OMAPLFBDeviceRelease_Entry(struct device unref__ * pDevice)
+{
+ DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
+ ": OMAPLFBDriverRelease_Entry\n"));
+}
+
+static struct platform_driver omaplfb_driver = {
+ .driver = {
+ .name = DRVNAME,
+ },
+ .suspend = OMAPLFBDriverSuspend_Entry,
+ .resume = OMAPLFBDriverResume_Entry,
+ .shutdown = OMAPLFBDriverShutdown_Entry,
+};
+
+static struct platform_device omaplfb_device = {
+ .name = DEVNAME,
+ .id = -1,
+ .dev = {
+ .release = OMAPLFBDeviceRelease_Entry
+ }
+};
+
+static int __init OMAPLFB_Init(void)
+{
+ int error;
+
+ if (OMAPLFBInit() != PVRSRV_OK) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": OMAPLFB_Init: OMAPLFBInit failed\n");
+ return -ENODEV;
+ }
+ error = platform_driver_register(&omaplfb_driver);
+ if (error) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": OMAPLFB_Init: Unable to register platform driver (%d)\n",
+ error);
+
+ goto ExitDeinit;
+ }
+
+ error = platform_device_register(&omaplfb_device);
+ if (error) {
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": OMAPLFB_Init: Unable to register platform device (%d)\n",
+ error);
+
+ goto ExitDriverUnregister;
+ }
+
+ return 0;
+
+ExitDriverUnregister:
+ platform_driver_unregister(&omaplfb_driver);
+
+ExitDeinit:
+ if (OMAPLFBDeinit() != PVRSRV_OK)
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": OMAPLFB_Init: OMAPLFBDeinit failed\n");
+
+ return -ENODEV;
+}
+
+static void __exit OMAPLFB_Cleanup(void)
+{
+ platform_device_unregister(&omaplfb_device);
+ platform_driver_unregister(&omaplfb_driver);
+
+ if (OMAPLFBDeinit() != PVRSRV_OK)
+ printk(KERN_WARNING DRIVER_PREFIX
+ ": OMAPLFB_Cleanup: OMAPLFBDeinit failed\n");
+}
+
+module_init(OMAPLFB_Init);
+module_exit(OMAPLFB_Cleanup);
diff --git a/drivers/gpu/pvr/osfunc.c b/drivers/gpu/pvr/osfunc.c
new file mode 100644
index 00000000000..c3c36acf9a4
--- /dev/null
+++ b/drivers/gpu/pvr/osfunc.c
@@ -0,0 +1,1498 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/hardirq.h>
+#include <linux/timer.h>
+#include <linux/capability.h>
+#include <linux/uaccess.h>
+#include <linux/spinlock.h>
+
+#include "img_types.h"
+#include "services_headers.h"
+#include "mm.h"
+#include "pvrmmap.h"
+#include "mmap.h"
+#include "env_data.h"
+#include "proc.h"
+#include "event.h"
+
+#define EVENT_OBJECT_TIMEOUT_MS (100)
+
+#define HOST_ALLOC_MEM_USING_KMALLOC ((void *)0)
+#define HOST_ALLOC_MEM_USING_VMALLOC ((void *)1)
+
+#define LINUX_KMALLOC_LIMIT PAGE_SIZE /* 4k */
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+enum PVRSRV_ERROR OSAllocMem(u32 ui32Flags, u32 ui32Size,
+ void **ppvCpuVAddr, void **phBlockAlloc)
+#else
+enum PVRSRV_ERROR _OSAllocMem(u32 ui32Flags, u32 ui32Size,
+ void **ppvCpuVAddr, void **phBlockAlloc,
+ char *pszFilename, u32 ui32Line)
+#endif
+{
+ u32 ui32Threshold;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+ /* determine whether to go straight to vmalloc */
+ ui32Threshold = LINUX_KMALLOC_LIMIT;
+
+ if (ui32Size > ui32Threshold) {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED,
+ pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED);
+#endif
+ if (!*ppvCpuVAddr)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ if (phBlockAlloc)
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_VMALLOC;
+ } else {
+ /* default - try kmalloc first */
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ *ppvCpuVAddr = _KMallocWrapper(ui32Size, pszFilename, ui32Line);
+#else
+ *ppvCpuVAddr = KMallocWrapper(ui32Size);
+#endif
+
+ if (!*ppvCpuVAddr)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ if (phBlockAlloc)
+ *phBlockAlloc = HOST_ALLOC_MEM_USING_KMALLOC;
+
+ }
+
+ return PVRSRV_OK;
+}
+
+#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+void OSFreeMem(u32 ui32Flags, u32 ui32Size, void *pvCpuVAddr, void *hBlockAlloc)
+#else
+void _OSFreeMem(u32 ui32Flags, u32 ui32Size, void *pvCpuVAddr,
+ void *hBlockAlloc, char *pszFilename, u32 ui32Line)
+#endif
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Flags);
+
+ if (ui32Size > LINUX_KMALLOC_LIMIT) {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _VFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ VFreeWrapper(pvCpuVAddr);
+#endif
+ } else {
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ _KFreeWrapper(pvCpuVAddr, pszFilename, ui32Line);
+#else
+ KFreeWrapper(pvCpuVAddr);
+#endif
+ }
+}
+
+enum PVRSRV_ERROR OSAllocPages(u32 ui32AllocFlags, u32 ui32Size,
+ u32 ui32PageSize, void **ppvCpuVAddr,
+ void **phOSMemHandle)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+
+ switch (ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea =
+ NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+ psLinuxMemArea =
+ NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ psLinuxMemArea =
+ NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "OSAllocPages: invalid flags 0x%x\n",
+ ui32AllocFlags);
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (void *) 0;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ if (ui32AllocFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
+ inv_cache_mem_area(psLinuxMemArea);
+
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+ *phOSMemHandle = psLinuxMemArea;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSFreePages(u32 ui32AllocFlags, u32 ui32Bytes,
+ void *pvCpuVAddr, void *hOSMemHandle)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+
+ psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
+
+ switch (ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSFreePages(ui32AllocFlags=0x%08X, ui32Bytes=%ld, "
+ "pvCpuVAddr=%p, hOSMemHandle=%p) FAILED!",
+ ui32AllocFlags, ui32Bytes, pvCpuVAddr,
+ hOSMemHandle);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "%s: invalid flags 0x%x\n",
+ __func__, ui32AllocFlags);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSGetSubMemHandle(void *hOSMemHandle, u32 ui32ByteOffset,
+ u32 ui32Bytes, u32 ui32Flags,
+ void **phOSMemHandleRet)
+{
+ struct LinuxMemArea *psParentLinuxMemArea, *psLinuxMemArea;
+ enum PVRSRV_ERROR eError;
+
+ psParentLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
+
+ psLinuxMemArea =
+ NewSubLinuxMemArea(psParentLinuxMemArea, ui32ByteOffset, ui32Bytes);
+ if (!psLinuxMemArea) {
+ *phOSMemHandleRet = NULL;
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ *phOSMemHandleRet = psLinuxMemArea;
+
+ if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
+ return PVRSRV_OK;
+
+ eError = PVRMMapRegisterArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ goto failed_register_area;
+
+ return PVRSRV_OK;
+
+failed_register_area:
+ *phOSMemHandleRet = NULL;
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+ return eError;
+}
+
+enum PVRSRV_ERROR OSReleaseSubMemHandle(void *hOSMemHandle, u32 ui32Flags)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ enum PVRSRV_ERROR eError;
+
+ psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
+ PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC);
+
+ if ((ui32Flags & PVRSRV_HAP_KERNEL_ONLY) == 0) {
+ eError = PVRMMapRemoveRegisteredArea(psLinuxMemArea);
+ if (eError != PVRSRV_OK)
+ return eError;
+ }
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+struct IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(void *hOSMemHandle,
+ u32 ui32ByteOffset)
+{
+ PVR_ASSERT(hOSMemHandle);
+
+ return LinuxMemAreaToCpuPAddr(hOSMemHandle, ui32ByteOffset);
+}
+
+void OSMemCopy(void *pvDst, void *pvSrc, u32 ui32Size)
+{
+ memcpy(pvDst, pvSrc, ui32Size);
+}
+
+void OSMemSet(void *pvDest, u8 ui8Value, u32 ui32Size)
+{
+ memset(pvDest, (int)ui8Value, (size_t) ui32Size);
+}
+
+char *OSStringCopy(char *pszDest, const char *pszSrc)
+{
+ return strcpy(pszDest, pszSrc);
+}
+
+s32 OSSNPrintf(char *pStr, u32 ui32Size, const char *pszFormat, ...)
+{
+ va_list argList;
+ s32 iCount;
+
+ va_start(argList, pszFormat);
+ iCount = vsnprintf(pStr, (size_t) ui32Size, pszFormat, argList);
+ va_end(argList);
+
+ return iCount;
+}
+
+enum PVRSRV_ERROR OSInitEnvData(void **ppvEnvSpecificData)
+{
+ struct ENV_DATA *psEnvData;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct ENV_DATA),
+ (void *)&psEnvData, NULL) != PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
+
+ memset(psEnvData, 0, sizeof(*psEnvData));
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+ &psEnvData->pvBridgeData, NULL) != PVRSRV_OK) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct ENV_DATA),
+ psEnvData, NULL);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ *ppvEnvSpecificData = psEnvData;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSDeInitEnvData(void *pvEnvSpecificData)
+{
+ struct ENV_DATA *psEnvData = (struct ENV_DATA *)pvEnvSpecificData;
+
+ PVR_ASSERT(!psEnvData->bMISRInstalled);
+ PVR_ASSERT(!psEnvData->bLISRInstalled);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PVRSRV_MAX_BRIDGE_IN_SIZE + PVRSRV_MAX_BRIDGE_OUT_SIZE,
+ psEnvData->pvBridgeData, NULL);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct ENV_DATA),
+ pvEnvSpecificData, NULL);
+
+ return PVRSRV_OK;
+}
+
+void OSReleaseThreadQuanta(void)
+{
+ schedule();
+}
+
+u32 OSClockus(void)
+{
+ u32 time, j = jiffies;
+
+ time = j * (1000000 / HZ);
+
+ return time;
+}
+
+void OSWaitus(u32 ui32Timeus)
+{
+ udelay(ui32Timeus);
+}
+
+u32 OSGetCurrentProcessIDKM(void)
+{
+ if (in_interrupt())
+ return KERNEL_ID;
+
+ return (u32) task_tgid_nr(current);
+}
+
+u32 OSGetPageSize(void)
+{
+ return PAGE_SIZE;
+}
+
+static irqreturn_t DeviceISRWrapper(int irq, void *dev_id)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ IMG_BOOL bStatus = IMG_FALSE;
+ PVR_UNREFERENCED_PARAMETER(irq);
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)dev_id;
+ if (!psDeviceNode) {
+ PVR_DPF(PVR_DBG_ERROR, "DeviceISRWrapper: invalid params\n");
+ goto out;
+ }
+
+ bStatus = PVRSRVDeviceLISR(psDeviceNode);
+
+ if (bStatus) {
+ struct SYS_DATA *psSysData = psDeviceNode->psSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
+ }
+
+out:
+ return bStatus ? IRQ_HANDLED : IRQ_NONE;
+}
+
+enum PVRSRV_ERROR OSInstallDeviceLISR(void *pvSysData,
+ u32 ui32Irq,
+ char *pszISRName, void *pvDeviceNode)
+{
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bLISRInstalled) {
+ PVR_DPF(PVR_DBG_ERROR, "OSInstallDeviceLISR: "
+ "An ISR has already been installed: IRQ %d cookie %x",
+ psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE("Installing device LISR %s on IRQ %d with cookie %x",
+ pszISRName, ui32Irq, pvDeviceNode);
+
+ if (request_irq(ui32Irq, DeviceISRWrapper,
+ IRQF_SHARED, pszISRName, pvDeviceNode)) {
+ PVR_DPF(PVR_DBG_ERROR, "OSInstallDeviceLISR: "
+ "Couldn't install device LISR on IRQ %d",
+ ui32Irq);
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ psEnvData->ui32IRQ = ui32Irq;
+ psEnvData->pvISRCookie = pvDeviceNode;
+ psEnvData->bLISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSUninstallDeviceLISR(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bLISRInstalled) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSUninstallDeviceLISR: No LISR has been installed");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE("Uninstalling device LISR on IRQ %d with cookie %x",
+ psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ free_irq(psEnvData->ui32IRQ, psEnvData->pvISRCookie);
+
+ psEnvData->bLISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+static void MISRWrapper(struct work_struct *work)
+{
+ struct ENV_DATA *psEnvData = container_of(work, struct ENV_DATA,
+ sMISRWork);
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)psEnvData->pvSysData;
+ PVRSRVMISR(psSysData);
+}
+
+enum PVRSRV_ERROR OSInstallMISR(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSInstallMISR: An MISR has already been installed");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE("Installing MISR with cookie %x", pvSysData);
+
+ psEnvData->pvSysData = pvSysData;
+ psEnvData->psMISRWorkqueue = create_singlethread_workqueue("sgx_misr");
+ INIT_WORK(&psEnvData->sMISRWork, MISRWrapper);
+
+ psEnvData->bMISRInstalled = IMG_TRUE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSUninstallMISR(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->bMISRInstalled) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSUninstallMISR: No MISR has been installed");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE("Uninstalling MISR");
+
+ flush_workqueue(psEnvData->psMISRWorkqueue);
+ destroy_workqueue(psEnvData->psMISRWorkqueue);
+
+ psEnvData->bMISRInstalled = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSScheduleMISR(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->bMISRInstalled)
+ queue_work(psEnvData->psMISRWorkqueue, &psEnvData->sMISRWork);
+
+ return PVRSRV_OK;
+}
+
+
+struct IMG_CPU_PHYADDR OSMapLinToCPUPhys(void *pvLinAddr)
+{
+ struct IMG_CPU_PHYADDR CpuPAddr;
+
+ CpuPAddr.uiAddr = (u32) VMallocToPhys(pvLinAddr);
+
+ return CpuPAddr;
+}
+
+void __iomem *OSMapPhysToLin(struct IMG_CPU_PHYADDR BasePAddr, u32 ui32Bytes,
+ u32 ui32MappingFlags, void **phOSMemHandle)
+{
+ if (phOSMemHandle)
+ *phOSMemHandle = (void *) 0;
+
+ if (ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) {
+ void __iomem *pvIORemapCookie;
+ pvIORemapCookie =
+ IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags);
+ if (pvIORemapCookie == NULL)
+ return NULL;
+ return pvIORemapCookie;
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSMapPhysToLin "
+ "should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ "(Use OSReservePhys otherwise)");
+ return NULL;
+ }
+
+}
+
+IMG_BOOL
+OSUnMapPhysToLin(void __iomem *pvLinAddr, u32 ui32Bytes,
+ u32 ui32MappingFlags, void *hPageAlloc)
+{
+ PVR_TRACE("%s: unmapping %d bytes from 0x%08x", __func__,
+ ui32Bytes, pvLinAddr);
+
+ PVR_UNREFERENCED_PARAMETER(hPageAlloc);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ if (ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY) {
+ IOUnmapWrapper(pvLinAddr);
+ return IMG_TRUE;
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSUnMapPhysToLin "
+ "should only be used with PVRSRV_HAP_KERNEL_ONLY "
+ " (Use OSUnReservePhys otherwise)");
+ return IMG_FALSE;
+ }
+
+}
+
+static enum PVRSRV_ERROR RegisterExternalMem(struct IMG_SYS_PHYADDR *pBasePAddr,
+ void *pvCPUVAddr, u32 ui32Bytes, IMG_BOOL bPhysContig,
+ u32 ui32MappingFlags, void **phOSMemHandle)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+
+ switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea =
+ NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
+ ui32Bytes, bPhysContig,
+ ui32MappingFlags);
+
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_GENERIC;
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+ psLinuxMemArea =
+ NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
+ ui32Bytes, bPhysContig,
+ ui32MappingFlags);
+
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_GENERIC;
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ psLinuxMemArea =
+ NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr,
+ ui32Bytes, bPhysContig,
+ ui32MappingFlags);
+
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_GENERIC;
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "OSRegisterMem : invalid flags 0x%x\n",
+ ui32MappingFlags);
+ *phOSMemHandle = (void *) 0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phOSMemHandle = (void *) psLinuxMemArea;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSRegisterMem(struct IMG_CPU_PHYADDR BasePAddr,
+ void *pvCPUVAddr, u32 ui32Bytes,
+ u32 ui32MappingFlags, void **phOSMemHandle)
+{
+ struct IMG_SYS_PHYADDR SysPAddr = SysCpuPAddrToSysPAddr(BasePAddr);
+
+ return RegisterExternalMem(&SysPAddr, pvCPUVAddr, ui32Bytes, IMG_TRUE,
+ ui32MappingFlags, phOSMemHandle);
+}
+
+enum PVRSRV_ERROR OSRegisterDiscontigMem(struct IMG_SYS_PHYADDR *pBasePAddr,
+ void *pvCPUVAddr, u32 ui32Bytes,
+ u32 ui32MappingFlags,
+ void **phOSMemHandle)
+{
+ return RegisterExternalMem(pBasePAddr, pvCPUVAddr, ui32Bytes,
+ IMG_FALSE, ui32MappingFlags, phOSMemHandle);
+}
+
+enum PVRSRV_ERROR OSUnRegisterMem(void *pvCpuVAddr, u32 ui32Bytes,
+ u32 ui32MappingFlags, void *hOSMemHandle)
+{
+ struct LinuxMemArea *psLinuxMemArea = (struct LinuxMemArea *)
+ hOSMemHandle;
+
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) !=
+ PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __func__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle);
+ BUG();
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSUnRegisterMem : invalid flags 0x%x",
+ ui32MappingFlags);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSUnRegisterDiscontigMem(void *pvCpuVAddr, u32 ui32Bytes,
+ u32 ui32Flags, void *hOSMemHandle)
+{
+ return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
+}
+
+enum PVRSRV_ERROR OSReservePhys(struct IMG_CPU_PHYADDR BasePAddr,
+ u32 ui32Bytes, u32 ui32MappingFlags, void **ppvCpuVAddr,
+ void **phOSMemHandle)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+
+ switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ {
+ psLinuxMemArea =
+ NewIORemapLinuxMemArea(BasePAddr, ui32Bytes,
+ ui32MappingFlags);
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_GENERIC;
+ break;
+ }
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ {
+ psLinuxMemArea =
+ NewIOLinuxMemArea(BasePAddr, ui32Bytes,
+ ui32MappingFlags);
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_GENERIC;
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ psLinuxMemArea =
+ NewIORemapLinuxMemArea(BasePAddr, ui32Bytes,
+ ui32MappingFlags);
+ if (!psLinuxMemArea)
+ return PVRSRV_ERROR_GENERIC;
+ PVRMMapRegisterArea(psLinuxMemArea);
+ break;
+ }
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "OSMapPhysToLin : invalid flags 0x%x\n",
+ ui32MappingFlags);
+ *ppvCpuVAddr = NULL;
+ *phOSMemHandle = (void *) 0;
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ *phOSMemHandle = (void *) psLinuxMemArea;
+ *ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSUnReservePhys(void *pvCpuVAddr,
+ u32 ui32Bytes, u32 ui32MappingFlags, void *hOSMemHandle)
+{
+ struct LinuxMemArea *psLinuxMemArea;
+ PVR_UNREFERENCED_PARAMETER(pvCpuVAddr);
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+
+ psLinuxMemArea = (struct LinuxMemArea *)hOSMemHandle;
+
+ switch (ui32MappingFlags & PVRSRV_HAP_MAPTYPE_MASK) {
+ case PVRSRV_HAP_KERNEL_ONLY:
+ break;
+ case PVRSRV_HAP_SINGLE_PROCESS:
+ case PVRSRV_HAP_MULTI_PROCESS:
+ {
+ if (PVRMMapRemoveRegisteredArea(psLinuxMemArea) !=
+ PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s(%p, %d, 0x%08X, %p) FAILED!",
+ __func__, pvCpuVAddr, ui32Bytes,
+ ui32MappingFlags, hOSMemHandle);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ break;
+ }
+ default:
+ {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSUnMapPhysToLin : invalid flags 0x%x",
+ ui32MappingFlags);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSBaseAllocContigMemory(u32 ui32Size, void **pvLinAddr,
+ struct IMG_CPU_PHYADDR *psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr);
+ PVR_DPF(PVR_DBG_ERROR, "%s: Not available", __func__);
+
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+#else
+ void *pvKernLinAddr;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ pvKernLinAddr = _KMallocWrapper(ui32Size, __FILE__, __LINE__);
+#else
+ pvKernLinAddr = KMallocWrapper(ui32Size);
+#endif
+ if (!pvKernLinAddr)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ *pvLinAddr = pvKernLinAddr;
+
+ psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
+
+ return PVRSRV_OK;
+#endif
+}
+
+enum PVRSRV_ERROR OSBaseFreeContigMemory(u32 ui32Size, void *pvLinAddr,
+ struct IMG_CPU_PHYADDR psPhysAddr)
+{
+#if !defined(NO_HARDWARE)
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ PVR_DPF(PVR_DBG_WARNING, "%s: Not available", __func__);
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+ PVR_UNREFERENCED_PARAMETER(psPhysAddr.uiAddr);
+
+ KFreeWrapper(pvLinAddr);
+#endif
+ return PVRSRV_OK;
+}
+
+u32 OSReadHWReg(void __iomem *pvLinRegBaseAddr, u32 ui32Offset)
+{
+#if !defined(NO_HARDWARE)
+ return (u32)readl(pvLinRegBaseAddr + ui32Offset);
+#else
+ return *(u32 *)((u8 *) pvLinRegBaseAddr + ui32Offset);
+#endif
+}
+
+void OSWriteHWReg(void __iomem *pvLinRegBaseAddr, u32 ui32Offset, u32 ui32Value)
+{
+#if !defined(NO_HARDWARE)
+ writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+#else
+ *(u32 *)((u8 *)pvLinRegBaseAddr + ui32Offset) = ui32Value;
+#endif
+}
+
+#define OS_MAX_TIMERS 8
+
+struct TIMER_CALLBACK_DATA {
+ IMG_BOOL bInUse;
+ void (*pfnTimerFunc)(void *);
+ void *pvData;
+ struct timer_list sTimer;
+ u32 ui32Delay;
+ IMG_BOOL bActive;
+};
+
+static struct TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
+static DEFINE_SPINLOCK(sTimerStructLock);
+static void OSTimerCallbackWrapper(unsigned long ui32Data)
+{
+ struct TIMER_CALLBACK_DATA *psTimerCBData =
+ (struct TIMER_CALLBACK_DATA *)ui32Data;
+
+ if (!psTimerCBData->bActive)
+ return;
+
+ psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
+
+ mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
+}
+
+void *OSAddTimer(void (*pfnTimerFunc)(void *), void *pvData, u32 ui32MsTimeout)
+{
+ struct TIMER_CALLBACK_DATA *psTimerCBData;
+ u32 ui32i;
+ unsigned long ulLockFlags;
+
+ if (!pfnTimerFunc) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAddTimer: passed invalid callback");
+ return NULL;
+ }
+
+ spin_lock_irqsave(&sTimerStructLock, ulLockFlags);
+ for (ui32i = 0; ui32i < OS_MAX_TIMERS; ui32i++) {
+ psTimerCBData = &sTimers[ui32i];
+ if (!psTimerCBData->bInUse) {
+ psTimerCBData->bInUse = IMG_TRUE;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&sTimerStructLock, ulLockFlags);
+
+ if (ui32i >= OS_MAX_TIMERS) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAddTimer: all timers are in use");
+ return NULL;
+ }
+
+ psTimerCBData->pfnTimerFunc = pfnTimerFunc;
+ psTimerCBData->pvData = pvData;
+ psTimerCBData->bActive = IMG_FALSE;
+
+ psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
+ ? 1 : ((HZ * ui32MsTimeout) / 1000);
+
+ init_timer(&psTimerCBData->sTimer);
+
+ psTimerCBData->sTimer.function = OSTimerCallbackWrapper;
+ psTimerCBData->sTimer.data = (u32) psTimerCBData;
+ psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
+
+ return (void *)(ui32i + 1);
+}
+
+static inline struct TIMER_CALLBACK_DATA *GetTimerStructure(void *hTimer)
+{
+ u32 ui32i = ((u32) hTimer) - 1;
+ PVR_ASSERT(ui32i < OS_MAX_TIMERS);
+ return &sTimers[ui32i];
+}
+
+enum PVRSRV_ERROR OSRemoveTimer(void *hTimer)
+{
+ struct TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+ /* free timer callback data struct */
+ psTimerCBData->bInUse = IMG_FALSE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSEnableTimer(void *hTimer)
+{
+ struct TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(!psTimerCBData->bActive);
+
+ psTimerCBData->bActive = IMG_TRUE;
+
+ add_timer(&psTimerCBData->sTimer);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSDisableTimer(void *hTimer)
+{
+ struct TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
+
+ PVR_ASSERT(psTimerCBData->bInUse);
+ PVR_ASSERT(psTimerCBData->bActive);
+
+ psTimerCBData->bActive = IMG_FALSE;
+
+ del_timer_sync(&psTimerCBData->sTimer);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSEventObjectCreate(const char *pszName,
+ struct PVRSRV_EVENTOBJECT *psEventObject)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psEventObject) {
+ if (pszName) {
+ strncpy(psEventObject->szName, pszName,
+ EVENTOBJNAME_MAXLENGTH);
+ } else {
+ static u16 ui16NameIndex;
+ snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH,
+ "PVRSRV_EVENTOBJECT_%d", ui16NameIndex++);
+ }
+
+ if (LinuxEventObjectListCreate(&psEventObject->hOSEventKM) !=
+ PVRSRV_OK)
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSEventObjectCreate: "
+ "psEventObject is not a valid pointer");
+ eError = PVRSRV_ERROR_GENERIC;
+ }
+
+ return eError;
+
+}
+
+enum PVRSRV_ERROR OSEventObjectDestroy(struct PVRSRV_EVENTOBJECT *psEventObject)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psEventObject) {
+ if (psEventObject->hOSEventKM) {
+ LinuxEventObjectListDestroy(psEventObject->hOSEventKM);
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSEventObjectDestroy: "
+ "hOSEventKM is not a valid pointer");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSEventObjectDestroy: "
+ "psEventObject is not a valid pointer");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR OSEventObjectWait(void *hOSEventKM)
+{
+ enum PVRSRV_ERROR eError;
+
+ if (hOSEventKM) {
+ eError =
+ LinuxEventObjectWait(hOSEventKM, EVENT_OBJECT_TIMEOUT_MS);
+ } else {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSEventObjectWait: hOSEventKM is not a valid handle");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR OSEventObjectOpen(struct PVRSRV_EVENTOBJECT *psEventObject,
+ void **phOSEvent)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psEventObject) {
+ if (LinuxEventObjectAdd(psEventObject->hOSEventKM, phOSEvent) !=
+ PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "LinuxEventObjectAdd: failed");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSEventObjectCreate: "
+ "psEventObject is not a valid pointer");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR OSEventObjectClose(struct PVRSRV_EVENTOBJECT *psEventObject,
+ void *hOSEventKM)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (psEventObject) {
+ if (LinuxEventObjectDelete
+ (psEventObject->hOSEventKM, hOSEventKM) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "LinuxEventObjectDelete: failed");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSEventObjectDestroy: "
+ "psEventObject is not a valid pointer");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+
+}
+
+enum PVRSRV_ERROR OSEventObjectSignal(void *hOSEventKM)
+{
+ enum PVRSRV_ERROR eError;
+
+ if (hOSEventKM) {
+ eError = LinuxEventObjectSignal(hOSEventKM);
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "OSEventObjectSignal: "
+ "hOSEventKM is not a valid handle");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return eError;
+}
+
+IMG_BOOL OSProcHasPrivSrvInit(void)
+{
+ return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
+}
+
+enum PVRSRV_ERROR OSCopyToUser(void *pvProcess, void __user *pvDest,
+ const void *pvSrc, u32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if (copy_to_user(pvDest, pvSrc, ui32Bytes) == 0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_GENERIC;
+}
+
+enum PVRSRV_ERROR OSCopyFromUser(void *pvProcess, void *pvDest,
+ const void __user *pvSrc, u32 ui32Bytes)
+{
+ PVR_UNREFERENCED_PARAMETER(pvProcess);
+
+ if (copy_from_user(pvDest, pvSrc, ui32Bytes) == 0)
+ return PVRSRV_OK;
+ else
+ return PVRSRV_ERROR_GENERIC;
+}
+
+IMG_BOOL OSAccessOK(enum IMG_VERIFY_TEST eVerification,
+ const void __user *pvUserPtr, u32 ui32Bytes)
+{
+ int linuxType;
+
+ if (eVerification == PVR_VERIFY_READ) {
+ linuxType = VERIFY_READ;
+ } else {
+ PVR_ASSERT(eVerification == PVR_VERIFY_WRITE);
+ linuxType = VERIFY_WRITE;
+ }
+
+ return access_ok(linuxType, pvUserPtr, ui32Bytes);
+}
+
+enum eWrapMemType {
+ WRAP_TYPE_CLEANUP,
+ WRAP_TYPE_GET_USER_PAGES,
+ WRAP_TYPE_FIND_VMA_PAGES,
+ WRAP_TYPE_FIND_VMA_PFN
+};
+
+struct sWrapMemInfo {
+ enum eWrapMemType eType;
+ int iNumPages;
+ struct page **ppsPages;
+ struct IMG_SYS_PHYADDR *psPhysAddr;
+ int iPageOffset;
+ int iContiguous;
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ u32 ulStartAddr;
+ u32 ulBeyondEndAddr;
+ struct vm_area_struct *psVMArea;
+#endif
+};
+
+static void CheckPagesContiguous(struct sWrapMemInfo *psInfo)
+{
+ int i;
+ u32 ui32AddrChk;
+
+ BUG_ON(psInfo == NULL);
+
+ psInfo->iContiguous = 1;
+
+ for (i = 0, ui32AddrChk = psInfo->psPhysAddr[0].uiAddr;
+ i < psInfo->iNumPages; i++, ui32AddrChk += PAGE_SIZE)
+ if (psInfo->psPhysAddr[i].uiAddr != ui32AddrChk) {
+ psInfo->iContiguous = 0;
+ break;
+ }
+}
+
+static struct page *CPUVAddrToPage(struct vm_area_struct *psVMArea,
+ u32 ulCPUVAddr)
+{
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ struct mm_struct *psMM = psVMArea->vm_mm;
+ u32 ulPFN;
+ spinlock_t *psPTLock;
+ struct page *psPage;
+
+ psPGD = pgd_offset(psMM, ulCPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ return NULL;
+
+ psPUD = pud_offset(psPGD, ulCPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ return NULL;
+
+ psPMD = pmd_offset(psPUD, ulCPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ return NULL;
+
+ psPage = NULL;
+
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ulCPUVAddr,
+ &psPTLock);
+ if ((pte_none(*psPTE) != 0) || (pte_present(*psPTE) == 0) ||
+ (pte_write(*psPTE) == 0))
+ goto exit_unlock;
+
+ ulPFN = pte_pfn(*psPTE);
+ if (!pfn_valid(ulPFN))
+ goto exit_unlock;
+
+ psPage = pfn_to_page(ulPFN);
+
+ get_page(psPage);
+
+exit_unlock:
+ pte_unmap_unlock(psPTE, psPTLock);
+
+ return psPage;
+}
+
+enum PVRSRV_ERROR OSReleasePhysPageAddr(void *hOSWrapMem)
+{
+ struct sWrapMemInfo *psInfo = (struct sWrapMemInfo *)hOSWrapMem;
+ int i;
+
+ BUG_ON(psInfo == NULL);
+
+ switch (psInfo->eType) {
+ case WRAP_TYPE_CLEANUP:
+ break;
+ case WRAP_TYPE_FIND_VMA_PFN:
+ break;
+ case WRAP_TYPE_GET_USER_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++) {
+ struct page *psPage = psInfo->ppsPages[i];
+
+ if (!PageReserved(psPage))
+ SetPageDirty(psPage);
+ page_cache_release(psPage);
+ }
+ break;
+ }
+ case WRAP_TYPE_FIND_VMA_PAGES:
+ {
+ for (i = 0; i < psInfo->iNumPages; i++)
+ put_page_testzero(psInfo->ppsPages[i]);
+ break;
+ }
+ default:
+ {
+ PVR_DPF(PVR_DBG_ERROR,
+ "OSReleasePhysPageAddr: Unknown wrap type (%d)",
+ psInfo->eType);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ if (psInfo->ppsPages != NULL)
+ kfree(psInfo->ppsPages);
+
+ if (psInfo->psPhysAddr != NULL)
+ kfree(psInfo->psPhysAddr);
+
+ kfree(psInfo);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSAcquirePhysPageAddr(void *pvCPUVAddr, u32 ui32Bytes,
+ struct IMG_SYS_PHYADDR *psSysPAddr,
+ void **phOSWrapMem)
+{
+ u32 ulStartAddrOrig = (u32) pvCPUVAddr;
+ u32 ulAddrRangeOrig = (u32) ui32Bytes;
+ u32 ulBeyondEndAddrOrig = ulStartAddrOrig + ulAddrRangeOrig;
+ u32 ulStartAddr;
+ u32 ulAddrRange;
+ u32 ulBeyondEndAddr;
+ u32 ulAddr;
+ int iNumPagesMapped;
+ int i;
+ struct vm_area_struct *psVMArea;
+ struct sWrapMemInfo *psInfo;
+
+ ulStartAddr = ulStartAddrOrig & PAGE_MASK;
+ ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
+ ulAddrRange = ulBeyondEndAddr - ulStartAddr;
+
+ psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
+ if (psInfo == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "Couldn't allocate information structure");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ memset(psInfo, 0, sizeof(*psInfo));
+
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ psInfo->ulStartAddr = ulStartAddrOrig;
+ psInfo->ulBeyondEndAddr = ulBeyondEndAddrOrig;
+#endif
+
+ psInfo->iNumPages = (int)(ulAddrRange >> PAGE_SHIFT);
+ psInfo->iPageOffset = (int)(ulStartAddrOrig & ~PAGE_MASK);
+
+ psInfo->psPhysAddr =
+ kmalloc((size_t) psInfo->iNumPages * sizeof(*psInfo->psPhysAddr),
+ GFP_KERNEL);
+ if (psInfo->psPhysAddr == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "Couldn't allocate page array");
+ goto error_free;
+ }
+
+ psInfo->ppsPages =
+ kmalloc((size_t) psInfo->iNumPages * sizeof(*psInfo->ppsPages),
+ GFP_KERNEL);
+ if (psInfo->ppsPages == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "Couldn't allocate page array");
+ goto error_free;
+ }
+
+ down_read(&current->mm->mmap_sem);
+
+ iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr,
+ psInfo->iNumPages, 1, 0,
+ psInfo->ppsPages, NULL);
+ up_read(&current->mm->mmap_sem);
+
+
+ if (iNumPagesMapped >= 0) {
+ if (iNumPagesMapped != psInfo->iNumPages) {
+ PVR_TRACE("OSAcquirePhysPageAddr: "
+ "Couldn't map all the pages needed "
+ "(wanted: %d, got %d)",
+ psInfo->iNumPages, iNumPagesMapped);
+
+ for (i = 0; i < iNumPagesMapped; i++)
+ page_cache_release(psInfo->ppsPages[i]);
+
+ goto error_free;
+ }
+
+ for (i = 0; i < psInfo->iNumPages; i++) {
+ struct IMG_CPU_PHYADDR CPUPhysAddr;
+
+ CPUPhysAddr.uiAddr =
+ page_to_pfn(psInfo->ppsPages[i]) << PAGE_SHIFT;
+ psInfo->psPhysAddr[i] =
+ SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+
+ }
+
+ psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
+
+ goto exit_check;
+ }
+
+ PVR_TRACE("OSAcquirePhysPageAddr: "
+ "get_user_pages failed (%d), trying something else",
+ iNumPagesMapped);
+
+ down_read(&current->mm->mmap_sem);
+
+ psVMArea = find_vma(current->mm, ulStartAddrOrig);
+ if (psVMArea == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "Couldn't find memory region "
+ "containing start address %lx",
+ ulStartAddrOrig);
+
+ goto error_release_mmap_sem;
+ }
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ psInfo->psVMArea = psVMArea;
+#endif
+
+ if (ulStartAddrOrig < psVMArea->vm_start) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "Start address %lx is outside of the "
+ "region returned by find_vma",
+ ulStartAddrOrig);
+ goto error_release_mmap_sem;
+ }
+
+ if (ulBeyondEndAddrOrig > psVMArea->vm_end) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "End address %lx is outside of the region "
+ "returned by find_vma",
+ ulBeyondEndAddrOrig);
+ goto error_release_mmap_sem;
+ }
+
+ if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) !=
+ (VM_IO | VM_RESERVED)) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "Memory region does not represent memory "
+ "mapped I/O (VMA flags: 0x%lx)",
+ psVMArea->vm_flags);
+ goto error_release_mmap_sem;
+ }
+
+ if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) !=
+ (VM_READ | VM_WRITE)) {
+ PVR_DPF(PVR_DBG_ERROR, "OSAcquirePhysPageAddr: "
+ "No read/write access to memory region "
+ "(VMA flags: 0x%lx)",
+ psVMArea->vm_flags);
+ goto error_release_mmap_sem;
+ }
+
+ for (ulAddr = ulStartAddrOrig, i = 0; ulAddr < ulBeyondEndAddrOrig;
+ ulAddr += PAGE_SIZE, i++) {
+ struct page *psPage;
+
+ BUG_ON(i >= psInfo->iNumPages);
+
+ psPage = CPUVAddrToPage(psVMArea, ulAddr);
+ if (psPage == NULL) {
+ int j;
+
+ PVR_TRACE("OSAcquirePhysPageAddr: "
+ "Couldn't lookup page structure "
+ "for address 0x%lx, trying something else",
+ ulAddr);
+
+ for (j = 0; j < i; j++)
+ put_page_testzero(psInfo->ppsPages[j]);
+ break;
+ }
+
+ psInfo->ppsPages[i] = psPage;
+ }
+
+ BUG_ON(i > psInfo->iNumPages);
+ if (i == psInfo->iNumPages) {
+ for (i = 0; i < psInfo->iNumPages; i++) {
+ struct page *psPage = psInfo->ppsPages[i];
+ struct IMG_CPU_PHYADDR CPUPhysAddr;
+
+ CPUPhysAddr.uiAddr = page_to_pfn(psPage) << PAGE_SHIFT;
+
+ psInfo->psPhysAddr[i] =
+ SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA_PAGES;
+ } else {
+
+ if ((psVMArea->vm_flags & VM_PFNMAP) == 0) {
+ PVR_DPF(PVR_DBG_WARNING, "OSAcquirePhysPageAddr: "
+ "Region isn't a raw PFN mapping. "
+ "Giving up.");
+ goto error_release_mmap_sem;
+ }
+
+ for (ulAddr = ulStartAddrOrig, i = 0;
+ ulAddr < ulBeyondEndAddrOrig; ulAddr += PAGE_SIZE, i++) {
+ struct IMG_CPU_PHYADDR CPUPhysAddr;
+
+ CPUPhysAddr.uiAddr = ((ulAddr - psVMArea->vm_start) +
+ (psVMArea->vm_pgoff << PAGE_SHIFT)) & PAGE_MASK;
+
+ psInfo->psPhysAddr[i] =
+ SysCpuPAddrToSysPAddr(CPUPhysAddr);
+ psSysPAddr[i] = psInfo->psPhysAddr[i];
+ }
+ BUG_ON(i != psInfo->iNumPages);
+
+ psInfo->eType = WRAP_TYPE_FIND_VMA_PFN;
+
+ PVR_DPF(PVR_DBG_WARNING, "OSAcquirePhysPageAddr: "
+ "Region can't be locked down");
+ }
+
+ up_read(&current->mm->mmap_sem);
+
+exit_check:
+ CheckPagesContiguous(psInfo);
+
+ *phOSWrapMem = (void *) psInfo;
+
+ return PVRSRV_OK;
+
+error_release_mmap_sem:
+ up_read(&current->mm->mmap_sem);
+
+error_free:
+ psInfo->eType = WRAP_TYPE_CLEANUP;
+ OSReleasePhysPageAddr((void *)psInfo);
+ return PVRSRV_ERROR_GENERIC;
+}
diff --git a/drivers/gpu/pvr/osfunc.h b/drivers/gpu/pvr/osfunc.h
new file mode 100644
index 00000000000..2d79af9788f
--- /dev/null
+++ b/drivers/gpu/pvr/osfunc.h
@@ -0,0 +1,216 @@
+/**********************************************************************
+ *
+ * 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 __OSFUNC_H__
+#define __OSFUNC_H__
+
+#if defined(__KERNEL__)
+#include <linux/hardirq.h>
+#include <linux/string.h>
+#endif
+
+#define PVRSRV_PAGEABLE_SELECT PVRSRV_OS_PAGEABLE_HEAP
+
+#define KERNEL_ID 0xffffffffL
+#define POWER_MANAGER_ID 0xfffffffeL
+#define ISR_ID 0xfffffffdL
+#define TIMER_ID 0xfffffffcL
+
+#define HOST_PAGESIZE OSGetPageSize
+#define HOST_PAGEMASK (~(HOST_PAGESIZE()-1))
+
+#define HOST_PAGEALIGN(addr) (((addr) + HOST_PAGESIZE() - 1) & \
+ HOST_PAGEMASK)
+
+#define PVRSRV_OS_HEAP_MASK 0xf
+#define PVRSRV_OS_PAGEABLE_HEAP 0x1
+#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2
+
+u32 OSClockus(void);
+u32 OSGetPageSize(void);
+enum PVRSRV_ERROR OSInstallDeviceLISR(void *pvSysData, u32 ui32Irq,
+ char *pszISRName, void *pvDeviceNode);
+enum PVRSRV_ERROR OSUninstallDeviceLISR(void *pvSysData);
+enum PVRSRV_ERROR OSInstallSystemLISR(void *pvSysData, u32 ui32Irq);
+enum PVRSRV_ERROR OSUninstallSystemLISR(void *pvSysData);
+enum PVRSRV_ERROR OSInstallMISR(void *pvSysData);
+enum PVRSRV_ERROR OSUninstallMISR(void *pvSysData);
+enum PVRSRV_ERROR OSInitPerf(void *pvSysData);
+enum PVRSRV_ERROR OSCleanupPerf(void *pvSysData);
+struct IMG_CPU_PHYADDR OSMapLinToCPUPhys(void *pvLinAddr);
+void OSMemCopy(void *pvDst, void *pvSrc, u32 ui32Size);
+void __iomem *OSMapPhysToLin(struct IMG_CPU_PHYADDR BasePAddr,
+ u32 ui32Bytes, u32 ui32MappingFlags, void **phOSMemHandle);
+IMG_BOOL OSUnMapPhysToLin(void __iomem *pvLinAddr, u32 ui32Bytes,
+ u32 ui32MappingFlags, void *hPageAlloc);
+
+enum PVRSRV_ERROR OSReservePhys(struct IMG_CPU_PHYADDR BasePAddr, u32 ui32Bytes,
+ u32 ui32Flags, void **ppvCpuVAddr, void **phOSMemHandle);
+enum PVRSRV_ERROR OSUnReservePhys(void *pvCpuVAddr, u32 ui32Bytes,
+ u32 ui32Flags, void *hOSMemHandle);
+
+enum PVRSRV_ERROR OSRegisterDiscontigMem(struct IMG_SYS_PHYADDR *pBasePAddr,
+ void *pvCpuVAddr, u32 ui32Bytes, u32 ui32Flags,
+ void **phOSMemHandle);
+enum PVRSRV_ERROR OSUnRegisterDiscontigMem(void *pvCpuVAddr, u32 ui32Bytes,
+ u32 ui32Flags, void *hOSMemHandle);
+
+static inline enum PVRSRV_ERROR OSReserveDiscontigPhys(
+ struct IMG_SYS_PHYADDR *pBasePAddr, u32 ui32Bytes,
+ u32 ui32Flags, void **ppvCpuVAddr, void **phOSMemHandle)
+{
+ *ppvCpuVAddr = NULL;
+ return OSRegisterDiscontigMem(pBasePAddr, *ppvCpuVAddr, ui32Bytes,
+ ui32Flags, phOSMemHandle);
+}
+
+static inline enum PVRSRV_ERROR OSUnReserveDiscontigPhys(void *pvCpuVAddr,
+ u32 ui32Bytes, u32 ui32Flags, void *hOSMemHandle)
+{
+ OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags,
+ hOSMemHandle);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSRegisterMem(struct IMG_CPU_PHYADDR BasePAddr,
+ void *pvCpuVAddr, u32 ui32Bytes, u32 ui32Flags,
+ void **phOSMemHandle);
+enum PVRSRV_ERROR OSUnRegisterMem(void *pvCpuVAddr, u32 ui32Bytes,
+ u32 ui32Flags, void *hOSMemHandle);
+
+enum PVRSRV_ERROR OSGetSubMemHandle(void *hOSMemHandle, u32 ui32ByteOffset,
+ u32 ui32Bytes, u32 ui32Flags, void **phOSMemHandleRet);
+enum PVRSRV_ERROR OSReleaseSubMemHandle(void *hOSMemHandle, u32 ui32Flags);
+
+u32 OSGetCurrentProcessIDKM(void);
+u32 OSGetCurrentThreadID(void);
+void OSMemSet(void *pvDest, u8 ui8Value, u32 ui32Size);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+enum PVRSRV_ERROR _OSAllocMem(u32 ui32Flags, u32 ui32Size, void **ppvLinAddr,
+ void **phBlockAlloc, char *pszFilename, u32 ui32Line);
+#define OSAllocMem(ui32Flags, ui32Size, ppvLinAddr, phBlockAlloc) \
+ _OSAllocMem(ui32Flags, ui32Size, ppvLinAddr, phBlockAlloc, \
+ __FILE__, __LINE__)
+void _OSFreeMem(u32 ui32Flags, u32 ui32Size, void *pvLinAddr,
+ void *hBlockAlloc, char *pszFilename, u32 ui32Line);
+#define OSFreeMem(ui32Flags, ui32Size, pvLinAddr, phBlockAlloc) \
+ _OSFreeMem(ui32Flags, ui32Size, pvLinAddr, phBlockAlloc, \
+ __FILE__, __LINE__)
+#else
+enum PVRSRV_ERROR OSAllocMem(u32 ui32Flags, u32 ui32Size, void **ppvLinAddr,
+ void **phBlockAlloc);
+void OSFreeMem(u32 ui32Flags, u32 ui32Size, void *pvLinAddr, void *hBlockAlloc);
+#endif
+enum PVRSRV_ERROR OSAllocPages(u32 ui32Flags, u32 ui32Size, u32 ui32PageSize,
+ void **ppvLinAddr, void **phPageAlloc);
+enum PVRSRV_ERROR OSFreePages(u32 ui32Flags, u32 ui32Size, void *pvLinAddr,
+ void *hPageAlloc);
+struct IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(void *hOSMemHandle,
+ u32 ui32ByteOffset);
+enum PVRSRV_ERROR OSInitEnvData(void **ppvEnvSpecificData);
+enum PVRSRV_ERROR OSDeInitEnvData(void *pvEnvSpecificData);
+char *OSStringCopy(char *pszDest, const char *pszSrc);
+s32 OSSNPrintf(char *pStr, u32 ui32Size, const char *pszFormat, ...);
+#define OSStringLength(pszString) strlen(pszString)
+
+enum PVRSRV_ERROR OSEventObjectCreate(const char *pszName,
+ struct PVRSRV_EVENTOBJECT *psEventObject);
+enum PVRSRV_ERROR OSEventObjectDestroy(
+ struct PVRSRV_EVENTOBJECT *psEventObject);
+enum PVRSRV_ERROR OSEventObjectSignal(void *hOSEventKM);
+enum PVRSRV_ERROR OSEventObjectWait(void *hOSEventKM);
+enum PVRSRV_ERROR OSEventObjectOpen(struct PVRSRV_EVENTOBJECT *psEventObject,
+ void **phOSEvent);
+enum PVRSRV_ERROR OSEventObjectClose(struct PVRSRV_EVENTOBJECT *psEventObject,
+ void *hOSEventKM);
+
+enum PVRSRV_ERROR OSBaseAllocContigMemory(u32 ui32Size, void **pLinAddr,
+ struct IMG_CPU_PHYADDR *pPhysAddr);
+enum PVRSRV_ERROR OSBaseFreeContigMemory(u32 ui32Size, void *LinAddr,
+ struct IMG_CPU_PHYADDR PhysAddr);
+
+void *MapUserFromKernel(void *pvLinAddrKM, u32 ui32Size, void **phMemBlock);
+void *OSMapHWRegsIntoUserSpace(void *hDevCookie,
+ struct IMG_SYS_PHYADDR sRegAddr, u32 ulSize, void **ppvProcess);
+void OSUnmapHWRegsFromUserSpace(void *hDevCookie, void *pvUserAddr,
+ void *pvProcess);
+
+void UnmapUserFromKernel(void *pvLinAddrUM, u32 ui32Size, void *hMemBlock);
+
+enum PVRSRV_ERROR OSMapPhysToUserSpace(void *hDevCookie,
+ struct IMG_SYS_PHYADDR sCPUPhysAddr, u32 uiSizeInBytes,
+ u32 ui32CacheFlags, void **ppvUserAddr, u32 *puiActualSize,
+ void *hMappingHandle);
+
+enum PVRSRV_ERROR OSUnmapPhysToUserSpace(void *hDevCookie, void *pvUserAddr,
+ void *pvProcess);
+
+void OSWaitus(u32 ui32Timeus);
+void OSReleaseThreadQuanta(void);
+
+u32 OSReadHWReg(void __iomem *pvLinRegBaseAddr, u32 ui32Offset);
+void OSWriteHWReg(void __iomem *pvLinRegBaseAddr, u32 ui32Offset,
+ u32 ui32Value);
+
+void *OSAddTimer(void (*pfnTimerFunc)(void *), void *pvData, u32 ui32MsTimeout);
+enum PVRSRV_ERROR OSRemoveTimer(void *hTimer);
+enum PVRSRV_ERROR OSEnableTimer(void *hTimer);
+enum PVRSRV_ERROR OSDisableTimer(void *hTimer);
+
+enum PVRSRV_ERROR OSGetSysMemSize(u32 *pui32Bytes);
+
+enum HOST_PCI_INIT_FLAGS {
+ HOST_PCI_INIT_FLAG_BUS_MASTER = 0x00000001,
+ HOST_PCI_INIT_FLAG_MSI = 0x00000002,
+ HOST_PCI_INIT_FLAG_FORCE_I32 = 0x7fffffff
+};
+
+enum PVRSRV_ERROR OSScheduleMISR(void *pvSysData);
+
+IMG_BOOL OSProcHasPrivSrvInit(void);
+
+enum IMG_VERIFY_TEST {
+ PVR_VERIFY_WRITE = 0,
+ PVR_VERIFY_READ
+};
+
+IMG_BOOL OSAccessOK(enum IMG_VERIFY_TEST eVerification,
+ const void __user *pvUserPtr, u32 ui32Bytes);
+
+enum PVRSRV_ERROR OSCopyToUser(void *pvProcess, void __user *pvDest,
+ const void *pvSrc, u32 ui32Bytes);
+enum PVRSRV_ERROR OSCopyFromUser(void *pvProcess, void *pvDest,
+ const void __user *pvSrc, u32 ui32Bytes);
+
+enum PVRSRV_ERROR OSAcquirePhysPageAddr(void *pvCPUVAddr, u32 ui32Bytes,
+ struct IMG_SYS_PHYADDR *psSysPAddr,
+ void **phOSWrapMem);
+enum PVRSRV_ERROR OSReleasePhysPageAddr(void *hOSWrapMem);
+
+#endif
diff --git a/drivers/gpu/pvr/osperproc.c b/drivers/gpu/pvr/osperproc.c
new file mode 100644
index 00000000000..dffd3172d27
--- /dev/null
+++ b/drivers/gpu/pvr/osperproc.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 "services_headers.h"
+#include "osperproc.h"
+
+#include "env_perproc.h"
+#include "proc.h"
+
+enum PVRSRV_ERROR OSPerProcessPrivateDataInit(void **phOsPrivateData)
+{
+ enum PVRSRV_ERROR eError;
+ void *hBlockAlloc;
+ struct PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_ENV_PER_PROCESS_DATA),
+ phOsPrivateData, &hBlockAlloc);
+
+ if (eError != PVRSRV_OK) {
+ *phOsPrivateData = NULL;
+
+ PVR_DPF(PVR_DBG_ERROR, "%s: OSAllocMem failed (%d)", __func__,
+ eError);
+ return eError;
+ }
+
+ psEnvPerProc = (struct PVRSRV_ENV_PER_PROCESS_DATA *)*phOsPrivateData;
+ OSMemSet(psEnvPerProc, 0, sizeof(*psEnvPerProc));
+
+ psEnvPerProc->hBlockAlloc = hBlockAlloc;
+
+ LinuxMMapPerProcessConnect(psEnvPerProc);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSPerProcessPrivateDataDeInit(void *hOsPrivateData)
+{
+ struct PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc;
+
+ if (hOsPrivateData == NULL)
+ return PVRSRV_OK;
+
+ psEnvPerProc = (struct PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
+
+ LinuxMMapPerProcessDisconnect(psEnvPerProc);
+
+ RemovePerProcessProcDir(psEnvPerProc);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_ENV_PER_PROCESS_DATA),
+ hOsPrivateData, psEnvPerProc->hBlockAlloc);
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSPerProcessSetHandleOptions(struct PVRSRV_HANDLE_BASE
+ *psHandleBase)
+{
+ return LinuxMMapPerProcessHandleOptions(psHandleBase);
+}
diff --git a/drivers/gpu/pvr/osperproc.h b/drivers/gpu/pvr/osperproc.h
new file mode 100644
index 00000000000..891ab66b782
--- /dev/null
+++ b/drivers/gpu/pvr/osperproc.h
@@ -0,0 +1,36 @@
+/**********************************************************************
+ *
+ * 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 __OSPERPROC_H__
+#define __OSPERPROC_H__
+
+enum PVRSRV_ERROR OSPerProcessPrivateDataInit(void **phOsPrivateData);
+enum PVRSRV_ERROR OSPerProcessPrivateDataDeInit(void *hOsPrivateData);
+
+enum PVRSRV_ERROR OSPerProcessSetHandleOptions(
+ struct PVRSRV_HANDLE_BASE *psHandleBase);
+
+#endif
diff --git a/drivers/gpu/pvr/pb.c b/drivers/gpu/pvr/pb.c
new file mode 100644
index 00000000000..ffd8f69eecf
--- /dev/null
+++ b/drivers/gpu/pvr/pb.c
@@ -0,0 +1,419 @@
+/**********************************************************************
+ *
+ * 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 "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "pdump_km.h"
+#include "sgxutils.h"
+
+static struct RESMAN_ITEM *psResItemCreateSharedPB;
+static struct PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB;
+
+static enum PVRSRV_ERROR SGXCleanupSharedPBDescCallback(void *pvParam,
+ u32 ui32Param);
+static enum PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(void *pvParam,
+ u32 ui32Param);
+
+enum PVRSRV_ERROR SGXFindSharedPBDescKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevCookie, IMG_BOOL bLockOnFailure,
+ u32 ui32TotalPBSize, void **phSharedPBDesc,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ u32 *ui32SharedPBDescSubKernelMemInfosCount)
+{
+ struct PVRSRV_STUB_PBDESC *psStubPBDesc;
+ struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos = NULL;
+ struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ enum PVRSRV_ERROR eError;
+
+ psSGXDevInfo = ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != NULL) {
+ u32 i;
+ struct RESMAN_ITEM *psResItem;
+
+ if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) {
+ PVR_DPF(PVR_DBG_WARNING, "SGXFindSharedPBDescKM: "
+ "Shared PB requested with different size "
+ "(0x%x) from existing shared PB (0x%x) - "
+ "requested size ignored",
+ ui32TotalPBSize,
+ psStubPBDesc->ui32TotalPBSize);
+ }
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
+ psStubPBDesc->ui32SubKernelMemInfosCount,
+ (void **) &ppsSharedPBDescSubKernelMemInfos,
+ NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXFindSharedPBDescKM: OSAllocMem failed");
+
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto ExitNotFound;
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc, 0,
+ &SGXCleanupSharedPBDescCallback);
+
+ if (psResItem == NULL) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO *)*
+ psStubPBDesc->ui32SubKernelMemInfosCount,
+ ppsSharedPBDescSubKernelMemInfos, NULL);
+
+ PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM: "
+ "ResManRegisterRes failed");
+ eError = PVRSRV_ERROR_GENERIC;
+ goto ExitNotFound;
+ }
+
+ *ppsSharedPBDescKernelMemInfo =
+ psStubPBDesc->psSharedPBDescKernelMemInfo;
+ *ppsHWPBDescKernelMemInfo =
+ psStubPBDesc->psHWPBDescKernelMemInfo;
+ *ppsBlockKernelMemInfo =
+ psStubPBDesc->psBlockKernelMemInfo;
+
+ *ui32SharedPBDescSubKernelMemInfosCount =
+ psStubPBDesc->ui32SubKernelMemInfosCount;
+
+ *pppsSharedPBDescSubKernelMemInfos =
+ ppsSharedPBDescSubKernelMemInfos;
+
+ for (i = 0;
+ i < psStubPBDesc->ui32SubKernelMemInfosCount;
+ i++) {
+ ppsSharedPBDescSubKernelMemInfos[i] =
+ psStubPBDesc->ppsSubKernelMemInfos[i];
+ }
+
+ psStubPBDesc->ui32RefCount++;
+ *phSharedPBDesc = (void *) psResItem;
+ return PVRSRV_OK;
+ }
+
+ eError = PVRSRV_OK;
+ if (bLockOnFailure) {
+ if (psResItemCreateSharedPB == NULL) {
+ psResItemCreateSharedPB =
+ ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ psPerProc, 0,
+ &SGXCleanupSharedPBDescCreateLockCallback);
+
+ if (psResItemCreateSharedPB == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXFindSharedPBDescKM: "
+ "ResManRegisterRes failed");
+
+ eError = PVRSRV_ERROR_GENERIC;
+ goto ExitNotFound;
+ }
+ PVR_ASSERT(psPerProcCreateSharedPB == NULL);
+ psPerProcCreateSharedPB = psPerProc;
+ } else {
+ eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
+ }
+ }
+ExitNotFound:
+ *phSharedPBDesc = NULL;
+
+ return eError;
+}
+
+static enum PVRSRV_ERROR SGXCleanupSharedPBDescKM(
+ struct PVRSRV_STUB_PBDESC *psStubPBDescIn)
+{
+ struct PVRSRV_STUB_PBDESC **ppsStubPBDesc;
+ u32 i;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)psStubPBDescIn->hDevCookie;
+ psSGXDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ for (ppsStubPBDesc = (struct PVRSRV_STUB_PBDESC **)
+ &psSGXDevInfo->psStubPBDescListKM;
+ *ppsStubPBDesc != NULL;
+ ppsStubPBDesc = &(*ppsStubPBDesc)->psNext) {
+ struct PVRSRV_STUB_PBDESC *psStubPBDesc = *ppsStubPBDesc;
+
+ if (psStubPBDesc == psStubPBDescIn) {
+ psStubPBDesc->ui32RefCount--;
+ PVR_ASSERT((s32) psStubPBDesc->ui32RefCount >= 0);
+
+ if (psStubPBDesc->ui32RefCount == 0) {
+ *ppsStubPBDesc = psStubPBDesc->psNext;
+
+ for (i = 0;
+ i < psStubPBDesc->ui32SubKernelMemInfosCount;
+ i++)
+ PVRSRVFreeDeviceMemKM(psStubPBDesc->
+ hDevCookie,
+ psStubPBDesc->ppsSubKernelMemInfos[i]);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO *)*
+ psStubPBDesc->
+ ui32SubKernelMemInfosCount,
+ psStubPBDesc->ppsSubKernelMemInfos,
+ NULL);
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
+ psBlockKernelMemInfo);
+
+ PVRSRVFreeDeviceMemKM(psStubPBDesc->hDevCookie,
+ psStubPBDesc->
+ psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psStubPBDesc->
+ psSharedPBDescKernelMemInfo);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_STUB_PBDESC),
+ psStubPBDesc, NULL);
+
+ SGXCleanupRequest(psDeviceNode, NULL,
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_SHAREDPBDESC);
+ }
+ return PVRSRV_OK;
+ }
+ }
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
+
+static enum PVRSRV_ERROR SGXCleanupSharedPBDescCallback(void *pvParam,
+ u32 ui32Param)
+{
+ struct PVRSRV_STUB_PBDESC *psStubPBDesc =
+ (struct PVRSRV_STUB_PBDESC *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ return SGXCleanupSharedPBDescKM(psStubPBDesc);
+}
+
+static enum PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(void *pvParam,
+ u32 ui32Param)
+{
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc =
+ (struct PVRSRV_PER_PROCESS_DATA *)pvParam;
+ PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
+#else
+ PVR_UNREFERENCED_PARAMETER(pvParam);
+#endif
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ psPerProcCreateSharedPB = NULL;
+ psResItemCreateSharedPB = NULL;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXUnrefSharedPBDescKM(void *hSharedPBDesc)
+{
+ PVR_ASSERT(hSharedPBDesc != NULL);
+
+ ResManFreeResByPtr(hSharedPBDesc);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXAddSharedPBDescKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevCookie,
+ struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ u32 ui32TotalPBSize, void **phSharedPBDesc,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos,
+ u32 ui32SharedPBDescSubKernelMemInfosCount)
+{
+ struct PVRSRV_STUB_PBDESC *psStubPBDesc = NULL;
+ enum PVRSRV_ERROR eRet = PVRSRV_ERROR_GENERIC;
+ u32 i;
+ struct PVRSRV_SGXDEV_INFO *psSGXDevInfo;
+ struct RESMAN_ITEM *psResItem;
+
+ if (psPerProcCreateSharedPB != psPerProc) {
+ goto NoAdd;
+ } else {
+ PVR_ASSERT(psResItemCreateSharedPB != NULL);
+
+ ResManFreeResByPtr(psResItemCreateSharedPB);
+
+ PVR_ASSERT(psResItemCreateSharedPB == NULL);
+ PVR_ASSERT(psPerProcCreateSharedPB == NULL);
+ }
+
+ psSGXDevInfo = (struct PVRSRV_SGXDEV_INFO *)
+ ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
+ if (psStubPBDesc != NULL) {
+ if (psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize) {
+ PVR_DPF(PVR_DBG_WARNING, "SGXAddSharedPBDescKM: "
+ "Shared PB requested with different size "
+ "(0x%x) from existing shared PB (0x%x) - "
+ "requested size ignored",
+ ui32TotalPBSize,
+ psStubPBDesc->ui32TotalPBSize);
+
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc, 0,
+ &SGXCleanupSharedPBDescCallback);
+ if (psResItem == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXAddSharedPBDescKM: "
+ "Failed to register existing shared "
+ "PBDesc with the resource manager");
+ goto NoAddKeepPB;
+ }
+
+ psStubPBDesc->ui32RefCount++;
+
+ *phSharedPBDesc = (void *) psResItem;
+ eRet = PVRSRV_OK;
+ goto NoAddKeepPB;
+ }
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_STUB_PBDESC),
+ (void **)&psStubPBDesc, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
+ "StubPBDesc");
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+ psStubPBDesc->ppsSubKernelMemInfos = NULL;
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
+ ui32SharedPBDescSubKernelMemInfosCount,
+ (void **)&psStubPBDesc->ppsSubKernelMemInfos, NULL) !=
+ PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to alloc "
+ "StubPBDesc->ppsSubKernelMemInfos");
+ eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto NoAdd;
+ }
+
+ if (PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ goto NoAdd;
+
+ if (PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
+ != PVRSRV_OK)
+ goto NoAdd;
+
+ if (PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
+ != PVRSRV_OK)
+ goto NoAdd;
+
+ psStubPBDesc->ui32RefCount = 1;
+ psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
+ psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
+ psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
+ psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
+
+ psStubPBDesc->ui32SubKernelMemInfosCount =
+ ui32SharedPBDescSubKernelMemInfosCount;
+ for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++) {
+ psStubPBDesc->ppsSubKernelMemInfos[i] =
+ ppsSharedPBDescSubKernelMemInfos[i];
+ if (PVRSRVDissociateMemFromResmanKM
+ (ppsSharedPBDescSubKernelMemInfos[i]) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to dissociate shared PBDesc "
+ "from process");
+ goto NoAdd;
+ }
+ }
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_SHARED_PB_DESC,
+ psStubPBDesc,
+ 0, &SGXCleanupSharedPBDescCallback);
+ if (psResItem == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
+ "Failed to register shared PBDesc "
+ " with the resource manager");
+ goto NoAdd;
+ }
+ psStubPBDesc->hDevCookie = hDevCookie;
+
+ psStubPBDesc->psNext = psSGXDevInfo->psStubPBDescListKM;
+ psSGXDevInfo->psStubPBDescListKM = psStubPBDesc;
+
+ *phSharedPBDesc = (void *) psResItem;
+
+ return PVRSRV_OK;
+
+NoAdd:
+ if (psStubPBDesc) {
+ if (psStubPBDesc->ppsSubKernelMemInfos) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_KERNEL_MEM_INFO *) *
+ ui32SharedPBDescSubKernelMemInfosCount,
+ psStubPBDesc->ppsSubKernelMemInfos, NULL);
+ }
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_STUB_PBDESC), psStubPBDesc,
+ NULL);
+ }
+
+NoAddKeepPB:
+ for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
+ PVRSRVFreeDeviceMemKM(hDevCookie,
+ ppsSharedPBDescSubKernelMemInfos[i]);
+
+ PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
+ PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
+
+ PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
+
+ return eRet;
+}
diff --git a/drivers/gpu/pvr/pdump.c b/drivers/gpu/pvr/pdump.c
new file mode 100644
index 00000000000..0dec52f187f
--- /dev/null
+++ b/drivers/gpu/pvr/pdump.c
@@ -0,0 +1,1271 @@
+/**********************************************************************
+ *
+ * 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 <asm/atomic.h>
+#include <stdarg.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+
+#include "pvrversion.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "sgxmmu.h"
+#include "mm.h"
+#include "pdump_km.h"
+
+#include <linux/tty.h>
+
+static IMG_BOOL PDumpWriteString2(char *pszString, u32 ui32Flags);
+static IMG_BOOL PDumpWriteILock(struct DBG_STREAM *psStream, u8 *pui8Data,
+ u32 ui32Count, u32 ui32Flags);
+static void DbgSetFrame(struct DBG_STREAM *psStream, u32 ui32Frame);
+static u32 DbgGetFrame(struct DBG_STREAM *psStream);
+static void DbgSetMarker(struct DBG_STREAM *psStream, u32 ui32Marker);
+static u32 DbgWrite(struct DBG_STREAM *psStream, u8 *pui8Data,
+ u32 ui32BCount, u32 ui32Flags);
+
+#define PDUMP_DATAMASTER_PIXEL 1
+
+#define MIN(a, b) (a > b ? b : a)
+
+#define MAX_FILE_SIZE 0x40000000
+
+static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
+
+static struct DBGKM_SERVICE_TABLE *gpfnDbgDrv;
+
+#define PDUMP_STREAM_PARAM2 0
+#define PDUMP_STREAM_SCRIPT2 1
+#define PDUMP_STREAM_DRIVERINFO 2
+#define PDUMP_NUM_STREAMS 3
+
+static char *pszStreamName[PDUMP_NUM_STREAMS] = { "ParamStream2",
+ "ScriptStream2",
+ "DriverInfoStream"
+};
+
+#define __PDBG_PDUMP_STATE_GET_MSG_STRING(ERROR) \
+ char *pszMsg = gsDBGPdumpState.pszMsg; \
+ if ((!pszMsg) || PDumpSuspended()) \
+ return ERROR
+
+#define __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(ERROR) \
+ char *pszScript = gsDBGPdumpState.pszScript; \
+ if ((!pszScript) || PDumpSuspended()) \
+ return ERROR
+
+#define __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(ERROR) \
+ char *pszScript = gsDBGPdumpState.pszScript; \
+ char *pszFile = gsDBGPdumpState.pszFile; \
+ if ((!pszScript) || (!pszFile) || PDumpSuspended()) \
+ return ERROR
+
+struct PDBG_PDUMP_STATE {
+ struct DBG_STREAM *psStream[PDUMP_NUM_STREAMS];
+ u32 ui32ParamFileNum;
+
+ char *pszMsg;
+ char *pszScript;
+ char *pszFile;
+
+};
+
+static struct PDBG_PDUMP_STATE gsDBGPdumpState = {
+ {NULL}, 0, NULL, NULL, NULL
+};
+
+#define SZ_MSG_SIZE_MAX (PVRSRV_PDUMP_MAX_COMMENT_SIZE - 1)
+#define SZ_SCRIPT_SIZE_MAX (PVRSRV_PDUMP_MAX_COMMENT_SIZE - 1)
+#define SZ_FILENAME_SIZE_MAX (PVRSRV_PDUMP_MAX_COMMENT_SIZE - 1)
+
+static inline IMG_BOOL PDumpSuspended(void)
+{
+ return atomic_read(&gsPDumpSuspended) != 0;
+}
+
+void PDumpInit(void)
+{
+ u32 i = 0;
+
+ if (!gpfnDbgDrv) {
+ DBGDrvGetServiceTable((void **) &gpfnDbgDrv);
+
+ if (gpfnDbgDrv == NULL)
+ return;
+
+ if (!gsDBGPdumpState.pszFile)
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ SZ_FILENAME_SIZE_MAX,
+ (void **)&gsDBGPdumpState.pszFile,
+ NULL) != PVRSRV_OK)
+ goto init_failed;
+
+ if (!gsDBGPdumpState.pszMsg)
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ SZ_MSG_SIZE_MAX,
+ (void **)&gsDBGPdumpState.pszMsg,
+ NULL) != PVRSRV_OK)
+ goto init_failed;
+
+ if (!gsDBGPdumpState.pszScript)
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ SZ_SCRIPT_SIZE_MAX,
+ (void **)&gsDBGPdumpState.pszScript,
+ NULL) != PVRSRV_OK)
+ goto init_failed;
+
+ for (i = 0; i < PDUMP_NUM_STREAMS; i++) {
+ gsDBGPdumpState.psStream[i] =
+ gpfnDbgDrv->pfnCreateStream(pszStreamName[i],
+ DEBUG_CAPMODE_FRAMED,
+ DEBUG_OUTMODE_STREAMENABLE,
+ 0, 10);
+
+ gpfnDbgDrv->pfnSetCaptureMode(gsDBGPdumpState.
+ psStream[i],
+ DEBUG_CAPMODE_FRAMED,
+ 0xFFFFFFFF, 0xFFFFFFFF,
+ 1);
+ gpfnDbgDrv->pfnSetFrame(gsDBGPdumpState.psStream[i], 0);
+ }
+
+ PDUMPCOMMENT("Driver Product Name: %s", VS_PRODUCT_NAME);
+ PDUMPCOMMENT("Driver Product Version: %s (%s)",
+ PVRVERSION_STRING, PVRVERSION_FILE);
+ PDUMPCOMMENT("Start of Init Phase");
+ }
+
+ return;
+
+init_failed:
+
+ if (gsDBGPdumpState.pszFile) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX,
+ (void *)gsDBGPdumpState.pszFile, NULL);
+ gsDBGPdumpState.pszFile = NULL;
+ }
+
+ if (gsDBGPdumpState.pszScript) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX,
+ (void *)gsDBGPdumpState.pszScript, NULL);
+ gsDBGPdumpState.pszScript = NULL;
+ }
+
+ if (gsDBGPdumpState.pszMsg) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX,
+ (void *)gsDBGPdumpState.pszMsg, NULL);
+ gsDBGPdumpState.pszMsg = NULL;
+ }
+
+ gpfnDbgDrv = NULL;
+}
+
+void PDumpDeInit(void)
+{
+ u32 i = 0;
+
+ for (i = 0; i < PDUMP_NUM_STREAMS; i++)
+ gpfnDbgDrv->pfnDestroyStream(gsDBGPdumpState.psStream[i]);
+
+ if (gsDBGPdumpState.pszFile) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_FILENAME_SIZE_MAX,
+ (void *)gsDBGPdumpState.pszFile, NULL);
+ gsDBGPdumpState.pszFile = NULL;
+ }
+
+ if (gsDBGPdumpState.pszScript) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_SCRIPT_SIZE_MAX,
+ (void *)gsDBGPdumpState.pszScript, NULL);
+ gsDBGPdumpState.pszScript = NULL;
+ }
+
+ if (gsDBGPdumpState.pszMsg) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, SZ_MSG_SIZE_MAX,
+ (void *)gsDBGPdumpState.pszMsg, NULL);
+ gsDBGPdumpState.pszMsg = NULL;
+ }
+
+ gpfnDbgDrv = NULL;
+}
+
+enum PVRSRV_ERROR PDumpStartInitPhaseKM(void)
+{
+ u32 i;
+
+ if (gpfnDbgDrv) {
+ PDUMPCOMMENT("Start Init Phase");
+ for (i = 0; i < PDUMP_NUM_STREAMS; i++)
+ gpfnDbgDrv->pfnStartInitPhase(gsDBGPdumpState.
+ psStream[i]);
+ }
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpStopInitPhaseKM(void)
+{
+ u32 i;
+
+ if (gpfnDbgDrv) {
+ PDUMPCOMMENT("Stop Init Phase");
+
+ for (i = 0; i < PDUMP_NUM_STREAMS; i++)
+ gpfnDbgDrv->pfnStopInitPhase(gsDBGPdumpState.
+ psStream[i]);
+ }
+ return PVRSRV_OK;
+}
+
+void PDumpComment(char *pszFormat, ...)
+{
+ va_list ap;
+
+ __PDBG_PDUMP_STATE_GET_MSG_STRING();
+
+ va_start(ap, pszFormat);
+ vsnprintf(pszMsg, SZ_MSG_SIZE_MAX, pszFormat, ap);
+ va_end(ap);
+
+ PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
+}
+
+void PDumpCommentWithFlags(u32 ui32Flags, char *pszFormat, ...)
+{
+ va_list ap;
+
+ __PDBG_PDUMP_STATE_GET_MSG_STRING();
+
+ va_start(ap, pszFormat);
+ vsnprintf(pszMsg, SZ_MSG_SIZE_MAX, pszFormat, ap);
+ va_end(ap);
+
+ PDumpCommentKM(pszMsg, ui32Flags);
+}
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(void)
+{
+ return gpfnDbgDrv->pfnIsLastCaptureFrame(
+ gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+}
+
+IMG_BOOL PDumpIsCaptureFrameKM(void)
+{
+ if (PDumpSuspended())
+ return IMG_FALSE;
+ return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.
+ psStream[PDUMP_STREAM_SCRIPT2],
+ IMG_FALSE);
+}
+
+enum PVRSRV_ERROR PDumpRegWithFlagsKM(u32 ui32Reg, u32 ui32Data, u32 ui32Flags)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "WRW :SGXREG:0x%8.8X 0x%8.8X\r\n", ui32Reg, ui32Data);
+ PDumpWriteString2(pszScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+void PDumpReg(u32 ui32Reg, u32 ui32Data)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "WRW :SGXREG:0x%8.8X 0x%8.8X\r\n", ui32Reg, ui32Data);
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+}
+
+enum PVRSRV_ERROR PDumpRegPolWithFlagsKM(u32 ui32RegAddr, u32 ui32RegValue,
+ u32 ui32Mask, u32 ui32Flags)
+{
+#define POLL_DELAY 1000
+#define POLL_COUNT_LONG (2000000000 / POLL_DELAY)
+#define POLL_COUNT_SHORT (1000000 / POLL_DELAY)
+
+ u32 ui32PollCount;
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+
+ if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask &
+ EUR_CR_EVENT_STATUS_TA_FINISHED_MASK)) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask &
+ EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK)) ||
+ ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
+ (ui32RegValue & ui32Mask &
+ EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK)))
+ ui32PollCount = POLL_COUNT_LONG;
+ else
+ ui32PollCount = POLL_COUNT_SHORT;
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "POL :SGXREG:0x%8.8X 0x%8.8X 0x%8.8X %d %u %d\r\n",
+ ui32RegAddr, ui32RegValue, ui32Mask, 0, ui32PollCount,
+ POLL_DELAY);
+ PDumpWriteString2(pszScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpRegPolKM(u32 ui32RegAddr, u32 ui32RegValue, u32 ui32Mask)
+{
+ return PDumpRegPolWithFlagsKM(ui32RegAddr, ui32RegValue, ui32Mask,
+ PDUMP_FLAGS_CONTINUOUS);
+}
+
+void PDumpMallocPages(enum PVRSRV_DEVICE_TYPE eDeviceType, u32 ui32DevVAddr,
+ void *pvLinAddr, void *hOSMemHandle, u32 ui32NumBytes,
+ u32 ui32PageSize, void *hUniqueTag)
+{
+ u32 ui32Offset;
+ u32 ui32NumPages;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32Page;
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+ PVR_UNREFERENCED_PARAMETER(pvLinAddr);
+
+ PVR_ASSERT(((u32) ui32DevVAddr & (ui32PageSize - 1)) == 0);
+ PVR_ASSERT(hOSMemHandle);
+ PVR_ASSERT(((u32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "-- MALLOC :SGXMEM:VA_%8.8X 0x%8.8X %u\r\n", ui32DevVAddr,
+ ui32NumBytes, ui32PageSize);
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+ ui32Offset = 0;
+ ui32NumPages = ui32NumBytes / ui32PageSize;
+ while (ui32NumPages--) {
+ sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
+ PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
+ ui32Offset += ui32PageSize;
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+ ui32Page = sDevPAddr.uiAddr / ui32PageSize;
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "MALLOC :SGXMEM:PA_%8.8X%8.8X %u %u 0x%8.8X\r\n",
+ (u32)hUniqueTag, ui32Page * ui32PageSize,
+ ui32PageSize, ui32PageSize, ui32Page * ui32PageSize);
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+}
+
+void PDumpMallocPageTable(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void *pvLinAddr, u32 ui32PTSize, void *hUniqueTag)
+{
+ u8 *pui8LinAddr;
+ u32 ui32NumPages;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32Page;
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((u32) pvLinAddr & (ui32PTSize - 1)) == 0);
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "-- MALLOC :SGXMEM:PAGE_TABLE 0x%8.8X %lu\r\n", ui32PTSize,
+ SGX_MMU_PAGE_SIZE);
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+ pui8LinAddr = (u8 *) pvLinAddr;
+
+ ui32NumPages = 1;
+
+ while (ui32NumPages--) {
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+ ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "MALLOC :SGXMEM:PA_%8.8X%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);
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+ pui8LinAddr += SGX_MMU_PAGE_SIZE;
+ }
+}
+
+void PDumpFreePages(struct BM_HEAP *psBMHeap, struct IMG_DEV_VIRTADDR sDevVAddr,
+ u32 ui32NumBytes, u32 ui32PageSize, void *hUniqueTag,
+ IMG_BOOL bInterleaved)
+{
+ u32 ui32NumPages, ui32PageCounter;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((u32) sDevVAddr.uiAddr & (ui32PageSize - 1)) == 0);
+ PVR_ASSERT(((u32) ui32NumBytes & (ui32PageSize - 1)) == 0);
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "-- FREE :SGXMEM:VA_%8.8X\r\n",
+ sDevVAddr.uiAddr);
+ PDumpWriteString2(pszScript, 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);
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "FREE :SGXMEM:PA_%8.8X%8.8X\r\n",
+ (u32)hUniqueTag, sDevPAddr.uiAddr);
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+ } else {
+
+ }
+
+ sDevVAddr.uiAddr += ui32PageSize;
+ }
+}
+
+void PDumpFreePageTable(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void *pvLinAddr, u32 ui32PTSize, void *hUniqueTag)
+{
+ u8 *pui8LinAddr;
+ u32 ui32NumPages;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32Page;
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ PVR_ASSERT(((u32) pvLinAddr & (ui32PTSize - 1)) == 0);
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "-- FREE :SGXMEM:PAGE_TABLE\r\n");
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+ pui8LinAddr = (u8 *) pvLinAddr;
+
+ ui32NumPages = 1;
+
+ while (ui32NumPages--) {
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+ ui32Page = sDevPAddr.uiAddr >> SGX_MMU_PAGE_SHIFT;
+ pui8LinAddr += SGX_MMU_PAGE_SIZE;
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "FREE :SGXMEM:PA_%8.8X%8.8lX\r\n", (u32)hUniqueTag,
+ ui32Page * SGX_MMU_PAGE_SIZE);
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+ }
+}
+
+void PDumpPDReg(u32 ui32Reg, u32 ui32Data, void *hUniqueTag)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "WRW :SGXREG:0x%8.8X :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
+ ui32Reg, (u32)hUniqueTag, ui32Data & ~(SGX_MMU_PAGE_SIZE - 1),
+ ui32Data & (SGX_MMU_PAGE_SIZE - 1));
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+}
+
+void PDumpPDRegWithFlags(u32 ui32Reg, u32 ui32Data, u32 ui32Flags,
+ void *hUniqueTag)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "WRW :SGXREG:0x%8.8X :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
+ ui32Reg, (u32) hUniqueTag, ui32Data & ~(SGX_MMU_PAGE_SIZE - 1),
+ ui32Data & (SGX_MMU_PAGE_SIZE - 1));
+ PDumpWriteString2(pszScript, ui32Flags);
+}
+
+enum PVRSRV_ERROR PDumpMemPolKM(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ u32 ui32Offset, u32 ui32Value, u32 ui32Mask,
+ enum PDUMP_POLL_OPERATOR eOperator,
+ IMG_BOOL bLastFrame, IMG_BOOL bOverwrite,
+ void *hUniqueTag)
+{
+#define MEMPOLL_DELAY (1000)
+#define MEMPOLL_COUNT (2000000000 / MEMPOLL_DELAY)
+
+ u32 ui32PageOffset;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ struct IMG_DEV_VIRTADDR sDevVPageAddr;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+ u32 ui32Flags;
+ __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+ PVR_ASSERT((ui32Offset + sizeof(u32)) <=
+ psMemInfo->ui32AllocSize);
+
+ if (gsDBGPdumpState.ui32ParamFileNum == 0)
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+ else
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%u.prm",
+ gsDBGPdumpState.ui32ParamFileNum);
+
+ ui32Flags = 0;
+
+ if (bLastFrame)
+ ui32Flags |= PDUMP_FLAGS_LASTFRAME;
+
+ if (bOverwrite)
+ ui32Flags |= PDUMP_FLAGS_RESETLFBUFFER;
+
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
+ ui32PageOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+ sDevVPageAddr.uiAddr =
+ psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX, "POL :SGXMEM:"
+ "PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X 0x%8.8X %d %d %d\r\n",
+ (u32)hUniqueTag, sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+ ui32Value, ui32Mask, eOperator, MEMPOLL_COUNT, MEMPOLL_DELAY);
+ PDumpWriteString2(pszScript, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpMemKM(void *pvAltLinAddr,
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ u32 ui32Offset, u32 ui32Bytes, u32 ui32Flags,
+ void *hUniqueTag)
+{
+ u32 ui32PageByteOffset;
+ u8 *pui8DataLinAddr = NULL;
+ struct IMG_DEV_VIRTADDR sDevVPageAddr;
+ struct IMG_DEV_VIRTADDR sDevVAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+ u32 ui32ParamOutPos;
+ u32 ui32CurrentOffset;
+ u32 ui32BytesRemaining;
+
+ __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+ PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->ui32AllocSize);
+
+ if (ui32Bytes == 0)
+ return PVRSRV_OK;
+
+ if (pvAltLinAddr) {
+ pui8DataLinAddr = pvAltLinAddr;
+ } else {
+ if (psMemInfo->pvLinAddrKM)
+ pui8DataLinAddr =
+ (u8 *) psMemInfo->pvLinAddrKM + ui32Offset;
+
+ }
+
+ PVR_ASSERT(pui8DataLinAddr);
+
+ ui32ParamOutPos =
+ gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.
+ psStream[PDUMP_STREAM_PARAM2]);
+
+ if (!PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2],
+ pui8DataLinAddr, ui32Bytes, ui32Flags))
+ return PVRSRV_ERROR_GENERIC;
+
+ if (gsDBGPdumpState.ui32ParamFileNum == 0) {
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+ } else {
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%u.prm",
+ gsDBGPdumpState.ui32ParamFileNum);
+ }
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "-- LDB :SGXMEM:VA_%8.8X:0x%8.8X 0x%8.8X 0x%8.8X %s\r\n",
+ psMemInfo->sDevVAddr.uiAddr,
+ ui32Offset, ui32Bytes, ui32ParamOutPos, pszFile);
+ PDumpWriteString2(pszScript, ui32Flags);
+
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
+ ui32PageByteOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+ sDevVAddr = psMemInfo->sDevVAddr;
+ sDevVAddr.uiAddr += ui32Offset;
+
+ ui32BytesRemaining = ui32Bytes;
+ ui32CurrentOffset = ui32Offset;
+
+ while (ui32BytesRemaining > 0) {
+ u32 ui32BlockBytes = MIN(ui32BytesRemaining, PAGE_SIZE);
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle,
+ ui32CurrentOffset);
+
+ sDevVPageAddr.uiAddr =
+ psMemInfo->sDevVAddr.uiAddr + ui32CurrentOffset -
+ ui32PageByteOffset;
+
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+
+ sDevPAddr.uiAddr += ui32PageByteOffset;
+
+ if (ui32PageByteOffset) {
+ ui32BlockBytes =
+ MIN(ui32BytesRemaining,
+ PAGE_ALIGN(CpuPAddr.uiAddr) - CpuPAddr.uiAddr);
+
+ ui32PageByteOffset = 0;
+ }
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX, "LDB :SGXMEM:"
+ "PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X 0x%8.8X %s\r\n",
+ (u32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+ ui32BlockBytes, ui32ParamOutPos, pszFile);
+ PDumpWriteString2(pszScript, ui32Flags);
+
+ ui32BytesRemaining -= ui32BlockBytes;
+ ui32CurrentOffset += ui32BlockBytes;
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+ PVR_ASSERT(ui32BytesRemaining == 0);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpMem2KM(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void *pvLinAddr, u32 ui32Bytes, u32 ui32Flags,
+ IMG_BOOL bInitialisePages, void *hUniqueTag1,
+ void *hUniqueTag2)
+{
+ u32 ui32NumPages;
+ u32 ui32PageOffset;
+ u32 ui32BlockBytes;
+ u8 *pui8LinAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ u32 ui32Offset;
+ u32 ui32ParamOutPos;
+
+ __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+ if (ui32Flags)
+ ;
+
+ if (!pvLinAddr)
+ return PVRSRV_ERROR_GENERIC;
+
+ ui32ParamOutPos =
+ gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.
+ psStream[PDUMP_STREAM_PARAM2]);
+
+ if (bInitialisePages) {
+
+ if (!PDumpWriteILock
+ (gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2], pvLinAddr,
+ ui32Bytes, PDUMP_FLAGS_CONTINUOUS))
+ return PVRSRV_ERROR_GENERIC;
+
+ if (gsDBGPdumpState.ui32ParamFileNum == 0)
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+ else
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%u.prm",
+ gsDBGPdumpState.ui32ParamFileNum);
+ }
+
+ ui32PageOffset = (u32) pvLinAddr & (HOST_PAGESIZE() - 1);
+ ui32NumPages =
+ (ui32PageOffset + ui32Bytes + HOST_PAGESIZE() - 1) /
+ HOST_PAGESIZE();
+ pui8LinAddr = (u8 *) pvLinAddr;
+
+ while (ui32NumPages--) {
+ sCpuPAddr = OSMapLinToCPUPhys(pui8LinAddr);
+ sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
+
+ if (ui32PageOffset + ui32Bytes > HOST_PAGESIZE())
+ ui32BlockBytes = HOST_PAGESIZE() - ui32PageOffset;
+ else
+ ui32BlockBytes = ui32Bytes;
+
+ if (bInitialisePages) {
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX, "LDB :SGXMEM:"
+ "PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X "
+ "0x%8.8X %s\r\n",
+ (u32) hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+ ui32BlockBytes, ui32ParamOutPos, pszFile);
+ PDumpWriteString2(pszScript, 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) {
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+"WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
+ (u32)hUniqueTag1,
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ ~(SGX_MMU_PAGE_SIZE - 1),
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ (SGX_MMU_PAGE_SIZE - 1),
+ (u32)hUniqueTag2,
+ ui32PTE &
+ SGX_MMU_PDE_ADDR_MASK,
+ ui32PTE &
+ ~SGX_MMU_PDE_ADDR_MASK);
+ } else {
+ PVR_ASSERT(!
+ (ui32PTE &
+ SGX_MMU_PTE_VALID));
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X%8.8X\r\n",
+ (u32) hUniqueTag1,
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ ~(SGX_MMU_PAGE_SIZE - 1),
+ (sDevPAddr.uiAddr +
+ ui32Offset) &
+ (SGX_MMU_PAGE_SIZE - 1),
+ ui32PTE, (u32)hUniqueTag2);
+ }
+ PDumpWriteString2(pszScript,
+ PDUMP_FLAGS_CONTINUOUS);
+ }
+ }
+
+ ui32PageOffset = 0;
+ ui32Bytes -= ui32BlockBytes;
+ pui8LinAddr += ui32BlockBytes;
+ ui32ParamOutPos += ui32BlockBytes;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpPDDevPAddrKM(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ u32 ui32Offset,
+ struct IMG_DEV_PHYADDR sPDDevPAddr,
+ void *hUniqueTag1, void *hUniqueTag2)
+{
+ u32 ui32ParamOutPos;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+ u32 ui32PageByteOffset;
+ struct IMG_DEV_VIRTADDR sDevVAddr;
+ struct IMG_DEV_VIRTADDR sDevVPageAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+
+ __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING(PVRSRV_ERROR_GENERIC);
+
+ ui32ParamOutPos =
+ gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.
+ psStream[PDUMP_STREAM_PARAM2]);
+
+ if (!PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2],
+ (u8 *)&sPDDevPAddr, sizeof(struct IMG_DEV_PHYADDR),
+ PDUMP_FLAGS_CONTINUOUS))
+ return PVRSRV_ERROR_GENERIC;
+
+ if (gsDBGPdumpState.ui32ParamFileNum == 0)
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%.prm");
+ else
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "%%0%%%u.prm",
+ gsDBGPdumpState.ui32ParamFileNum);
+
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psMemInfo->sMemBlk.hOSMemHandle, ui32Offset);
+ ui32PageByteOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+ sDevVAddr = psMemInfo->sDevVAddr;
+ sDevVAddr.uiAddr += ui32Offset;
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
+ BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
+ sDevPAddr.uiAddr += ui32PageByteOffset;
+
+ if ((sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK) != 0) {
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+"WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX\r\n",
+ (u32) hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+ (u32)hUniqueTag2,
+ sPDDevPAddr.uiAddr & SGX_MMU_PDE_ADDR_MASK,
+ sPDDevPAddr.uiAddr & ~SGX_MMU_PDE_ADDR_MASK);
+ } else {
+ PVR_ASSERT(!(sDevPAddr.uiAddr & SGX_MMU_PTE_VALID));
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "WRW :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X\r\n",
+ (u32)hUniqueTag1,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+ sPDDevPAddr.uiAddr);
+ }
+ PDumpWriteString2(pszScript, PDUMP_FLAGS_CONTINUOUS);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpSetFrameKM(u32 ui32Frame)
+{
+ u32 ui32Stream;
+
+ for (ui32Stream = 0; ui32Stream < PDUMP_NUM_STREAMS; ui32Stream++)
+ if (gsDBGPdumpState.psStream[ui32Stream])
+ DbgSetFrame(gsDBGPdumpState.psStream[ui32Stream],
+ ui32Frame);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR PDumpGetFrameKM(u32 *pui32Frame)
+{
+ *pui32Frame =
+ DbgGetFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpCommentKM(char *pszComment, u32 ui32Flags)
+{
+ u32 ui32Count = 0;
+ enum PVRSRV_ERROR eError;
+ __PDBG_PDUMP_STATE_GET_MSG_STRING(PVRSRV_ERROR_GENERIC);
+
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ eError = PVRSRV_ERROR_GENERIC;
+ else
+ eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+
+ if (!PDumpWriteString2("-- ", ui32Flags))
+ return eError;
+
+ snprintf(pszMsg, SZ_MSG_SIZE_MAX, "%s", pszComment);
+
+ while ((pszMsg[ui32Count] != 0) && (ui32Count < SZ_MSG_SIZE_MAX))
+ ui32Count++;
+
+ if ((pszMsg[ui32Count - 1] != '\n') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+ pszMsg[ui32Count] = '\n';
+ ui32Count++;
+ pszMsg[ui32Count] = '\0';
+ }
+ if ((pszMsg[ui32Count - 2] != '\r') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+ pszMsg[ui32Count - 1] = '\r';
+ pszMsg[ui32Count] = '\n';
+ ui32Count++;
+ pszMsg[ui32Count] = '\0';
+ }
+
+ PDumpWriteString2(pszMsg, ui32Flags);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpDriverInfoKM(char *pszString, u32 ui32Flags)
+{
+ u32 ui32Count = 0;
+ __PDBG_PDUMP_STATE_GET_MSG_STRING(PVRSRV_ERROR_GENERIC);
+
+ snprintf(pszMsg, SZ_MSG_SIZE_MAX, "%s", pszString);
+
+ while ((pszMsg[ui32Count] != 0) && (ui32Count < SZ_MSG_SIZE_MAX))
+ ui32Count++;
+
+ if ((pszMsg[ui32Count - 1] != '\n') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+ pszMsg[ui32Count] = '\n';
+ ui32Count++;
+ pszMsg[ui32Count] = '\0';
+ }
+ if ((pszMsg[ui32Count - 2] != '\r') && (ui32Count < SZ_MSG_SIZE_MAX)) {
+ pszMsg[ui32Count - 1] = '\r';
+ pszMsg[ui32Count] = '\n';
+ ui32Count++;
+ pszMsg[ui32Count] = '\0';
+ }
+
+ if (!PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_DRIVERINFO],
+ (u8 *) pszMsg, ui32Count, ui32Flags)) {
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS)
+ return PVRSRV_ERROR_GENERIC;
+ else
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpBitmapKM(char *pszFileName, u32 ui32FileOffset,
+ u32 ui32Width, u32 ui32Height, u32 ui32StrideInBytes,
+ struct IMG_DEV_VIRTADDR sDevBaseAddr,
+ u32 ui32Size, enum PDUMP_PIXEL_FORMAT ePixelFormat,
+ enum PDUMP_MEM_FORMAT eMemFormat, u32 ui32PDumpFlags)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+ "\r\n-- Dump bitmap of render\r\n");
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "SII %s %s.bin :SGXMEM:v:0x%08X 0x%08X "
+ "0x%08X 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X\r\n",
+ pszFileName, pszFileName, sDevBaseAddr.uiAddr, ui32Size,
+ ui32FileOffset, ePixelFormat, ui32Width, ui32Height,
+ ui32StrideInBytes, eMemFormat);
+
+ PDumpWriteString2(pszScript, ui32PDumpFlags);
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PDumpReadRegKM(char *pszFileName, u32 ui32FileOffset,
+ u32 ui32Address, u32 ui32Size, u32 ui32PDumpFlags)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING(PVRSRV_ERROR_GENERIC);
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "SAB :SGXREG:0x%08X 0x%08X %s\r\n",
+ ui32Address, ui32FileOffset, pszFileName);
+
+ PDumpWriteString2(pszScript, ui32PDumpFlags);
+
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL PDumpWriteString2(char *pszString, u32 ui32Flags)
+{
+ return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2],
+ (u8 *)pszString, strlen(pszString), ui32Flags);
+}
+
+static IMG_BOOL PDumpWriteILock(struct DBG_STREAM *psStream, u8 *pui8Data,
+ u32 ui32Count, u32 ui32Flags)
+{
+ u32 ui32Written = 0;
+ u32 ui32Off = 0;
+
+ if (!psStream || PDumpSuspended() || (ui32Flags & PDUMP_FLAGS_NEVER))
+ return IMG_TRUE;
+
+ if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2]) {
+ u32 ui32ParamOutPos =
+ gpfnDbgDrv->pfnGetStreamOffset(gsDBGPdumpState.
+ psStream
+ [PDUMP_STREAM_PARAM2]);
+
+ if (ui32ParamOutPos + ui32Count > MAX_FILE_SIZE)
+ if ((gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]
+ &&
+ PDumpWriteString2
+ ("\r\n-- Splitting pdump output file\r\n\r\n",
+ ui32Flags))) {
+ DbgSetMarker(gsDBGPdumpState.
+ psStream[PDUMP_STREAM_PARAM2],
+ ui32ParamOutPos);
+ gsDBGPdumpState.ui32ParamFileNum++;
+ }
+ }
+
+ while (((u32) ui32Count > 0) && (ui32Written != 0xFFFFFFFF)) {
+ ui32Written =
+ DbgWrite(psStream, &pui8Data[ui32Off], ui32Count,
+ ui32Flags);
+
+ if (ui32Written == 0)
+ OSReleaseThreadQuanta();
+
+ if (ui32Written != 0xFFFFFFFF) {
+ ui32Off += ui32Written;
+ ui32Count -= ui32Written;
+ }
+ }
+
+ if (ui32Written == 0xFFFFFFFF)
+ return IMG_FALSE;
+
+ return IMG_TRUE;
+}
+
+static void DbgSetFrame(struct DBG_STREAM *psStream, u32 ui32Frame)
+{
+ gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
+}
+
+static u32 DbgGetFrame(struct DBG_STREAM *psStream)
+{
+ return gpfnDbgDrv->pfnGetFrame(psStream);
+}
+
+static void DbgSetMarker(struct DBG_STREAM *psStream, u32 ui32Marker)
+{
+ gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
+}
+
+static u32 DbgWrite(struct DBG_STREAM *psStream, u8 *pui8Data,
+ u32 ui32BCount, u32 ui32Flags)
+{
+ u32 ui32BytesWritten;
+
+ if (ui32Flags & PDUMP_FLAGS_CONTINUOUS) {
+ if ((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) &&
+ (psStream->ui32Start == 0xFFFFFFFF) &&
+ (psStream->ui32End == 0xFFFFFFFF) &&
+ psStream->bInitPhaseComplete)
+ ui32BytesWritten = ui32BCount;
+ else
+ ui32BytesWritten =
+ gpfnDbgDrv->pfnDBGDrivWrite2(psStream, pui8Data,
+ ui32BCount, 1);
+ } else if (ui32Flags & PDUMP_FLAGS_LASTFRAME) {
+ u32 ui32DbgFlags;
+
+ ui32DbgFlags = 0;
+ if (ui32Flags & PDUMP_FLAGS_RESETLFBUFFER)
+ ui32DbgFlags |= WRITELF_FLAGS_RESETBUF;
+
+ ui32BytesWritten =
+ gpfnDbgDrv->pfnWriteLF(psStream, pui8Data,
+ ui32BCount, 1, ui32DbgFlags);
+ } else {
+ ui32BytesWritten =
+ gpfnDbgDrv->pfnWriteBINCM(psStream, pui8Data,
+ ui32BCount, 1);
+ }
+
+ return ui32BytesWritten;
+}
+
+IMG_BOOL PDumpTestNextFrame(u32 ui32CurrentFrame)
+{
+ IMG_BOOL bFrameDumped;
+
+ bFrameDumped = IMG_FALSE;
+ PDumpSetFrameKM(ui32CurrentFrame + 1);
+ bFrameDumped = PDumpIsCaptureFrameKM();
+ PDumpSetFrameKM(ui32CurrentFrame);
+
+ return bFrameDumped;
+}
+
+void PDump3DSignatureRegisters(u32 ui32DumpFrameNum, IMG_BOOL bLastFrame,
+ u32 *pui32Registers, u32 ui32NumRegisters)
+{
+ u32 ui32FileOffset, ui32Flags;
+ u32 i;
+
+ __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ ui32FileOffset = 0;
+
+ PDUMPCOMMENTWITHFLAGS(ui32Flags,
+ "\r\n-- Dump 3D signature registers\r\n");
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "out%u_3d.sig",
+ ui32DumpFrameNum);
+
+ for (i = 0; i < ui32NumRegisters; i++) {
+ PDumpReadRegKM(pszFile, ui32FileOffset, pui32Registers[i],
+ sizeof(u32), ui32Flags);
+ ui32FileOffset += sizeof(u32);
+ }
+}
+
+static void PDumpCountRead(char *pszFileName, u32 ui32Address, u32 ui32Size,
+ u32 *pui32FileOffset, IMG_BOOL bLastFrame)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX,
+ "SAB :SGXREG:0x%08X 0x%08X %s\r\n", ui32Address,
+ *pui32FileOffset, pszFileName);
+ PDumpWriteString2(pszScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+
+ *pui32FileOffset += ui32Size;
+}
+
+void PDumpCounterRegisters(u32 ui32DumpFrameNum, IMG_BOOL bLastFrame,
+ u32 *pui32Registers, u32 ui32NumRegisters)
+{
+ u32 ui32FileOffset;
+ u32 i;
+
+ __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING();
+
+ PDUMPCOMMENTWITHFLAGS(bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0,
+ "\r\n-- Dump counter registers\r\n");
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "out%u.perf",
+ ui32DumpFrameNum);
+ ui32FileOffset = 0;
+
+ for (i = 0; i < ui32NumRegisters; i++)
+ PDumpCountRead(pszFile, pui32Registers[i], sizeof(u32),
+ &ui32FileOffset, bLastFrame);
+}
+
+void PDumpTASignatureRegisters(u32 ui32DumpFrameNum, u32 ui32TAKickCount,
+ IMG_BOOL bLastFrame, u32 *pui32Registers,
+ u32 ui32NumRegisters)
+{
+ u32 ui32FileOffset, ui32Flags;
+ u32 i;
+
+ __PDBG_PDUMP_STATE_GET_SCRIPT_AND_FILE_STRING();
+
+ ui32Flags = bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0;
+ PDUMPCOMMENTWITHFLAGS(ui32Flags,
+ "\r\n-- Dump TA signature registers\r\n");
+ snprintf(pszFile, SZ_FILENAME_SIZE_MAX, "out%u_ta.sig",
+ ui32DumpFrameNum);
+
+ ui32FileOffset = ui32TAKickCount * ui32NumRegisters * sizeof(u32);
+
+ for (i = 0; i < ui32NumRegisters; i++) {
+ PDumpReadRegKM(pszFile, ui32FileOffset, pui32Registers[i],
+ sizeof(u32), ui32Flags);
+ ui32FileOffset += sizeof(u32);
+ }
+}
+
+void PDumpRegRead(const u32 ui32RegOffset, u32 ui32Flags)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "RDW :SGXREG:0x%X\r\n",
+ ui32RegOffset);
+ PDumpWriteString2(pszScript, ui32Flags);
+}
+
+void PDumpCycleCountRegRead(const u32 ui32RegOffset, IMG_BOOL bLastFrame)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ snprintf(pszScript, SZ_SCRIPT_SIZE_MAX, "RDW :SGXREG:0x%X\r\n",
+ ui32RegOffset);
+ PDumpWriteString2(pszScript, bLastFrame ? PDUMP_FLAGS_LASTFRAME : 0);
+}
+
+void PDumpHWPerfCBKM(char *pszFileName, u32 ui32FileOffset,
+ struct IMG_DEV_VIRTADDR sDevBaseAddr, u32 ui32Size,
+ u32 ui32PDumpFlags)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+ PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags,
+ "\r\n-- Dump Hardware Performance Circular Buffer\r\n");
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "SAB :SGXMEM:v:0x%08X 0x%08X 0x%08X %s.bin\r\n",
+ sDevBaseAddr.uiAddr, ui32Size, ui32FileOffset, pszFileName);
+
+ PDumpWriteString2(pszScript, ui32PDumpFlags);
+}
+
+void PDumpCBP(struct PVRSRV_KERNEL_MEM_INFO *psROffMemInfo,
+ u32 ui32ROffOffset, u32 ui32WPosVal, u32 ui32PacketSize,
+ u32 ui32BufferSize, u32 ui32Flags, void *hUniqueTag)
+{
+ u32 ui32PageOffset;
+ struct IMG_DEV_VIRTADDR sDevVAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ struct IMG_DEV_VIRTADDR sDevVPageAddr;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ PVR_ASSERT((ui32ROffOffset + sizeof(u32)) <=
+ psROffMemInfo->ui32AllocSize);
+
+ sDevVAddr = psROffMemInfo->sDevVAddr;
+
+ sDevVAddr.uiAddr += ui32ROffOffset;
+
+ CpuPAddr =
+ OSMemHandleToCpuPAddr(psROffMemInfo->sMemBlk.hOSMemHandle,
+ ui32ROffOffset);
+ ui32PageOffset = CpuPAddr.uiAddr & (PAGE_SIZE - 1);
+
+ sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
+
+ BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
+
+ sDevPAddr.uiAddr += ui32PageOffset;
+
+ snprintf(pszScript,
+ SZ_SCRIPT_SIZE_MAX,
+ "CBP :SGXMEM:PA_%8.8X%8.8lX:0x%8.8lX 0x%8.8X 0x%8.8X 0x%8.8X\r\n",
+ (u32) hUniqueTag,
+ sDevPAddr.uiAddr & ~(SGX_MMU_PAGE_SIZE - 1),
+ sDevPAddr.uiAddr & (SGX_MMU_PAGE_SIZE - 1),
+ ui32WPosVal, ui32PacketSize, ui32BufferSize);
+ PDumpWriteString2(pszScript, ui32Flags);
+}
+
+void PDumpIDLWithFlags(u32 ui32Clocks, u32 ui32Flags)
+{
+ __PDBG_PDUMP_STATE_GET_SCRIPT_STRING();
+
+ sprintf(pszScript, "IDL %u\r\n", ui32Clocks);
+ PDumpWriteString2(pszScript, ui32Flags);
+}
+
+void PDumpIDL(u32 ui32Clocks)
+{
+ PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
+}
+
+void PDumpSuspendKM(void)
+{
+ atomic_inc(&gsPDumpSuspended);
+}
+
+void PDumpResumeKM(void)
+{
+ atomic_dec(&gsPDumpSuspended);
+}
+
+#endif
diff --git a/drivers/gpu/pvr/pdump_common.c b/drivers/gpu/pvr/pdump_common.c
new file mode 100644
index 00000000000..4f0e6f2f116
--- /dev/null
+++ b/drivers/gpu/pvr/pdump_common.c
@@ -0,0 +1,237 @@
+/**********************************************************************
+ *
+ * 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 "services_headers.h"
+#include "pdump_km.h"
+
+#if !defined(PDUMP_TEMP_BUFFER_SIZE)
+#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024L)
+#endif
+
+#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 10
+static void *gpvTempBuffer;
+static void *ghTempBufferBlockAlloc;
+static u16 gui16MMUContextUsage;
+
+static void *GetTempBuffer(void)
+{
+ if (gpvTempBuffer == NULL) {
+ enum PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ PDUMP_TEMP_BUFFER_SIZE,
+ &gpvTempBuffer,
+ &ghTempBufferBlockAlloc);
+ if (eError != PVRSRV_OK)
+ PVR_DPF(PVR_DBG_ERROR,
+ "GetTempBuffer: OSAllocMem failed: %d",
+ eError);
+ }
+
+ return gpvTempBuffer;
+}
+
+static void FreeTempBuffer(void)
+{
+ if (gpvTempBuffer != NULL) {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, PDUMP_TEMP_BUFFER_SIZE,
+ gpvTempBuffer, ghTempBufferBlockAlloc);
+ gpvTempBuffer = NULL;
+ }
+}
+
+void PDumpInitCommon(void)
+{
+ (void)GetTempBuffer();
+ PDumpInit();
+}
+
+void PDumpDeInitCommon(void)
+{
+ FreeTempBuffer();
+ PDumpDeInit();
+}
+
+enum PVRSRV_ERROR PDumpMemUM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *pvAltLinAddrUM, void *pvLinAddrUM,
+ struct 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;) {
+ enum 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 enum PVRSRV_ERROR _PdumpAllocMMUContext(u32 *pui32MMUContextID)
+{
+ u32 i;
+
+ for (i = 0; i < MAX_PDUMP_MMU_CONTEXTS; i++)
+ if ((gui16MMUContextUsage & (1UL << i)) == 0) {
+ gui16MMUContextUsage |= 1UL << i;
+ *pui32MMUContextID = i;
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "_PdumpAllocMMUContext: no free MMU context ids");
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+static enum PVRSRV_ERROR _PdumpFreeMMUContext(u32 ui32MMUContextID)
+{
+ if (ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS) {
+
+ gui16MMUContextUsage &= ~(1UL << ui32MMUContextID);
+ return PVRSRV_OK;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "_PdumpFreeMMUContext: MMU context ids invalid");
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+enum PVRSRV_ERROR PDumpSetMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ char *pszMemSpace, u32 *pui32MMUContextID,
+ u32 ui32MMUType, void *hUniqueTag1,
+ void *pvPDCPUAddr)
+{
+ u8 *pui8LinAddr = (u8 *) pvPDCPUAddr;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ struct IMG_DEV_PHYADDR sDevPAddr;
+ u32 ui32MMUContextID;
+ enum 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;
+
+ 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;
+}
+
+enum PVRSRV_ERROR PDumpClearMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ char *pszMemSpace,
+ u32 ui32MMUContextID, u32 ui32MMUType)
+{
+ enum PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+ PDumpComment("Clear MMU Context\r\n");
+
+ 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;
+}
+
+#endif
diff --git a/drivers/gpu/pvr/pdump_km.h b/drivers/gpu/pvr/pdump_km.h
new file mode 100644
index 00000000000..958c3332f80
--- /dev/null
+++ b/drivers/gpu/pvr/pdump_km.h
@@ -0,0 +1,268 @@
+/**********************************************************************
+ *
+ * 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 _PDUMP_KM_H_
+#define _PDUMP_KM_H_
+
+
+#define PDUMP_FLAGS_NEVER 0x08000000
+#define PDUMP_FLAGS_TOOUT2MEM 0x10000000
+#define PDUMP_FLAGS_LASTFRAME 0x20000000
+#define PDUMP_FLAGS_RESETLFBUFFER 0x40000000
+#define PDUMP_FLAGS_CONTINUOUS 0x80000000
+
+#define PDUMP_PD_UNIQUETAG ((void *)0)
+#define PDUMP_PT_UNIQUETAG ((void *)0)
+
+#ifndef PDUMP
+#define MAKEUNIQUETAG(hMemInfo) (0)
+#endif
+
+#ifdef PDUMP
+
+#define MAKEUNIQUETAG(hMemInfo) \
+ (((struct BM_BUF *)(((struct PVRSRV_KERNEL_MEM_INFO *) \
+ hMemInfo)->sMemBlk.hBuffer))->pMapping)
+
+#define PDUMP_REG_FUNC_NAME PDumpReg
+
+enum PVRSRV_ERROR PDumpMemPolKM(struct PVRSRV_KERNEL_MEM_INFO
+ *psMemInfo, u32 ui32Offset,
+ u32 ui32Value, u32 ui32Mask,
+ enum PDUMP_POLL_OPERATOR eOperator,
+ IMG_BOOL bLastFrame,
+ IMG_BOOL bOverwrite,
+ void *hUniqueTag);
+
+enum PVRSRV_ERROR PDumpMemUM(struct PVRSRV_PER_PROCESS_DATA
+ *psProcData, void *pvAltLinAddr,
+ void *pvLinAddr,
+ struct PVRSRV_KERNEL_MEM_INFO
+ *psMemInfo, u32 ui32Offset,
+ u32 ui32Bytes, u32 ui32Flags,
+ void *hUniqueTag);
+
+enum PVRSRV_ERROR PDumpMemKM(void *pvAltLinAddr,
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo, u32 ui32Offset,
+ u32 ui32Bytes, u32 ui32Flags, void *hUniqueTag);
+
+enum PVRSRV_ERROR PDumpMemPagesKM(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ struct IMG_DEV_PHYADDR *pPages, u32 ui32NumPages,
+ struct IMG_DEV_VIRTADDR sDevAddr, u32 ui32Start,
+ u32 ui32Length, u32 ui32Flags, void *hUniqueTag);
+
+enum PVRSRV_ERROR PDumpMem2KM(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void *pvLinAddr,
+ u32 ui32Bytes,
+ u32 ui32Flags,
+ IMG_BOOL bInitialisePages,
+ void *hUniqueTag1, void *hUniqueTag2);
+void PDumpInitCommon(void);
+void PDumpDeInitCommon(void);
+void PDumpInit(void);
+void PDumpDeInit(void);
+enum PVRSRV_ERROR PDumpStartInitPhaseKM(void);
+enum PVRSRV_ERROR PDumpStopInitPhaseKM(void);
+enum PVRSRV_ERROR PDumpSetFrameKM(u32 ui32Frame);
+enum PVRSRV_ERROR PDumpCommentKM(char *pszComment, u32 ui32Flags);
+enum PVRSRV_ERROR PDumpDriverInfoKM(char *pszString, u32 ui32Flags);
+enum PVRSRV_ERROR PDumpRegWithFlagsKM(u32 ui32RegAddr, u32 ui32RegValue,
+ u32 ui32Flags);
+
+enum PVRSRV_ERROR PDumpBitmapKM(char *pszFileName, u32 ui32FileOffset,
+ u32 ui32Width, u32 ui32Height, u32 ui32StrideInBytes,
+ struct IMG_DEV_VIRTADDR sDevBaseAddr, u32 ui32Size,
+ enum PDUMP_PIXEL_FORMAT ePixelFormat,
+ enum PDUMP_MEM_FORMAT eMemFormat, u32 ui32PDumpFlags);
+void PDumpHWPerfCBKM(char *pszFileName, u32 ui32FileOffset,
+ struct IMG_DEV_VIRTADDR sDevBaseAddr,
+ u32 ui32Size, u32 ui32PDumpFlags);
+enum PVRSRV_ERROR PDumpReadRegKM(char *pszFileName, u32 ui32FileOffset,
+ u32 ui32Address, u32 ui32Size, u32 ui32PDumpFlags);
+void PDUMP_REG_FUNC_NAME(u32 dwReg, u32 dwData);
+
+void PDumpMsvdxRegRead(const char *const pRegRegion, const u32 dwRegOffset);
+
+void PDumpMsvdxRegWrite(const char *const pRegRegion, const u32 dwRegOffset,
+ const u32 dwData);
+
+enum PVRSRV_ERROR PDumpMsvdxRegPol(const char *const pRegRegion,
+ const u32 ui32Offset, const u32 ui32CheckFuncIdExt,
+ const u32 ui32RequValue, const u32 ui32Enable,
+ const u32 ui32PollCount, const u32 ui32TimeOut);
+
+enum PVRSRV_ERROR PDumpMsvdxWriteRef(const char *const pRegRegion,
+ const u32 ui32VLROffset, const u32 ui32Physical);
+
+void PDumpComment(char *pszFormat, ...);
+
+void PDumpCommentWithFlags(u32 ui32Flags, char *pszFormat, ...);
+enum PVRSRV_ERROR PDumpRegPolKM(u32 ui32RegAddr, u32 ui32RegValue,
+ u32 ui32Mask);
+enum PVRSRV_ERROR PDumpRegPolWithFlagsKM(u32 ui32RegAddr, u32 ui32RegValue,
+ u32 ui32Mask, u32 ui32Flags);
+
+IMG_BOOL PDumpIsLastCaptureFrameKM(void);
+IMG_BOOL PDumpIsCaptureFrameKM(void);
+
+void PDumpMallocPages(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ u32 ui32DevVAddr, void *pvLinAddr, void *hOSMemHandle,
+ u32 ui32NumBytes, u32 ui32PageSize, void *hUniqueTag);
+void PDumpMallocPagesPhys(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ u32 ui32DevVAddr, u32 *pui32PhysPages, u32 ui32NumPages,
+ void *hUniqueTag);
+void PDumpMallocPageTable(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void *pvLinAddr, u32 ui32NumBytes, void *hUniqueTag);
+enum PVRSRV_ERROR PDumpSetMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ char *pszMemSpace, u32 *pui32MMUContextID,
+ u32 ui32MMUType, void *hUniqueTag1,
+ void *pvPDCPUAddr);
+enum PVRSRV_ERROR PDumpClearMMUContext(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ char *pszMemSpace,
+ u32 ui32MMUContextID, u32 ui32MMUType);
+void PDumpFreePages(struct BM_HEAP *psBMHeap,
+ struct IMG_DEV_VIRTADDR sDevVAddr, u32 ui32NumBytes,
+ u32 ui32PageSize, void *hUniqueTag, IMG_BOOL bInterleaved);
+void PDumpFreePageTable(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void *pvLinAddr, u32 ui32NumBytes, void *hUniqueTag);
+void PDumpPDReg(u32 ui32Reg, u32 ui32dwData, void *hUniqueTag);
+void PDumpPDRegWithFlags(u32 ui32Reg, u32 ui32Data, u32 ui32Flags,
+ void *hUniqueTag);
+
+enum PVRSRV_ERROR PDumpPDDevPAddrKM(struct PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ u32 ui32Offset, struct IMG_DEV_PHYADDR sPDDevPAddr,
+ void *hUniqueTag1, void *hUniqueTag2);
+
+IMG_BOOL PDumpTestNextFrame(u32 ui32CurrentFrame);
+
+void PDumpTASignatureRegisters(u32 ui32DumpFrameNum,
+ u32 ui32TAKickCount, IMG_BOOL bLastFrame,
+ u32 *pui32Registers, u32 ui32NumRegisters);
+
+void PDump3DSignatureRegisters(u32 ui32DumpFrameNum, IMG_BOOL bLastFrame,
+ u32 *pui32Registers, u32 ui32NumRegisters);
+
+void PDumpRegRead(const u32 dwRegOffset, u32 ui32Flags);
+
+void PDumpCycleCountRegRead(const u32 dwRegOffset, IMG_BOOL bLastFrame);
+
+void PDumpCounterRegisters(u32 ui32DumpFrameNum, IMG_BOOL bLastFrame,
+ u32 *pui32Registers, u32 ui32NumRegisters);
+
+void PDumpCBP(struct PVRSRV_KERNEL_MEM_INFO *psROffMemInfo,
+ u32 ui32ROffOffset,
+ u32 ui32WPosVal,
+ u32 ui32PacketSize,
+ u32 ui32BufferSize, u32 ui32Flags, void *hUniqueTag);
+
+void PDumpIDLWithFlags(u32 ui32Clocks, u32 ui32Flags);
+void PDumpIDL(u32 ui32Clocks);
+
+void PDumpSuspendKM(void);
+void PDumpResumeKM(void);
+
+#define PDUMPMEMPOL PDumpMemPolKM
+#define PDUMPMEM PDumpMemKM
+#define PDUMPMEM2 PDumpMem2KM
+#define PDUMPMEMUM PDumpMemUM
+#define PDUMPINIT PDumpInitCommon
+#define PDUMPDEINIT PDumpDeInitCommon
+#define PDUMPISLASTFRAME PDumpIsLastCaptureFrameKM
+#define PDUMPTESTFRAME PDumpIsCaptureFrameKM
+#define PDUMPTESTNEXTFRAME PDumpTestNextFrame
+#define PDUMPREGWITHFLAGS PDumpRegWithFlagsKM
+#define PDUMPREG PDUMP_REG_FUNC_NAME
+#define PDUMPCOMMENT PDumpComment
+#define PDUMPCOMMENTWITHFLAGS PDumpCommentWithFlags
+#define PDUMPREGPOL PDumpRegPolKM
+#define PDUMPREGPOLWITHFLAGS PDumpRegPolWithFlagsKM
+#define PDUMPMALLOCPAGES PDumpMallocPages
+#define PDUMPMALLOCPAGETABLE PDumpMallocPageTable
+#define PDUMPSETMMUCONTEXT PDumpSetMMUContext
+#define PDUMPCLEARMMUCONTEXT PDumpClearMMUContext
+#define PDUMPFREEPAGES PDumpFreePages
+#define PDUMPFREEPAGETABLE PDumpFreePageTable
+#define PDUMPPDREG PDumpPDReg
+#define PDUMPPDREGWITHFLAGS PDumpPDRegWithFlags
+#define PDUMPCBP PDumpCBP
+#define PDUMPMALLOCPAGESPHYS PDumpMallocPagesPhys
+#define PDUMPENDINITPHASE PDumpStopInitPhaseKM
+#define PDUMPMSVDXREGWRITE PDumpMsvdxRegWrite
+#define PDUMPMSVDXREGREAD PDumpMsvdxRegRead
+#define PDUMPMSVDXPOL PDumpMsvdxRegPol
+#define PDUMPMSVDXWRITEREF PDumpMsvdxWriteRef
+#define PDUMPBITMAPKM PDumpBitmapKM
+#define PDUMPDRIVERINFO PDumpDriverInfoKM
+#define PDUMPIDLWITHFLAGS PDumpIDLWithFlags
+#define PDUMPIDL PDumpIDL
+#define PDUMPSUSPEND PDumpSuspendKM
+#define PDUMPRESUME PDumpResumeKM
+
+#else
+#define PDUMPMEMPOL(args...)
+#define PDUMPMEM(args...)
+#define PDUMPMEM2(args...)
+#define PDUMPMEMUM(args...)
+#define PDUMPINIT(args...)
+#define PDUMPDEINIT(args...)
+#define PDUMPISLASTFRAME(args...)
+#define PDUMPTESTFRAME(args...)
+#define PDUMPTESTNEXTFRAME(args...)
+#define PDUMPREGWITHFLAGS(args...)
+#define PDUMPREG(args...)
+#define PDUMPCOMMENT(args...)
+#define PDUMPREGPOL(args...)
+#define PDUMPREGPOLWITHFLAGS(args...)
+#define PDUMPMALLOCPAGES(args...)
+#define PDUMPMALLOCPAGETABLE(args...)
+#define PDUMPSETMMUCONTEXT(args...)
+#define PDUMPCLEARMMUCONTEXT(args...)
+#define PDUMPFREEPAGES(args...)
+#define PDUMPFREEPAGETABLE(args...)
+#define PDUMPPDREG(args...)
+#define PDUMPPDREGWITHFLAGS(args...)
+#define PDUMPSYNC(args...)
+#define PDUMPCOPYTOMEM(args...)
+#define PDUMPWRITE(args...)
+#define PDUMPCBP(args...)
+#define PDUMPCOMMENTWITHFLAGS(args...)
+#define PDUMPMALLOCPAGESPHYS(args...)
+#define PDUMPENDINITPHASE(args...)
+#define PDUMPMSVDXREG(args...)
+#define PDUMPMSVDXREGWRITE(args...)
+#define PDUMPMSVDXREGREAD(args...)
+#define PDUMPMSVDXPOLEQ(args...)
+#define PDUMPMSVDXPOL(args...)
+#define PDUMPBITMAPKM(args...)
+#define PDUMPDRIVERINFO(args...)
+#define PDUMPIDLWITHFLAGS(args...)
+#define PDUMPIDL(args...)
+#define PDUMPSUSPEND(args...)
+#define PDUMPRESUME(args...)
+#define PDUMPMSVDXWRITEREF(args...)
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/pdumpdefs.h b/drivers/gpu/pvr/pdumpdefs.h
new file mode 100644
index 00000000000..dec488bbdd4
--- /dev/null
+++ b/drivers/gpu/pvr/pdumpdefs.h
@@ -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
+ *
+ ******************************************************************************/
+
+#if !defined(__PDUMPDEFS_H__)
+#define __PDUMPDEFS_H__
+
+enum PDUMP_PIXEL_FORMAT {
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB8 = 1,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB332 = 2,
+ PVRSRV_PDUMP_PIXEL_FORMAT_KRGB555 = 3,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB565 = 4,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB4444 = 5,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB1555 = 6,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB888 = 7,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8888 = 8,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV8 = 9,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV4444 = 10,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VY0UY1_8888 = 11,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UY0VY1_8888 = 12,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0UY1V_8888 = 13,
+ PVRSRV_PDUMP_PIXEL_FORMAT_Y0VY1U_8888 = 14,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV888 = 15,
+ PVRSRV_PDUMP_PIXEL_FORMAT_UYVY10101010 = 16,
+ PVRSRV_PDUMP_PIXEL_FORMAT_VYAUYA8888 = 17,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV8888 = 18,
+ PVRSRV_PDUMP_PIXEL_FORMAT_AYUV2101010 = 19,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV101010 = 20,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y8 = 21,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_IMC2 = 22,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_YV12 = 23,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL8 = 24,
+ PVRSRV_PDUMP_PIXEL_FORMAT_YUV_PL12 = 25,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV8 = 26,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV8 = 27,
+ PVRSRV_PDUMP_PIXEL_FORMAT_PL12Y10 = 28,
+ PVRSRV_PDUMP_PIXEL_FORMAT_422PL12YUV10 = 29,
+ PVRSRV_PDUMP_PIXEL_FORMAT_420PL12YUV10 = 30,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ABGR8888 = 31,
+ PVRSRV_PDUMP_PIXEL_FORMAT_BGRA8888 = 32,
+ PVRSRV_PDUMP_PIXEL_FORMAT_ARGB8332 = 33,
+ PVRSRV_PDUMP_PIXEL_FORMAT_RGB555 = 34,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F16 = 35,
+ PVRSRV_PDUMP_PIXEL_FORMAT_F32 = 36,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L16 = 37,
+ PVRSRV_PDUMP_PIXEL_FORMAT_L32 = 38,
+
+ PVRSRV_PDUMP_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff
+};
+
+enum PDUMP_MEM_FORMAT {
+ PVRSRV_PDUMP_MEM_FORMAT_STRIDE = 0,
+ PVRSRV_PDUMP_MEM_FORMAT_RESERVED = 1,
+ PVRSRV_PDUMP_MEM_FORMAT_TILED = 8,
+ PVRSRV_PDUMP_MEM_FORMAT_TWIDDLED = 9,
+ PVRSRV_PDUMP_MEM_FORMAT_HYBRID = 10,
+
+ PVRSRV_PDUMP_MEM_FORMAT_FORCE_I32 = 0x7fffffff
+};
+
+enum PDUMP_POLL_OPERATOR {
+ PDUMP_POLL_OPERATOR_EQUAL = 0,
+ PDUMP_POLL_OPERATOR_LESS = 1,
+ PDUMP_POLL_OPERATOR_LESSEQUAL = 2,
+ PDUMP_POLL_OPERATOR_GREATER = 3,
+ PDUMP_POLL_OPERATOR_GREATEREQUAL = 4,
+ PDUMP_POLL_OPERATOR_NOTEQUAL = 5,
+};
+
+#endif
diff --git a/drivers/gpu/pvr/perproc.c b/drivers/gpu/pvr/perproc.c
new file mode 100644
index 00000000000..d0d4f4cc806
--- /dev/null
+++ b/drivers/gpu/pvr/perproc.c
@@ -0,0 +1,266 @@
+/**********************************************************************
+ *
+ * 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 struct HASH_TABLE *psHashTab;
+
+static enum PVRSRV_ERROR FreePerProcessData(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ enum 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((struct PVRSRV_PER_PROCESS_DATA *)
+ uiPerProc == psPerProc);
+ PVR_ASSERT(((struct 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;
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(*psPerProc), psPerProc,
+ psPerProc->hBlockAlloc);
+
+ return PVRSRV_OK;
+}
+
+struct PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(u32 ui32PID)
+{
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != NULL);
+
+ psPerProc =
+ (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab,
+ (u32) ui32PID);
+ return psPerProc;
+}
+
+enum PVRSRV_ERROR PVRSRVPerProcessDataConnect(u32 ui32PID)
+{
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc;
+ void *hBlockAlloc;
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_ASSERT(psHashTab != NULL);
+
+ psPerProc = (struct PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab,
+ (u32)ui32PID);
+ if (psPerProc == NULL) {
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(*psPerProc), (void **)&psPerProc,
+ &hBlockAlloc);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVPerProcessDataConnect: "
+ "Couldn't allocate per-process data (%d)",
+ eError);
+ return eError;
+ }
+ OSMemSet(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)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc;
+
+ PVR_ASSERT(psHashTab != NULL);
+
+ psPerProc = (struct 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,
+ IMG_FALSE);
+
+ 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);
+}
+
+enum 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;
+}
+
+enum PVRSRV_ERROR PVRSRVPerProcessDataDeInit(void)
+{
+ if (psHashTab != NULL) {
+ HASH_Delete(psHashTab);
+ psHashTab = NULL;
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/pvr/perproc.h b/drivers/gpu/pvr/perproc.h
new file mode 100644
index 00000000000..a89b0e4e51e
--- /dev/null
+++ b/drivers/gpu/pvr/perproc.h
@@ -0,0 +1,79 @@
+/**********************************************************************
+ *
+ * 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 __PERPROC_H__
+#define __PERPROC_H__
+
+#include "img_types.h"
+#include "resman.h"
+
+#include "handle.h"
+
+struct PVRSRV_PER_PROCESS_DATA {
+ u32 ui32PID;
+ void *hBlockAlloc;
+ struct RESMAN_CONTEXT *hResManContext;
+ void *hPerProcData;
+ struct PVRSRV_HANDLE_BASE *psHandleBase;
+
+ IMG_BOOL bHandlesBatched;
+ u32 ui32RefCount;
+
+ IMG_BOOL bInitProcess;
+
+ void *hOsPrivateData;
+};
+
+struct PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(u32 ui32PID);
+
+enum PVRSRV_ERROR PVRSRVPerProcessDataConnect(u32 ui32PID);
+void PVRSRVPerProcessDataDisconnect(u32 ui32PID);
+
+enum PVRSRV_ERROR PVRSRVPerProcessDataInit(void);
+enum PVRSRV_ERROR PVRSRVPerProcessDataDeInit(void);
+
+static inline struct PVRSRV_PER_PROCESS_DATA *PVRSRVFindPerProcessData(void)
+{
+ return PVRSRVPerProcessData(OSGetCurrentProcessIDKM());
+}
+
+static inline void *PVRSRVProcessPrivateData(struct PVRSRV_PER_PROCESS_DATA
+ *psPerProc)
+{
+ return (psPerProc != NULL) ? psPerProc->hOsPrivateData : NULL;
+}
+
+static inline void *PVRSRVPerProcessPrivateData(u32 ui32PID)
+{
+ return PVRSRVProcessPrivateData(PVRSRVPerProcessData(ui32PID));
+}
+
+static inline void *PVRSRVFindPerProcessPrivateData(void)
+{
+ return PVRSRVProcessPrivateData(PVRSRVFindPerProcessData());
+}
+
+#endif
diff --git a/drivers/gpu/pvr/power.c b/drivers/gpu/pvr/power.c
new file mode 100644
index 00000000000..a33e0de81c4
--- /dev/null
+++ b/drivers/gpu/pvr/power.c
@@ -0,0 +1,559 @@
+/**********************************************************************
+ *
+ * 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 <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+static IMG_BOOL gbInitServerRunning;
+static IMG_BOOL gbInitServerRan;
+static IMG_BOOL gbInitSuccessful;
+static DEFINE_MUTEX(hPowerAndFreqLock);
+
+enum PVRSRV_ERROR PVRSRVSetInitServerState(enum PVRSRV_INIT_SERVER_STATE
+ eInitServerState, IMG_BOOL 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;
+}
+
+IMG_BOOL PVRSRVGetInitServerState(
+ enum PVRSRV_INIT_SERVER_STATE eInitServerState)
+{
+ IMG_BOOL 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 = IMG_FALSE;
+ }
+
+ return bReturnVal;
+}
+
+static IMG_BOOL _IsSystemStatePowered(enum PVR_POWER_STATE eSystemPowerState)
+{
+ return (IMG_BOOL)(eSystemPowerState < PVRSRV_POWER_STATE_D2);
+}
+
+static enum PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
+ u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
+ enum PVR_POWER_STATE eNewDevicePowerState;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ psPowerDevice = psSysData->psPowerDeviceList;
+ while (psPowerDevice) {
+ if (bAllDevices ||
+ (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)) {
+ eNewDevicePowerState =
+ (eNewPowerState == PVRSRV_POWER_Unspecified) ?
+ psPowerDevice->eDefaultPowerState :
+ eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState !=
+ eNewDevicePowerState) {
+ if (psPowerDevice->pfnPrePower != NULL) {
+ eError =
+ psPowerDevice->
+ pfnPrePower(psPowerDevice->
+ hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPrePower failed (%u)\n",
+ eError);
+ return eError;
+ }
+ }
+
+ eError = SysDevicePrePowerState(
+ psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ pr_err("SysDevicePrePowerState failed "
+ "(%u)\n", eError);
+ return eError;
+ }
+ }
+ }
+
+ psPowerDevice = psPowerDevice->psNext;
+ }
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
+ u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
+ enum PVR_POWER_STATE eNewDevicePowerState;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ psPowerDevice = psSysData->psPowerDeviceList;
+ while (psPowerDevice) {
+ if (bAllDevices ||
+ (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)) {
+ eNewDevicePowerState = (eNewPowerState ==
+ PVRSRV_POWER_Unspecified) ? psPowerDevice->
+ eDefaultPowerState : eNewPowerState;
+
+ if (psPowerDevice->eCurrentPowerState !=
+ eNewDevicePowerState) {
+ eError = SysDevicePostPowerState(
+ psPowerDevice->ui32DeviceIndex,
+ eNewDevicePowerState,
+ psPowerDevice->eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ pr_err("SysDevicePostPowerState "
+ "failed (%u)\n", eError);
+ return eError;
+ }
+
+ if (psPowerDevice->pfnPostPower != NULL) {
+ eError =
+ psPowerDevice->
+ pfnPostPower(psPowerDevice->
+ hDevCookie,
+ eNewDevicePowerState,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPostPower failed "
+ "(%u)\n", eError);
+ return eError;
+ }
+ }
+
+ psPowerDevice->eCurrentPowerState =
+ eNewDevicePowerState;
+ }
+ }
+
+ psPowerDevice = psPowerDevice->psNext;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+#if defined(PDUMP)
+ if (eNewPowerState == PVRSRV_POWER_Unspecified) {
+ eError =
+ PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex,
+ PVRSRV_POWER_STATE_D0);
+ if (eError != PVRSRV_OK)
+ goto Exit;
+ eError =
+ PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex,
+ PVRSRV_POWER_STATE_D0);
+ if (eError != PVRSRV_OK)
+ goto Exit;
+
+ PDUMPSUSPEND();
+ }
+#endif
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex,
+ eNewPowerState);
+ if (eError != PVRSRV_OK) {
+ if (eNewPowerState == PVRSRV_POWER_Unspecified)
+ PDUMPRESUME();
+ goto Exit;
+ }
+
+ eError = PVRSRVDevicePostPowerStateKM(IMG_FALSE, ui32DeviceIndex,
+ eNewPowerState);
+
+ if (eNewPowerState == PVRSRV_POWER_Unspecified)
+ PDUMPRESUME();
+
+Exit:
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetDevicePowerStateKM : "
+ "Transition to %d FAILED 0x%x",
+ eNewPowerState, eError);
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(
+ enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ enum PVR_POWER_STATE eNewDevicePowerState;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ if (_IsSystemStatePowered(eNewPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState)) {
+ if (_IsSystemStatePowered(eNewPowerState))
+ eNewDevicePowerState = PVRSRV_POWER_Unspecified;
+ else
+ eNewDevicePowerState = PVRSRV_POWER_STATE_D3;
+
+ eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0,
+ eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ goto ErrorExit;
+ }
+
+ if (eNewPowerState != psSysData->eCurrentPowerState) {
+ eError = SysSystemPrePowerState(eNewPowerState);
+ 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, eNewPowerState, eError);
+
+ psSysData->eFailedPowerState = eNewPowerState;
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(
+ enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ enum PVR_POWER_STATE eNewDevicePowerState;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ goto Exit;
+
+ if (eNewPowerState != psSysData->eCurrentPowerState) {
+ eError = SysSystemPostPowerState(eNewPowerState);
+ if (eError != PVRSRV_OK)
+ goto Exit;
+ }
+
+ if (_IsSystemStatePowered(eNewPowerState) !=
+ _IsSystemStatePowered(psSysData->eCurrentPowerState)) {
+ if (_IsSystemStatePowered(eNewPowerState))
+ eNewDevicePowerState = PVRSRV_POWER_Unspecified;
+ else
+ eNewDevicePowerState = PVRSRV_POWER_STATE_D3;
+
+ eError =
+ PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0,
+ eNewDevicePowerState);
+ if (eError != PVRSRV_OK)
+ goto Exit;
+ }
+
+ PVR_DPF(PVR_DBG_WARNING, "PVRSRVSystemPostPowerStateKM: "
+ "System Power Transition from %d to %d OK",
+ psSysData->eCurrentPowerState, eNewPowerState);
+
+ psSysData->eCurrentPowerState = eNewPowerState;
+
+Exit:
+
+ if (_IsSystemStatePowered(eNewPowerState) &&
+ PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
+ PVRSRVCommandCompleteCallbacks();
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVSetPowerStateKM(enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ eError = PVRSRVSystemPrePowerStateKM(eNewPowerState);
+ if (eError != PVRSRV_OK)
+ goto ErrorExit;
+
+ eError = PVRSRVSystemPostPowerStateKM(eNewPowerState);
+ if (eError != PVRSRV_OK)
+ goto ErrorExit;
+
+ psSysData->eFailedPowerState = PVRSRV_POWER_Unspecified;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetPowerStateKM: "
+ "Transition from %d to %d FAILED 0x%x",
+ psSysData->eCurrentPowerState, eNewPowerState, eError);
+
+ psSysData->eFailedPowerState = eNewPowerState;
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVRegisterPowerDevice(u32 ui32DeviceIndex,
+ enum PVRSRV_ERROR (*pfnPrePower)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*pfnPostPower)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*pfnPreClockSpeedChange)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*pfnPostClockSpeedChange)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE),
+ void *hDevCookie, enum PVR_POWER_STATE eCurrentPowerState,
+ enum PVR_POWER_STATE eDefaultPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
+
+ if (pfnPrePower == NULL && pfnPostPower == NULL)
+ return PVRSRVRemovePowerDevice(ui32DeviceIndex);
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_POWER_DEV),
+ (void **) &psPowerDevice, NULL);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterPowerDevice: "
+ "Failed to alloc struct 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;
+
+ psPowerDevice->psNext = psSysData->psPowerDeviceList;
+ psSysData->psPowerDeviceList = psPowerDevice;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVRemovePowerDevice(u32 ui32DeviceIndex)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psCurrent, *psPrevious;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ psCurrent = psSysData->psPowerDeviceList;
+ psPrevious = NULL;
+
+ while (psCurrent)
+ if (psCurrent->ui32DeviceIndex == ui32DeviceIndex) {
+ if (psPrevious)
+ psPrevious->psNext = psCurrent->psNext;
+ else
+ psSysData->psPowerDeviceList =
+ psCurrent->psNext;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_POWER_DEV), psCurrent,
+ NULL);
+ break;
+ } else {
+ psPrevious = psCurrent;
+ psCurrent = psCurrent->psNext;
+ }
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PVRSRVIsDevicePowered(u32 ui32DeviceIndex)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return IMG_FALSE;
+
+ psPowerDevice = psSysData->psPowerDeviceList;
+ while (psPowerDevice) {
+ if (psPowerDevice->ui32DeviceIndex == ui32DeviceIndex)
+ return (IMG_BOOL)(psPowerDevice->eCurrentPowerState ==
+ PVRSRV_POWER_STATE_D0);
+ psPowerDevice = psPowerDevice->psNext;
+ }
+
+ return IMG_FALSE;
+}
+
+enum PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(u32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ void *pvInfo)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ psPowerDevice = psSysData->psPowerDeviceList;
+ while (psPowerDevice) {
+ if (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)
+ if (psPowerDevice->pfnPreClockSpeedChange) {
+ eError =
+ psPowerDevice->
+ pfnPreClockSpeedChange(psPowerDevice->
+ hDevCookie,
+ bIdleDevice,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPreClockSpeedChange failed\n");
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVDevicePreClockSpeedChange : "
+ "Device %lu failed, error:0x%lx",
+ ui32DeviceIndex, eError);
+ break;
+ }
+ }
+ psPowerDevice = psPowerDevice->psNext;
+ }
+
+ return eError;
+}
+
+void PVRSRVDevicePostClockSpeedChange(u32 ui32DeviceIndex, IMG_BOOL bIdleDevice,
+ void *pvInfo)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
+
+ PVR_UNREFERENCED_PARAMETER(pvInfo);
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return;
+
+ psPowerDevice = psSysData->psPowerDeviceList;
+ while (psPowerDevice) {
+ if (ui32DeviceIndex == psPowerDevice->ui32DeviceIndex)
+ if (psPowerDevice->pfnPostClockSpeedChange) {
+ eError =
+ psPowerDevice->
+ pfnPostClockSpeedChange(psPowerDevice->
+ hDevCookie,
+ bIdleDevice,
+ psPowerDevice->
+ eCurrentPowerState);
+ if (eError != PVRSRV_OK) {
+ pr_err
+ ("pfnPostClockSpeedChange "
+ "failed\n");
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVDevicePostClockSpeedChange : "
+ "Device %lu failed, error:0x%lx",
+ ui32DeviceIndex, eError);
+ }
+ }
+ psPowerDevice = psPowerDevice->psNext;
+ }
+}
diff --git a/drivers/gpu/pvr/power.h b/drivers/gpu/pvr/power.h
new file mode 100644
index 00000000000..a5d00e2a1a9
--- /dev/null
+++ b/drivers/gpu/pvr/power.h
@@ -0,0 +1,97 @@
+/**********************************************************************
+ *
+ * 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 POWER_H
+#define POWER_H
+
+struct PVRSRV_POWER_DEV {
+ enum PVRSRV_ERROR (*pfnPrePower)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE);
+ enum PVRSRV_ERROR (*pfnPostPower)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE);
+ enum PVRSRV_ERROR (*pfnPreClockSpeedChange)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE);
+ enum PVRSRV_ERROR (*pfnPostClockSpeedChange)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE);
+ void *hDevCookie;
+ u32 ui32DeviceIndex;
+ enum PVR_POWER_STATE eDefaultPowerState;
+ enum PVR_POWER_STATE eCurrentPowerState;
+ struct PVRSRV_POWER_DEV *psNext;
+
+};
+
+enum PVRSRV_INIT_SERVER_STATE {
+ PVRSRV_INIT_SERVER_Unspecified = -1,
+ PVRSRV_INIT_SERVER_RUNNING = 0,
+ PVRSRV_INIT_SERVER_RAN = 1,
+ PVRSRV_INIT_SERVER_SUCCESSFUL = 2,
+ PVRSRV_INIT_SERVER_NUM = 3,
+ PVRSRV_INIT_SERVER_FORCE_I32 = 0x7fffffff
+};
+
+IMG_BOOL PVRSRVGetInitServerState(enum PVRSRV_INIT_SERVER_STATE
+ eInitServerState);
+
+enum PVRSRV_ERROR PVRSRVSetInitServerState(enum PVRSRV_INIT_SERVER_STATE
+ eInitServerState,
+ IMG_BOOL bState);
+
+enum PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState);
+
+enum PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(
+ enum PVR_POWER_STATE eNewPowerState);
+enum PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(
+ enum PVR_POWER_STATE eNewPowerState);
+
+enum PVRSRV_ERROR PVRSRVSetPowerStateKM(enum PVR_POWER_STATE ePVRState);
+
+enum PVRSRV_ERROR PVRSRVRegisterPowerDevice(u32 ui32DeviceIndex,
+ enum PVRSRV_ERROR (*pfnPrePower)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*pfnPostPower)(void *, enum PVR_POWER_STATE,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*pfnPreClockSpeedChange)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE),
+ enum PVRSRV_ERROR (*pfnPostClockSpeedChange)(void *, IMG_BOOL,
+ enum PVR_POWER_STATE),
+ void *hDevCookie, enum PVR_POWER_STATE eCurrentPowerState,
+ enum PVR_POWER_STATE eDefaultPowerState);
+
+enum PVRSRV_ERROR PVRSRVRemovePowerDevice(u32 ui32DeviceIndex);
+
+IMG_BOOL PVRSRVIsDevicePowered(u32 ui32DeviceIndex);
+
+enum PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(u32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ void *pvInfo);
+
+void PVRSRVDevicePostClockSpeedChange(u32 ui32DeviceIndex,
+ IMG_BOOL bIdleDevice,
+ void *pvInfo);
+
+#endif
diff --git a/drivers/gpu/pvr/private_data.h b/drivers/gpu/pvr/private_data.h
new file mode 100644
index 00000000000..b91b838e7fd
--- /dev/null
+++ b/drivers/gpu/pvr/private_data.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 __INCLUDED_PRIVATE_DATA_H_
+#define __INCLUDED_PRIVATE_DATA_H_
+
+#include <linux/wait.h>
+#include <linux/list.h>
+
+struct PVRSRV_FILE_PRIVATE_DATA {
+ u32 ui32OpenPID;
+ void *hBlockAlloc;
+
+ wait_queue_head_t event_wait;
+ struct list_head event_list;
+ int event_space;
+};
+
+#endif
diff --git a/drivers/gpu/pvr/proc.c b/drivers/gpu/pvr/proc.c
new file mode 100644
index 00000000000..613d3decab6
--- /dev/null
+++ b/drivers/gpu/pvr/proc.c
@@ -0,0 +1,421 @@
+/**********************************************************************
+ *
+ * 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+
+#include "services_headers.h"
+
+#include "queue.h"
+#include "resman.h"
+#include "pvrmmap.h"
+#include "pvr_debug.h"
+#include "pvrversion.h"
+#include "proc.h"
+#include "perproc.h"
+#include "env_perproc.h"
+
+/* The proc entry for our /proc/pvr directory */
+
+static struct proc_dir_entry *dir;
+
+static off_t procDumpSysNodes(char *buf, size_t size, off_t off);
+static off_t procDumpVersion(char *buf, size_t size, off_t off);
+
+static const char PVRProcDirRoot[] = "pvr";
+
+off_t printAppend(char *buffer, size_t size, off_t off, const char *format, ...)
+{
+ int n;
+ int space = size - off;
+ va_list ap;
+
+ PVR_ASSERT(space >= 0);
+
+ va_start(ap, format);
+ n = vsnprintf(buffer + off, space, format, ap);
+ va_end(ap);
+
+ if (n >= space || n < 0) {
+
+ buffer[size - 1] = 0;
+ return size - 1;
+ } else {
+ return off + n;
+}
+}
+
+static int pvr_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ off_t (*pprn)(char *, size_t, off_t) = data;
+
+ off_t len = pprn(page, count, off);
+
+ if (len == END_OF_FILE) {
+ len = 0;
+ *eof = 1;
+ } else if (!len) {
+ *start = (char *)0;
+ } else {
+ *start = (char *)1;
+ }
+
+ return len;
+}
+
+static int CreateProcEntryInDir(struct proc_dir_entry *pdir, const char *name,
+ read_proc_t rhandler, write_proc_t whandler,
+ void *data)
+{
+ struct proc_dir_entry *file;
+ mode_t mode;
+
+ if (!pdir) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreateProcEntryInDir: parent directory doesn't exist");
+
+ return -ENOMEM;
+ }
+
+ mode = S_IFREG;
+
+ if (rhandler)
+ mode |= S_IRUGO;
+
+ if (whandler)
+ mode |= S_IWUSR;
+
+ file = create_proc_entry(name, mode, pdir);
+
+ if (file) {
+ file->read_proc = rhandler;
+ file->write_proc = whandler;
+ file->data = data;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "Created proc entry %s in %s", name,
+ pdir->name);
+
+ return 0;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreateProcEntry: cannot create proc entry %s in %s", name,
+ pdir->name);
+
+ return -ENOMEM;
+}
+
+int CreateProcEntry(const char *name, read_proc_t rhandler,
+ write_proc_t whandler, void *data)
+{
+ return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
+}
+
+int CreatePerProcessProcEntry(const char *name, read_proc_t rhandler,
+ write_proc_t whandler, void *data)
+{
+ struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
+ u32 ui32PID;
+
+ if (!dir) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreatePerProcessProcEntries: /proc/%s doesn't exist",
+ PVRProcDirRoot);
+
+ return -ENOMEM;
+ }
+
+ ui32PID = OSGetCurrentProcessIDKM();
+
+ psPerProc = PVRSRVPerProcessPrivateData(ui32PID);
+ if (!psPerProc) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreatePerProcessProcEntries: no per process data");
+
+ return -ENOMEM;
+ }
+
+ if (!psPerProc->psProcDir) {
+ char dirname[16];
+ int ret;
+
+ ret = snprintf(dirname, sizeof(dirname), "%u", ui32PID);
+
+ if (ret <= 0 || ret >= sizeof(dirname)) {
+ PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: "
+ "couldn't generate per process proc "
+ "directory name \"%u\"",
+ ui32PID);
+
+ return -ENOMEM;
+ } else {
+ psPerProc->psProcDir = proc_mkdir(dirname, dir);
+ if (!psPerProc->psProcDir) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreatePerProcessProcEntries: "
+ "couldn't create per process proc "
+ "directory /proc/%s/%u",
+ PVRProcDirRoot, ui32PID);
+
+ return -ENOMEM;
+ }
+ }
+ }
+
+ return CreateProcEntryInDir(psPerProc->psProcDir, name, rhandler,
+ whandler, data);
+}
+
+int CreateProcReadEntry(const char *name,
+ off_t (handler)(char *, size_t, off_t))
+{
+ struct proc_dir_entry *file;
+
+ if (!dir) {
+ PVR_DPF(PVR_DBG_ERROR, "CreateProcReadEntry: "
+ "cannot make proc entry /proc/%s/%s: no parent",
+ PVRProcDirRoot, name);
+
+ return -ENOMEM;
+ }
+
+ file =
+ create_proc_read_entry(name, S_IFREG | S_IRUGO, dir, pvr_read_proc,
+ (void *)handler);
+
+ if (file)
+ return 0;
+
+ PVR_DPF(PVR_DBG_ERROR, "CreateProcReadEntry: "
+ "cannot make proc entry /proc/%s/%s: no memory",
+ PVRProcDirRoot, name);
+
+ return -ENOMEM;
+}
+
+int CreateProcEntries(void)
+{
+ dir = proc_mkdir(PVRProcDirRoot, NULL);
+
+ if (!dir) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreateProcEntries: cannot make /proc/%s directory",
+ PVRProcDirRoot);
+
+ return -ENOMEM;
+ }
+
+ if (CreateProcReadEntry("queue", QueuePrintQueues) ||
+ CreateProcReadEntry("version", procDumpVersion) ||
+ CreateProcReadEntry("nodes", procDumpSysNodes)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreateProcEntries: couldn't make /proc/%s files",
+ PVRProcDirRoot);
+
+ return -ENOMEM;
+ }
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+ if (CreateProcEntry
+ ("debug_level", PVRDebugProcGetLevel, PVRDebugProcSetLevel, NULL)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "CreateProcEntries: couldn't make /proc/%s/debug_level",
+ PVRProcDirRoot);
+
+ return -ENOMEM;
+ }
+#endif
+
+ return 0;
+}
+
+void RemoveProcEntry(const char *name)
+{
+ if (dir) {
+ remove_proc_entry(name, dir);
+ PVR_DPF(PVR_DBG_MESSAGE, "Removing /proc/%s/%s",
+ PVRProcDirRoot, name);
+ }
+}
+
+void RemovePerProcessProcEntry(const char *name)
+{
+ struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc =
+ PVRSRVFindPerProcessPrivateData();
+
+ if (!psPerProc) {
+ PVR_DPF(PVR_DBG_ERROR, "CreatePerProcessProcEntries: "
+ "can't remove %s, no per process data",
+ name);
+ return;
+ }
+
+ if (psPerProc->psProcDir) {
+ remove_proc_entry(name, psPerProc->psProcDir);
+
+ PVR_DPF(PVR_DBG_MESSAGE, "Removing proc entry %s from %s",
+ name, psPerProc->psProcDir->name);
+ }
+}
+
+void RemovePerProcessProcDir(struct PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
+{
+ if (psPerProc->psProcDir) {
+ while (psPerProc->psProcDir->subdir) {
+ PVR_DPF(PVR_DBG_WARNING,
+ "Belatedly removing /proc/%s/%s/%s",
+ PVRProcDirRoot, psPerProc->psProcDir->name,
+ psPerProc->psProcDir->subdir->name);
+
+ RemoveProcEntry(psPerProc->psProcDir->subdir->name);
+ }
+ RemoveProcEntry(psPerProc->psProcDir->name);
+ }
+}
+
+void RemoveProcEntries(void)
+{
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+ RemoveProcEntry("debug_level");
+#endif
+ RemoveProcEntry("queue");
+ RemoveProcEntry("nodes");
+ RemoveProcEntry("version");
+
+ while (dir->subdir) {
+ PVR_DPF(PVR_DBG_WARNING, "Belatedly removing /proc/%s/%s",
+ PVRProcDirRoot, dir->subdir->name);
+
+ RemoveProcEntry(dir->subdir->name);
+ }
+
+ remove_proc_entry(PVRProcDirRoot, NULL);
+}
+
+static off_t procDumpVersion(char *buf, size_t size, off_t off)
+{
+ struct SYS_DATA *psSysData;
+
+ if (off == 0)
+ return printAppend(buf, size, 0, "Version %s (%s) %s\n",
+ PVRVERSION_STRING, PVR_BUILD_TYPE,
+ PVR_BUILD_DIR);
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
+
+ if (off == 1) {
+ char *pszSystemVersionString = "None";
+
+ if (psSysData->pszVersionString)
+ pszSystemVersionString = psSysData->pszVersionString;
+
+ if (strlen(pszSystemVersionString) +
+ strlen("System Version String: \n") + 1 > size)
+ return 0;
+ return printAppend(buf, size, 0, "System Version String: %s\n",
+ pszSystemVersionString);
+ }
+
+ return END_OF_FILE;
+}
+
+static const char *deviceTypeToString(enum PVRSRV_DEVICE_TYPE deviceType)
+{
+ switch (deviceType) {
+ default:
+ {
+ static char text[10];
+ sprintf(text, "?%x", deviceType);
+ return text;
+ }
+ }
+}
+
+static const char *deviceClassToString(enum PVRSRV_DEVICE_CLASS deviceClass)
+{
+ switch (deviceClass) {
+ case PVRSRV_DEVICE_CLASS_3D:
+ {
+ return "3D";
+ }
+ case PVRSRV_DEVICE_CLASS_DISPLAY:
+ {
+ return "display";
+ }
+ case PVRSRV_DEVICE_CLASS_BUFFER:
+ {
+ return "buffer";
+ }
+ default:
+ {
+ static char text[10];
+
+ sprintf(text, "?%x", deviceClass);
+ return text;
+ }
+ }
+}
+
+static off_t procDumpSysNodes(char *buf, size_t size, off_t off)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_DEVICE_NODE *psDevNode;
+ off_t len;
+
+ if (size < 80)
+ return 0;
+
+ if (off == 0)
+ return printAppend(buf, size, 0,
+ "Registered nodes\n"
+ "Addr Type Class Index Ref pvDev Size Res\n");
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
+
+ for (psDevNode = psSysData->psDeviceNodeList;
+ --off && psDevNode; psDevNode = psDevNode->psNext)
+ ;
+
+ if (!psDevNode)
+ return END_OF_FILE;
+
+ len = printAppend(buf, size, 0,
+ "%p %-8s %-8s %4d %2u %p %3u %p\n",
+ psDevNode,
+ deviceTypeToString(psDevNode->sDevId.eDeviceType),
+ deviceClassToString(psDevNode->sDevId.eDeviceClass),
+ psDevNode->sDevId.eDeviceClass,
+ psDevNode->ui32RefCount,
+ psDevNode->pvDevice,
+ psDevNode->ui32pvDeviceSize,
+ psDevNode->hResManContext);
+ return len;
+}
diff --git a/drivers/gpu/pvr/proc.h b/drivers/gpu/pvr/proc.h
new file mode 100644
index 00000000000..942b2ea9d0b
--- /dev/null
+++ b/drivers/gpu/pvr/proc.h
@@ -0,0 +1,54 @@
+/**********************************************************************
+ *
+ * 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 __SERVICES_PROC_H__
+#define __SERVICES_PROC_H__
+
+#include <asm/system.h>
+#include <linux/proc_fs.h>
+
+#define END_OF_FILE ((off_t) -1)
+
+off_t printAppend(char *buffer, size_t size, off_t off,
+ const char *format, ...)
+ __attribute__ ((format(printf, 4, 5)));
+
+int CreateProcEntries(void);
+int CreateProcReadEntry(const char *name,
+ off_t (handler)(char *, size_t, off_t));
+int CreateProcEntry(const char *name, read_proc_t rhandler,
+ write_proc_t whandler, void *data);
+
+int CreatePerProcessProcEntry(const char *name, read_proc_t rhandler,
+ write_proc_t whandler, void *data);
+
+void RemoveProcEntry(const char *name);
+
+void RemovePerProcessProcEntry(const char *name);
+
+void RemoveProcEntries(void);
+
+#endif
diff --git a/drivers/gpu/pvr/pvr_bridge.h b/drivers/gpu/pvr/pvr_bridge.h
new file mode 100644
index 00000000000..d41e73d5861
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_bridge.h
@@ -0,0 +1,1107 @@
+/**********************************************************************
+ *
+ * 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 __PVR_BRIDGE_H__
+#define __PVR_BRIDGE_H__
+
+
+#include "servicesint.h"
+
+
+#include <linux/ioctl.h>
+
+#define PVRSRV_IOC_GID 'g'
+#define PVRSRV_IO(INDEX) \
+ _IO(PVRSRV_IOC_GID, INDEX, struct PVRSRV_BRIDGE_PACKAGE)
+#define PVRSRV_IOW(INDEX) \
+ _IOW(PVRSRV_IOC_GID, INDEX, struct PVRSRV_BRIDGE_PACKAGE)
+#define PVRSRV_IOR(INDEX) \
+ _IOR(PVRSRV_IOC_GID, INDEX, struct PVRSRV_BRIDGE_PACKAGE)
+#define PVRSRV_IOWR(INDEX) \
+ _IOWR(PVRSRV_IOC_GID, INDEX, struct PVRSRV_BRIDGE_PACKAGE)
+
+
+#define PVRSRV_BRIDGE_CORE_CMD_FIRST 0
+#define PVRSRV_BRIDGE_ENUM_DEVICES \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_ACQUIRE_DEVICEINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_RELEASE_DEVICEINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_DESTROY_DEVMEMCONTEXT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DEVMEM_HEAPINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_ALLOC_DEVICEMEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_FREE_DEVICEMEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_GETFREE_DEVICEMEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_CREATE_COMMANDQUEUE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_DESTROY_COMMANDQUEUE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_CONNECT_SERVICES \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_DISCONNECT_SERVICES \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_WRAP_DEVICE_MEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_GET_DEVICEMEMINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_RESERVE_DEV_VIRTMEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_FREE_DEV_VIRTMEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_MAP_EXT_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_UNMAP_EXT_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+19)
+#define PVRSRV_BRIDGE_MAP_DEV_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+20)
+#define PVRSRV_BRIDGE_UNMAP_DEV_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+21)
+#define PVRSRV_BRIDGE_MAP_DEVICECLASS_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+22)
+#define PVRSRV_BRIDGE_UNMAP_DEVICECLASS_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+23)
+#define PVRSRV_BRIDGE_MAP_MEM_INFO_TO_USER \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+24)
+#define PVRSRV_BRIDGE_UNMAP_MEM_INFO_FROM_USER \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+25)
+#define PVRSRV_BRIDGE_EXPORT_DEVICEMEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+26)
+#define PVRSRV_BRIDGE_RELEASE_MMAP_DATA \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+27)
+#define PVRSRV_BRIDGE_CACHE_FLUSH_DRM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_CORE_CMD_FIRST+28)
+#define PVRSRV_BRIDGE_CORE_CMD_LAST \
+ (PVRSRV_BRIDGE_CORE_CMD_FIRST+28)
+
+#define PVRSRV_BRIDGE_SIM_CMD_FIRST \
+ (PVRSRV_BRIDGE_CORE_CMD_LAST+1)
+#define PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_REGISTER_SIM_PROCESS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_SIM_CMD_LAST \
+ (PVRSRV_BRIDGE_SIM_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_MAPPING_CMD_FIRST \
+ (PVRSRV_BRIDGE_SIM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_MAPPING_CMD_LAST \
+ (PVRSRV_BRIDGE_MAPPING_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_STATS_CMD_FIRST \
+ (PVRSRV_BRIDGE_MAPPING_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_FB_STATS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_STATS_CMD_LAST \
+ (PVRSRV_BRIDGE_STATS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_MISC_CMD_FIRST \
+ (PVRSRV_BRIDGE_STATS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_MISC_INFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_RELEASE_MISC_INFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MISC_CMD_LAST \
+ (PVRSRV_BRIDGE_MISC_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_OVERLAY_CMD_FIRST \
+ (PVRSRV_BRIDGE_MISC_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OVERLAY_CMD_LAST \
+ (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_PDUMP_CMD_FIRST \
+ (PVRSRV_BRIDGE_OVERLAY_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_INIT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_PDUMP_MEMPOL \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_PDUMP_DUMPMEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_PDUMP_REG \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_PDUMP_REGPOL \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_PDUMP_COMMENT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_PDUMP_SETFRAME \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_PDUMP_ISCAPTURING \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_PDUMP_DUMPBITMAP \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_PDUMP_DUMPREADREG \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_PDUMP_SYNCPOL \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_PDUMP_DUMPSYNC \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_PDUMP_MEMPAGES \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_PDUMP_DRIVERINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_PDUMP_PDREG \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_PDUMP_DUMPPDDEVPADDR \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+15)
+#define PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+16)
+#define PVRSRV_BRIDGE_PDUMP_STARTINITPHASE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+17)
+#define PVRSRV_BRIDGE_PDUMP_STOPINITPHASE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST \
+ (PVRSRV_BRIDGE_PDUMP_CMD_FIRST+18)
+#else
+#define PVRSRV_BRIDGE_PDUMP_CMD_LAST PVRSRV_BRIDGE_OVERLAY_CMD_LAST
+#endif
+
+#define PVRSRV_BRIDGE_OEM_CMD_FIRST \
+ (PVRSRV_BRIDGE_PDUMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GET_OEMJTABLE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_OEM_CMD_LAST \
+ (PVRSRV_BRIDGE_OEM_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST \
+ (PVRSRV_BRIDGE_OEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ENUM_CLASS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_DEVCLASS_CMD_LAST \
+ (PVRSRV_BRIDGE_DEVCLASS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST \
+ (PVRSRV_BRIDGE_DEVCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+4)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_INFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+5)
+#define PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+6)
+#define PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+7)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTRECT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+8)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCRECT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+9)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_DSTCOLOURKEY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+10)
+#define PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+11)
+#define PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+12)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+13)
+#define PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+#define PVRSRV_BRIDGE_DISPCLASS_CMD_LAST \
+ (PVRSRV_BRIDGE_DISPCLASS_CMD_FIRST+14)
+
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST \
+ (PVRSRV_BRIDGE_DISPCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_BUFCLASS_CMD_LAST \
+ (PVRSRV_BRIDGE_BUFCLASS_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_WRAP_CMD_FIRST \
+ (PVRSRV_BRIDGE_BUFCLASS_CMD_LAST+1)
+#define PVRSRV_BRIDGE_WRAP_EXT_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_WRAP_CMD_LAST \
+ (PVRSRV_BRIDGE_WRAP_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST \
+ (PVRSRV_BRIDGE_WRAP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_MAP_MEMINFO_MEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_UNMAP_MEMINFO_MEM \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+#define PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST \
+ (PVRSRV_BRIDGE_SHAREDMEM_CMD_FIRST+3)
+
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST \
+ (PVRSRV_BRIDGE_SHAREDMEM_CMD_LAST+1)
+#define PVRSRV_BRIDGE_GETMMU_PD_DEVPADDR \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST \
+ (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_INITSRV_CMD_FIRST \
+ (PVRSRV_BRIDGE_SERVICES4_TMP_CMD_LAST+1)
+#define PVRSRV_BRIDGE_INITSRV_CONNECT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_INITSRV_DISCONNECT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_INITSRV_CMD_LAST \
+ (PVRSRV_BRIDGE_INITSRV_CMD_FIRST+1)
+
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST \
+ (PVRSRV_BRIDGE_INITSRV_CMD_LAST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_WAIT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_OPEN \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+1)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+#define PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST \
+ (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_FIRST+2)
+
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST \
+ (PVRSRV_BRIDGE_EVENT_OBJECT_CMD_LAST+1)
+#define PVRSRV_BRIDGE_MODIFY_SYNC_OPS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+#define PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST \
+ (PVRSRV_BRIDGE_SYNC_OPS_CMD_FIRST+0)
+
+#define PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD \
+ (PVRSRV_BRIDGE_SYNC_OPS_CMD_LAST+1)
+
+#define PVRSRV_KERNEL_MODE_CLIENT 1
+
+struct PVRSRV_BRIDGE_RETURN {
+ enum PVRSRV_ERROR eError;
+ void *pvData;
+};
+
+struct PVRSRV_BRIDGE_PACKAGE {
+ u32 ui32BridgeID;
+ u32 ui32Size;
+ void __user *pvParamIn;
+ u32 ui32InBufferSize;
+ void __user *pvParamOut;
+ u32 ui32OutBufferSize;
+
+ void *hKernelServices;
+};
+
+struct PVRSRV_BRIDGE_IN_ACQUIRE_DEVICEINFO {
+ u32 ui32BridgeFlags;
+ u32 uiDevIndex;
+ enum PVRSRV_DEVICE_TYPE eDeviceType;
+};
+
+struct PVRSRV_BRIDGE_IN_ENUMCLASS {
+ u32 ui32BridgeFlags;
+ enum PVRSRV_DEVICE_CLASS sDeviceClass;
+};
+
+struct PVRSRV_BRIDGE_IN_CLOSE_DISPCLASS_DEVICE {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_FORMATS {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_INFO {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_IN_CLOSE_BUFFERCLASS_DEVICE {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_INFO {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_IN_RELEASE_DEVICEINFO {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_IN_FREE_CLASSDEVICEINFO {
+ u32 ui32BridgeFlags;
+ enum PVRSRV_DEVICE_CLASS DeviceClass;
+ void *pvDevInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_DEVMEM_HEAPINFO {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hDevMemContext;
+};
+
+struct PVRSRV_BRIDGE_IN_CREATE_DEVMEMCONTEXT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_IN_DESTROY_DEVMEMCONTEXT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hDevMemContext;
+};
+
+struct PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hDevMemHeap;
+ u32 ui32Attribs;
+ u32 ui32Size;
+ u32 ui32Alignment;
+};
+
+struct PVRSRV_BRIDGE_IN_MAPMEMINFOTOUSER {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_UNMAPMEMINFOFROMUSER {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ void *pvLinAddr;
+ void *hMappingInfo;
+};
+
+#define DRM_PVR2D_CFLUSH_FROM_GPU 1
+#define DRM_PVR2D_CFLUSH_TO_GPU 2
+
+struct PVRSRV_BRIDGE_IN_CACHEFLUSHDRMFROMUSER {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ u32 ui32Type;
+ u32 ui32Virt;
+ u32 ui32Length;
+};
+
+struct PVRSRV_BRIDGE_IN_FREEDEVICEMEM {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+
+};
+
+struct PVRSRV_BRIDGE_IN_EXPORTDEVICEMEM {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+};
+
+struct PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM {
+ u32 ui32BridgeFlags;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_CREATECOMMANDQUEUE {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ u32 ui32QueueSize;
+};
+
+struct PVRSRV_BRIDGE_IN_DESTROYCOMMANDQUEUE {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct PVRSRV_QUEUE_INFO *psQueueInfo;
+
+};
+
+struct PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA {
+ u32 ui32BridgeFlags;
+ void *hMHandle;
+};
+
+struct PVRSRV_BRIDGE_IN_RELEASE_MMAP_DATA {
+ u32 ui32BridgeFlags;
+ void *hMHandle;
+};
+
+struct PVRSRV_BRIDGE_IN_RESERVE_DEV_VIRTMEM {
+ u32 ui32BridgeFlags;
+ void *hDevMemHeap;
+ struct IMG_DEV_VIRTADDR *psDevVAddr;
+ u32 ui32Size;
+ u32 ui32Alignment;
+};
+
+struct PVRSRV_BRIDGE_OUT_CONNECT_SERVICES {
+ enum PVRSRV_ERROR eError;
+ void *hKernelServices;
+};
+
+struct PVRSRV_BRIDGE_OUT_RESERVE_DEV_VIRTMEM {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_FREE_DEV_VIRTMEM {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_MAP_DEV_MEMORY {
+ u32 ui32BridgeFlags;
+ void *hKernelMemInfo;
+ void *hDstDevMemHeap;
+};
+
+struct PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_KERNEL_MEM_INFO *psDstKernelMemInfo;
+ struct PVRSRV_KERNEL_SYNC_INFO *psDstKernelSyncInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sDstClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sDstClientSyncInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_UNMAP_DEV_MEMORY {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_MAP_EXT_MEMORY {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct IMG_SYS_PHYADDR *psSysPAddr;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_UNMAP_EXT_MEMORY {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_MAP_DEVICECLASS_MEMORY {
+ u32 ui32BridgeFlags;
+ void *hDeviceClassBuffer;
+ void *hDevMemContext;
+
+};
+
+struct PVRSRV_BRIDGE_OUT_MAP_DEVICECLASS_MEMORY {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ void *hMappingInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_UNMAP_DEVICECLASS_MEMORY {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_MEMPOL {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ u32 ui32Offset;
+ u32 ui32Value;
+ u32 ui32Mask;
+ IMG_BOOL bLastFrame;
+ IMG_BOOL bOverwrite;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_SYNCPOL {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ IMG_BOOL bIsRead;
+ u32 ui32Value;
+ u32 ui32Mask;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_DUMPMEM {
+ u32 ui32BridgeFlags;
+ void *pvLinAddr;
+ void *pvAltLinAddr;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ u32 ui32Offset;
+ u32 ui32Bytes;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_DUMPSYNC {
+ u32 ui32BridgeFlags;
+ void *pvAltLinAddr;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ u32 ui32Offset;
+ u32 ui32Bytes;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_DUMPREG {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_HWREG sHWReg;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_REGPOL {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_HWREG sHWReg;
+ u32 ui32Mask;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDREG {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_HWREG sHWReg;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_MEMPAGES {
+ u32 ui32BridgeFlags;
+ void *hKernelMemInfo;
+ struct IMG_DEV_PHYADDR *pPages;
+ u32 ui32NumPages;
+ struct IMG_DEV_VIRTADDR sDevAddr;
+ u32 ui32Start;
+ u32 ui32Length;
+ IMG_BOOL bContinuous;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_COMMENT {
+ u32 ui32BridgeFlags;
+ char szComment[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_SETFRAME {
+ u32 ui32BridgeFlags;
+ u32 ui32Frame;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_BITMAP {
+ u32 ui32BridgeFlags;
+ char szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ u32 ui32FileOffset;
+ u32 ui32Width;
+ u32 ui32Height;
+ u32 ui32StrideInBytes;
+ struct IMG_DEV_VIRTADDR sDevBaseAddr;
+ u32 ui32Size;
+ enum PDUMP_PIXEL_FORMAT ePixelFormat;
+ enum PDUMP_MEM_FORMAT eMemFormat;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_READREG {
+ u32 ui32BridgeFlags;
+ char szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ u32 ui32FileOffset;
+ u32 ui32Address;
+ u32 ui32Size;
+ u32 ui32Flags;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_DRIVERINFO {
+ u32 ui32BridgeFlags;
+ char szString[PVRSRV_PDUMP_MAX_COMMENT_SIZE];
+ IMG_BOOL bContinuous;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_DUMPPDDEVPADDR {
+ u32 ui32BridgeFlags;
+ void *hKernelMemInfo;
+ u32 ui32Offset;
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_CYCLE_COUNT_REG_READ {
+ u32 ui32BridgeFlags;
+ u32 ui32RegOffset;
+ IMG_BOOL bLastFrame;
+};
+
+struct PVRSRV_BRIDGE_OUT_ENUMDEVICE {
+ enum PVRSRV_ERROR eError;
+ u32 ui32NumDevices;
+ struct PVRSRV_DEVICE_IDENTIFIER asDeviceIdentifier[PVRSRV_MAX_DEVICES];
+};
+
+struct PVRSRV_BRIDGE_OUT_ACQUIRE_DEVICEINFO {
+
+ enum PVRSRV_ERROR eError;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_OUT_ENUMCLASS {
+ enum PVRSRV_ERROR eError;
+ u32 ui32NumDevices;
+ u32 ui32DevID[PVRSRV_MAX_DEVICES];
+};
+
+struct PVRSRV_BRIDGE_IN_OPEN_DISPCLASS_DEVICE {
+ u32 ui32BridgeFlags;
+ u32 ui32DeviceID;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_OUT_OPEN_DISPCLASS_DEVICE {
+ enum PVRSRV_ERROR eError;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hDevMemContext;
+ void *pvLinAddr;
+ u32 ui32ByteSize;
+ u32 ui32PageOffset;
+ IMG_BOOL bPhysContig;
+ u32 ui32NumPageTableEntries;
+ struct IMG_SYS_PHYADDR __user *psSysPAddr;
+};
+
+struct PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_UNWRAP_EXT_MEMORY {
+ u32 ui32BridgeFlags;
+ void *hKernelMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+};
+
+#define PVRSRV_MAX_DC_DISPLAY_FORMATS 10
+#define PVRSRV_MAX_DC_DISPLAY_DIMENSIONS 10
+#define PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS 4
+#define PVRSRV_MAX_DC_CLIP_RECTS 32
+
+struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_FORMATS {
+ enum PVRSRV_ERROR eError;
+ u32 ui32Count;
+ struct DISPLAY_FORMAT asFormat[PVRSRV_MAX_DC_DISPLAY_FORMATS];
+};
+
+struct PVRSRV_BRIDGE_IN_ENUM_DISPCLASS_DIMS {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ struct DISPLAY_FORMAT sFormat;
+};
+
+struct PVRSRV_BRIDGE_OUT_ENUM_DISPCLASS_DIMS {
+ enum PVRSRV_ERROR eError;
+ u32 ui32Count;
+ struct DISPLAY_DIMS asDim[PVRSRV_MAX_DC_DISPLAY_DIMENSIONS];
+};
+
+struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_INFO {
+ enum PVRSRV_ERROR eError;
+ struct DISPLAY_INFO sDisplayInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER {
+ enum PVRSRV_ERROR eError;
+ void *hBuffer;
+};
+
+struct PVRSRV_BRIDGE_IN_CREATE_DISPCLASS_SWAPCHAIN {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ u32 ui32Flags;
+ struct DISPLAY_SURF_ATTRIBUTES sDstSurfAttrib;
+ struct DISPLAY_SURF_ATTRIBUTES sSrcSurfAttrib;
+ u32 ui32BufferCount;
+ u32 ui32OEMFlags;
+ u32 ui32SwapChainID;
+};
+
+struct PVRSRV_BRIDGE_OUT_CREATE_DISPCLASS_SWAPCHAIN {
+ enum PVRSRV_ERROR eError;
+ void *hSwapChain;
+ u32 ui32SwapChainID;
+};
+
+struct PVRSRV_BRIDGE_IN_DESTROY_DISPCLASS_SWAPCHAIN {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ void *hSwapChain;
+};
+
+struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_RECT {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ void *hSwapChain;
+ struct IMG_RECT sRect;
+};
+
+struct PVRSRV_BRIDGE_IN_SET_DISPCLASS_COLOURKEY {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ void *hSwapChain;
+ u32 ui32CKColour;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_DISPCLASS_BUFFERS {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ void *hSwapChain;
+};
+
+struct PVRSRV_BRIDGE_OUT_GET_DISPCLASS_BUFFERS {
+ enum PVRSRV_ERROR eError;
+ u32 ui32BufferCount;
+ void *ahBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS];
+};
+
+struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ void *hBuffer;
+ u32 ui32SwapInterval;
+ void *hPrivateTag;
+ u32 ui32ClipRectCount;
+ struct IMG_RECT sClipRect[PVRSRV_MAX_DC_CLIP_RECTS];
+};
+
+struct PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ void *hSwapChain;
+};
+
+struct PVRSRV_BRIDGE_IN_OPEN_BUFFERCLASS_DEVICE {
+ u32 ui32BridgeFlags;
+ u32 ui32DeviceID;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_OUT_OPEN_BUFFERCLASS_DEVICE {
+ enum PVRSRV_ERROR eError;
+ void *hDeviceKM;
+};
+
+struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_INFO {
+ enum PVRSRV_ERROR eError;
+ struct BUFFER_INFO sBufferInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_BUFFERCLASS_BUFFER {
+ u32 ui32BridgeFlags;
+ void *hDeviceKM;
+ u32 ui32BufferIndex;
+};
+
+struct PVRSRV_BRIDGE_OUT_GET_BUFFERCLASS_BUFFER {
+ enum PVRSRV_ERROR eError;
+ void *hBuffer;
+};
+
+struct PVRSRV_BRIDGE_OUT_GET_DEVMEM_HEAPINFO {
+ enum PVRSRV_ERROR eError;
+ u32 ui32ClientHeapCount;
+ struct PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+};
+
+struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT {
+ enum PVRSRV_ERROR eError;
+ void *hDevMemContext;
+ u32 ui32ClientHeapCount;
+ struct PVRSRV_HEAP_INFO sHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+};
+
+struct PVRSRV_BRIDGE_OUT_CREATE_DEVMEMHEAP {
+ enum PVRSRV_ERROR eError;
+ void *hDevMemHeap;
+};
+
+struct PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+
+};
+
+struct PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM {
+ enum PVRSRV_ERROR eError;
+ void *hMemInfo;
+
+};
+
+struct PVRSRV_BRIDGE_OUT_MAPMEMINFOTOUSER {
+ enum PVRSRV_ERROR eError;
+ void *pvLinAddr;
+ void *hMappingInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_GETFREEDEVICEMEM {
+ enum PVRSRV_ERROR eError;
+ u32 ui32Total;
+ u32 ui32Free;
+ u32 ui32LargestBlock;
+};
+
+#include "pvrmmap.h"
+struct PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA {
+ enum PVRSRV_ERROR eError;
+ u32 ui32MMapOffset;
+ u32 ui32ByteOffset;
+ u32 ui32RealByteSize;
+ u32 ui32UserVAddr;
+};
+
+struct PVRSRV_BRIDGE_OUT_RELEASE_MMAP_DATA {
+ enum PVRSRV_ERROR eError;
+ IMG_BOOL bMUnmap;
+ u32 ui32UserVAddr;
+ u32 ui32RealByteSize;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_MISC_INFO {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_MISC_INFO sMiscInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_GET_MISC_INFO {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_MISC_INFO sMiscInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_RELEASE_MISC_INFO {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_MISC_INFO sMiscInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_RELEASE_MISC_INFO {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_MISC_INFO sMiscInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_PDUMP_ISCAPTURING {
+ enum PVRSRV_ERROR eError;
+ IMG_BOOL bIsCapturing;
+};
+
+struct PVRSRV_BRIDGE_IN_GET_FB_STATS {
+ u32 ui32BridgeFlags;
+ u32 ui32Total;
+ u32 ui32Available;
+};
+
+struct PVRSRV_BRIDGE_IN_MAPPHYSTOUSERSPACE {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct IMG_SYS_PHYADDR sSysPhysAddr;
+ u32 uiSizeInBytes;
+};
+
+struct PVRSRV_BRIDGE_OUT_MAPPHYSTOUSERSPACE {
+ void *pvUserAddr;
+ u32 uiActualSize;
+ void *pvProcess;
+};
+
+struct PVRSRV_BRIDGE_IN_UNMAPPHYSTOUSERSPACE {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *pvUserAddr;
+ void *pvProcess;
+};
+
+struct PVRSRV_BRIDGE_OUT_GETPHYSTOUSERSPACEMAP {
+ void **ppvTbl;
+ u32 uiTblSize;
+};
+
+struct PVRSRV_BRIDGE_IN_REGISTER_SIM_PROCESS {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *pvProcess;
+};
+
+struct PVRSRV_BRIDGE_OUT_REGISTER_SIM_PROCESS {
+ struct IMG_SYS_PHYADDR sRegsPhysBase;
+ void *pvRegsBase;
+ void *pvProcess;
+ u32 ulNoOfEntries;
+ void *pvTblLinAddr;
+};
+
+struct PVRSRV_BRIDGE_IN_UNREGISTER_SIM_PROCESS {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *pvProcess;
+ void *pvRegsBase;
+};
+
+struct PVRSRV_BRIDGE_IN_PROCESS_SIMISR_EVENT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ u32 ui32StatusAndMask;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_INITSRV_DISCONNECT {
+ u32 ui32BridgeFlags;
+ IMG_BOOL bInitSuccesful;
+};
+
+struct PVRSRV_BRIDGE_IN_ALLOC_SHARED_SYS_MEM {
+ u32 ui32BridgeFlags;
+ u32 ui32Flags;
+ u32 ui32Size;
+};
+
+struct PVRSRV_BRIDGE_OUT_ALLOC_SHARED_SYS_MEM {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_FREE_SHARED_SYS_MEM {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_FREE_SHARED_SYS_MEM {
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_MAP_MEMINFO_MEM {
+ u32 ui32BridgeFlags;
+ void *hKernelMemInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_MAP_MEMINFO_MEM {
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+ struct PVRSRV_CLIENT_SYNC_INFO sClientSyncInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_UNMAP_MEMINFO_MEM {
+ u32 ui32BridgeFlags;
+ struct PVRSRV_CLIENT_MEM_INFO sClientMemInfo;
+};
+
+struct PVRSRV_BRIDGE_OUT_UNMAP_MEMINFO_MEM {
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_GETMMU_PD_DEVPADDR {
+ u32 ui32BridgeFlags;
+ void *hDevMemContext;
+};
+
+struct PVRSRV_BRIDGE_OUT_GETMMU_PD_DEVPADDR {
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_WAIT {
+ u32 ui32BridgeFlags;
+ void *hOSEventKM;
+};
+
+struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_OPEN {
+ struct PVRSRV_EVENTOBJECT sEventObject;
+};
+
+struct PVRSRV_BRIDGE_OUT_EVENT_OBJECT_OPEN {
+ void *hOSEvent;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_EVENT_OBJECT_CLOSE {
+ struct PVRSRV_EVENTOBJECT sEventObject;
+ void *hOSEventKM;
+};
+
+struct PVRSRV_BRIDGE_IN_MODIFY_SYNC_OPS {
+ u32 ui32BridgeFlags;
+ void *hKernelSyncInfo;
+ u32 ui32ModifyFlags;
+
+};
+
+struct PVRSRV_BRIDGE_OUT_MODIFY_SYNC_OPS {
+ enum PVRSRV_ERROR eError;
+ u32 ui32ReadOpsPending;
+ u32 ui32ReadOpsComplete;
+ u32 ui32WriteOpsPending;
+ u32 ui32WriteOpsComplete;
+
+};
+
+#endif
diff --git a/drivers/gpu/pvr/pvr_bridge_k.c b/drivers/gpu/pvr/pvr_bridge_k.c
new file mode 100644
index 00000000000..4cbc04167d7
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_bridge_k.c
@@ -0,0 +1,241 @@
+/**********************************************************************
+ *
+ * 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 <linux/sched.h>
+
+#include "img_defs.h"
+#include "services.h"
+#include "pvr_bridge.h"
+#include "pvr_bridge_km.h"
+#include "perproc.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "private_data.h"
+
+#include "sgx_bridge.h"
+
+#include "bridged_pvr_bridge.h"
+
+/* Global driver lock protecting all HW and SW state tracking objects. */
+DEFINE_MUTEX(gPVRSRVLock);
+static int pvr_dev_locked;
+static DECLARE_WAIT_QUEUE_HEAD(pvr_dev_wq);
+int pvr_disabled;
+
+/*
+ * The pvr_dvfs_* interface is needed to suppress a lockdep warning in
+ * the following situation during a clock rate change:
+ * On the CLK_PRE_RATE_CHANGE:
+ * 1. lock A <- __blocking_notifier_call_chain:nh->rwsem
+ * 2. lock B <- vdd2_pre_post_func:gPVRSRVLock
+ * 3. unlock A
+ *
+ * On the CLK_POST_RATE_CHANGE/CLK_ABORT_RATE_CHANGE:
+ * 4. lock A
+ * 5. unlock B
+ * 6. unlock A
+ *
+ * The above has an ABA lock pattern which triggers the warning. This can't
+ * lead to a dead lock though since at 3. we always release A, before it's
+ * again acquired at 4. To avoid the warning use a wait queue based approach
+ * so that we can unlock B before 3.
+ */
+void pvr_dev_lock(void)
+{
+ while (cmpxchg(&pvr_dev_locked, 0, 1)) {
+ DEFINE_WAIT(pvr_dev_wait);
+ prepare_to_wait(&pvr_dev_wq, &pvr_dev_wait,
+ TASK_UNINTERRUPTIBLE);
+ if (pvr_dev_locked)
+ schedule();
+ finish_wait(&pvr_dev_wq, &pvr_dev_wait);
+ }
+}
+
+void pvr_dev_unlock(void)
+{
+ BUG_ON(!pvr_dev_locked);
+ pvr_dev_locked = 0;
+ wake_up(&pvr_dev_wq);
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+static off_t printLinuxBridgeStats(char *buffer, size_t size, off_t off);
+#endif
+
+enum PVRSRV_ERROR LinuxBridgeInit(void)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ {
+ int iStatus;
+ iStatus =
+ CreateProcReadEntry("bridge_stats", printLinuxBridgeStats);
+ if (iStatus != 0)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+#endif
+ return CommonBridgeInit();
+}
+
+void LinuxBridgeDeInit(void)
+{
+#if defined(DEBUG_BRIDGE_KM)
+ RemoveProcEntry("bridge_stats");
+#endif
+}
+
+#if defined(DEBUG_BRIDGE_KM)
+static off_t printLinuxBridgeStats(char *buffer, size_t count, off_t off)
+{
+ struct PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry;
+ off_t Ret;
+
+ pvr_lock();
+
+ if (!off) {
+ if (count < 500) {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+ Ret = printAppend(buffer, count, 0,
+ "Total ioctl call count = %u\n"
+ "Total number of bytes copied via copy_from_user = %u\n"
+ "Total number of bytes copied via copy_to_user = %u\n"
+ "Total number of bytes copied via copy_*_user = %u\n\n"
+ "%-45s | %-40s | %10s | %20s | %10s\n",
+ g_BridgeGlobalStats.ui32IOCTLCount,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ g_BridgeGlobalStats.ui32TotalCopyFromUserBytes +
+ g_BridgeGlobalStats.ui32TotalCopyToUserBytes,
+ "Bridge Name", "Wrapper Function",
+ "Call Count", "copy_from_user Bytes",
+ "copy_to_user Bytes");
+
+ goto unlock_and_return;
+ }
+
+ if (off > BRIDGE_DISPATCH_TABLE_ENTRY_COUNT) {
+ Ret = END_OF_FILE;
+ goto unlock_and_return;
+ }
+
+ if (count < 300) {
+ Ret = 0;
+ goto unlock_and_return;
+ }
+
+ psEntry = &g_BridgeDispatchTable[off - 1];
+ Ret = printAppend(buffer, count, 0,
+ "%-45s %-40s %-10u %-20u %-10u\n",
+ psEntry->pszIOCName,
+ psEntry->pszFunctionName,
+ psEntry->ui32CallCount,
+ psEntry->ui32CopyFromUserTotalBytes,
+ psEntry->ui32CopyToUserTotalBytes);
+
+unlock_and_return:
+ pvr_unlock();
+
+ return Ret;
+}
+#endif
+
+long PVRSRV_BridgeDispatchKM(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ u32 ui32BridgeID = PVRSRV_GET_BRIDGE_ID(cmd);
+ struct PVRSRV_BRIDGE_PACKAGE __user *psBridgePackageUM =
+ (struct PVRSRV_BRIDGE_PACKAGE __user *)arg;
+ struct PVRSRV_BRIDGE_PACKAGE sBridgePackageKM;
+ u32 ui32PID = OSGetCurrentProcessIDKM();
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc;
+ int err = -EFAULT;
+
+ pvr_lock();
+
+ if (pvr_is_disabled()) {
+ pvr_unlock();
+ return -ENODEV;
+ }
+
+ if (!OSAccessOK(PVR_VERIFY_WRITE, psBridgePackageUM,
+ sizeof(struct PVRSRV_BRIDGE_PACKAGE))) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Received invalid pointer to function arguments",
+ __func__);
+
+ goto unlock_and_return;
+ }
+
+ if (OSCopyFromUser(NULL, &sBridgePackageKM, psBridgePackageUM,
+ sizeof(struct PVRSRV_BRIDGE_PACKAGE)) != PVRSRV_OK)
+ goto unlock_and_return;
+
+ if (ui32BridgeID !=
+ PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES)) {
+ enum PVRSRV_ERROR eError;
+
+ eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (void **)&psPerProc,
+ sBridgePackageKM.hKernelServices,
+ PVRSRV_HANDLE_TYPE_PERPROC_DATA);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Invalid kernel services handle (%d)",
+ __func__, eError);
+ goto unlock_and_return;
+ }
+
+ if (psPerProc->ui32PID != ui32PID) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: Process %d tried to access data "
+ "belonging to process %d", __func__,
+ ui32PID, psPerProc->ui32PID);
+ goto unlock_and_return;
+ }
+ } else {
+ psPerProc = PVRSRVPerProcessData(ui32PID);
+ if (psPerProc == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRV_BridgeDispatchKM: "
+ "Couldn't create per-process data area");
+ goto unlock_and_return;
+ }
+ }
+
+ sBridgePackageKM.ui32BridgeID = PVRSRV_GET_BRIDGE_ID(
+ sBridgePackageKM.ui32BridgeID);
+
+ err = BridgedDispatchKM(filp, psPerProc, &sBridgePackageKM);
+ if (err != PVRSRV_OK)
+ goto unlock_and_return;
+
+unlock_and_return:
+ pvr_unlock();
+
+ return err;
+}
diff --git a/drivers/gpu/pvr/pvr_bridge_km.h b/drivers/gpu/pvr/pvr_bridge_km.h
new file mode 100644
index 00000000000..55392f2d574
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_bridge_km.h
@@ -0,0 +1,222 @@
+/**********************************************************************
+ *
+ * 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 __PVR_BRIDGE_KM_H_
+#define __PVR_BRIDGE_KM_H_
+
+#include <linux/fs.h> /* for struct file */
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+extern void pvr_dev_lock(void);
+extern void pvr_dev_unlock(void);
+extern struct mutex gPVRSRVLock;
+extern int pvr_disabled;
+
+static inline void pvr_lock(void)
+{
+ mutex_lock(&gPVRSRVLock);
+}
+
+static inline void pvr_unlock(void)
+{
+ mutex_unlock(&gPVRSRVLock);
+}
+
+static inline int pvr_is_locked(void)
+{
+ return mutex_is_locked(&gPVRSRVLock);
+}
+
+static inline void pvr_disable(void)
+{
+ pvr_disabled = 1;
+}
+
+static inline int pvr_is_disabled(void)
+{
+ return unlikely(pvr_disabled);
+}
+
+enum PVRSRV_ERROR LinuxBridgeInit(void);
+void LinuxBridgeDeInit(void);
+
+enum PVRSRV_ERROR PVRSRVEnumerateDevicesKM(u32 *pui32NumDevices,
+ struct PVRSRV_DEVICE_IDENTIFIER *psDevIdList);
+
+enum PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(u32 uiDevIndex,
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void **phDevCookie);
+
+enum PVRSRV_ERROR PVRSRVCreateCommandQueueKM(u32 ui32QueueSize,
+ struct PVRSRV_QUEUE_INFO **ppsQueueInfo);
+
+enum PVRSRV_ERROR PVRSRVDestroyCommandQueueKM(
+ struct PVRSRV_QUEUE_INFO *psQueueInfo);
+
+enum PVRSRV_ERROR PVRSRVGetDeviceMemHeapsKM(void *hDevCookie,
+ struct PVRSRV_HEAP_INFO *psHeapInfo);
+
+enum PVRSRV_ERROR PVRSRVCreateDeviceMemContextKM(void *hDevCookie,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void **phDevMemContext, u32 *pui32ClientHeapCount,
+ struct PVRSRV_HEAP_INFO *psHeapInfo, IMG_BOOL *pbCreated,
+ IMG_BOOL *pbShared);
+
+enum PVRSRV_ERROR PVRSRVDestroyDeviceMemContextKM(void *hDevCookie,
+ void *hDevMemContext, IMG_BOOL *pbCreated);
+
+enum PVRSRV_ERROR PVRSRVGetDeviceMemHeapInfoKM(void *hDevCookie,
+ void *hDevMemContext, u32 *pui32ClientHeapCount,
+ struct PVRSRV_HEAP_INFO *psHeapInfo, IMG_BOOL *pbShared);
+
+enum PVRSRV_ERROR PVRSRVAllocDeviceMemKM(void *hDevCookie,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevMemHeap,
+ u32 ui32Flags, u32 ui32Size, u32 ui32Alignment,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+enum PVRSRV_ERROR PVRSRVFreeDeviceMemKM(void *hDevCookie,
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+enum PVRSRV_ERROR PVRSRVDissociateDeviceMemKM(void *hDevCookie,
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+enum PVRSRV_ERROR PVRSRVReserveDeviceVirtualMemKM(void *hDevMemHeap,
+ struct IMG_DEV_VIRTADDR *psDevVAddr, u32 ui32Size,
+ u32 ui32Alignment, struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+enum PVRSRV_ERROR PVRSRVFreeDeviceVirtualMemKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+enum PVRSRV_ERROR PVRSRVMapDeviceMemoryKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ struct PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
+ void *hDstDevMemHeap,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsDstMemInfo);
+
+enum PVRSRV_ERROR PVRSRVUnmapDeviceMemoryKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+enum PVRSRV_ERROR PVRSRVWrapExtMemoryKM(void *hDevCookie,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevMemContext,
+ u32 ui32ByteSize, u32 ui32PageOffset, IMG_BOOL bPhysContig,
+ struct IMG_SYS_PHYADDR *psSysAddr, void *pvLinAddr,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+enum PVRSRV_ERROR PVRSRVUnwrapExtMemoryKM(struct PVRSRV_KERNEL_MEM_INFO
+ *psMemInfo);
+
+enum PVRSRV_ERROR PVRSRVEnumerateDCKM(enum PVRSRV_DEVICE_CLASS DeviceClass,
+ u32 *pui32DevCount, u32 *pui32DevID);
+
+enum PVRSRV_ERROR PVRSRVOpenDCDeviceKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ u32 ui32DeviceID, void *hDevCookie, void **phDeviceKM);
+
+enum PVRSRV_ERROR PVRSRVCloseDCDeviceKM(void *hDeviceKM,
+ IMG_BOOL bResManCallback);
+
+enum PVRSRV_ERROR PVRSRVEnumDCFormatsKM(void *hDeviceKM, u32 *pui32Count,
+ struct DISPLAY_FORMAT *psFormat);
+
+enum PVRSRV_ERROR PVRSRVEnumDCDimsKM(void *hDeviceKM,
+ struct DISPLAY_FORMAT *psFormat, u32 *pui32Count,
+ struct DISPLAY_DIMS *psDim);
+
+enum PVRSRV_ERROR PVRSRVGetDCSystemBufferKM(void *hDeviceKM, void **phBuffer);
+
+enum PVRSRV_ERROR PVRSRVGetDCInfoKM(void *hDeviceKM,
+ struct DISPLAY_INFO *psDisplayInfo);
+
+enum PVRSRV_ERROR PVRSRVCreateDCSwapChainKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDeviceKM,
+ u32 ui32Flags, struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
+ struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
+ u32 ui32BufferCount, u32 ui32OEMFlags, void **phSwapChain,
+ u32 *pui32SwapChainID);
+
+enum PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(void *hSwapChain);
+enum PVRSRV_ERROR PVRSRVSetDCDstRectKM(void *hDeviceKM, void *hSwapChain,
+ struct IMG_RECT *psRect);
+enum PVRSRV_ERROR PVRSRVSetDCSrcRectKM(void *hDeviceKM, void *hSwapChain,
+ struct IMG_RECT *psRect);
+enum PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(void *hDeviceKM, void *hSwapChain,
+ u32 ui32CKColour);
+enum PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(void *hDeviceKM, void *hSwapChain,
+ u32 ui32CKColour);
+enum PVRSRV_ERROR PVRSRVGetDCBuffersKM(void *hDeviceKM, void *hSwapChain,
+ u32 *pui32BufferCount, void **phBuffer);
+enum PVRSRV_ERROR PVRSRVSwapToDCBufferKM(void *hDeviceKM, void *hBuffer,
+ u32 ui32SwapInterval, void *hPrivateTag,
+ u32 ui32ClipRectCount, struct IMG_RECT *psClipRect);
+enum PVRSRV_ERROR PVRSRVSwapToDCSystemKM(void *hDeviceKM, void *hSwapChain);
+
+enum PVRSRV_ERROR PVRSRVOpenBCDeviceKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ u32 ui32DeviceID, void *hDevCookie, void **phDeviceKM);
+enum PVRSRV_ERROR PVRSRVCloseBCDeviceKM(void *hDeviceKM,
+ IMG_BOOL bResManCallback);
+
+enum PVRSRV_ERROR PVRSRVGetBCInfoKM(void *hDeviceKM,
+ struct BUFFER_INFO *psBufferInfo);
+enum PVRSRV_ERROR PVRSRVGetBCBufferKM(void *hDeviceKM,
+ u32 ui32BufferIndex, void **phBuffer);
+
+enum PVRSRV_ERROR PVRSRVMapDeviceClassMemoryKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc, void *hDevMemContext,
+ void *hDeviceClassBuffer,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsMemInfo, void **phOSMapInfo);
+
+enum PVRSRV_ERROR PVRSRVUnmapDeviceClassMemoryKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+
+enum PVRSRV_ERROR PVRSRVGetFreeDeviceMemKM(u32 ui32Flags, u32 *pui32Total,
+ u32 *pui32Free, u32 *pui32LargestBlock);
+enum PVRSRV_ERROR PVRSRVAllocSyncInfoKM(void *hDevCookie, void *hDevMemContext,
+ struct PVRSRV_KERNEL_SYNC_INFO **ppsKernelSyncInfo);
+enum PVRSRV_ERROR PVRSRVFreeSyncInfoKM(
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
+
+enum PVRSRV_ERROR PVRSRVGetMiscInfoKM(struct PVRSRV_MISC_INFO *psMiscInfo);
+
+enum PVRSRV_ERROR PVRSRVGetFBStatsKM(u32 *pui32Total, u32 *pui32Available);
+
+enum PVRSRV_ERROR PVRSRVAllocSharedSysMemoryKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc, u32 ui32Flags,
+ u32 ui32Size, struct PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo);
+
+enum PVRSRV_ERROR PVRSRVFreeSharedSysMemoryKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+enum PVRSRV_ERROR PVRSRVDissociateMemFromResmanKM(
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+
+long PVRSRV_BridgeDispatchKM(struct file *, unsigned, unsigned long);
+
+#endif
diff --git a/drivers/gpu/pvr/pvr_debug.c b/drivers/gpu/pvr/pvr_debug.c
new file mode 100644
index 00000000000..0ac1322a700
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_debug.c
@@ -0,0 +1,358 @@
+/**********************************************************************
+ *
+ * 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 <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/hardirq.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/tty.h>
+#include <linux/debugfs.h>
+#include <stdarg.h>
+#include "img_types.h"
+#include "servicesext.h"
+#include "pvr_debug.h"
+#include "proc.h"
+#include "syscommon.h"
+#include "sgxinfokm.h"
+#include "sgxutils.h"
+#include "pvr_bridge_km.h"
+
+u32 gPVRDebugLevel = DBGPRIV_WARNING;
+
+#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+
+static char gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+
+static char gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+static struct mutex gsDebugMutexNonIRQ;
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
+#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
+static inline void GetBufferLock(unsigned long *pulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
+ else
+ mutex_lock(&gsDebugMutexNonIRQ);
+}
+
+static inline void ReleaseBufferLock(unsigned long ulLockFlags)
+{
+ if (USE_SPIN_LOCK)
+ spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
+ else
+ mutex_unlock(&gsDebugMutexNonIRQ);
+}
+
+static inline void SelectBuffer(char **ppszBuf, u32 *pui32BufSiz)
+{
+ if (USE_SPIN_LOCK) {
+ *ppszBuf = gszBufferIRQ;
+ *pui32BufSiz = sizeof(gszBufferIRQ);
+ } else {
+ *ppszBuf = gszBufferNonIRQ;
+ *pui32BufSiz = sizeof(gszBufferNonIRQ);
+ }
+}
+
+static IMG_BOOL VBAppend(char *pszBuf, u32 ui32BufSiz, const char *pszFormat,
+ va_list VArgs)
+{
+ u32 ui32Used;
+ u32 ui32Space;
+ s32 i32Len;
+ ui32Used = strlen(pszBuf);
+ BUG_ON(ui32Used >= ui32BufSiz);
+ ui32Space = ui32BufSiz - ui32Used;
+ i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
+ pszBuf[ui32BufSiz - 1] = 0;
+ return i32Len < 0 || i32Len >= ui32Space;
+}
+
+static IMG_BOOL BAppend(char *pszBuf, u32 ui32BufSiz, const char *pszFormat,
+ ...)
+{
+ va_list VArgs;
+ IMG_BOOL bTrunc;
+
+ va_start(VArgs, pszFormat);
+
+ bTrunc = VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs);
+
+ va_end(VArgs);
+
+ return bTrunc;
+}
+
+void PVRSRVDebugPrintf(u32 ui32DebugLevel,
+ const char *pszFileName,
+ u32 ui32Line, const char *pszFormat, ...)
+{
+ IMG_BOOL bTrace, bDebug;
+ char *pszLeafName;
+
+ pszLeafName = (char *)strrchr(pszFileName, '\\');
+
+ if (pszLeafName)
+ pszFileName = pszLeafName;
+
+ bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+ bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+ if (bTrace || bDebug) {
+ va_list vaArgs;
+ unsigned long ulLockFlags = 0; /* suppress gc warning */
+ char *pszBuf;
+ u32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+ va_start(vaArgs, pszFormat);
+
+ GetBufferLock(&ulLockFlags);
+
+ if (bDebug) {
+ switch (ui32DebugLevel) {
+ case DBGPRIV_FATAL:
+ strncpy(pszBuf, "PVR_K:(Fatal): ",
+ (ui32BufSiz - 1));
+ break;
+ case DBGPRIV_ERROR:
+ strncpy(pszBuf, "PVR_K:(Error): ",
+ (ui32BufSiz - 1));
+ break;
+ case DBGPRIV_WARNING:
+ strncpy(pszBuf, "PVR_K:(Warning): ",
+ (ui32BufSiz - 1));
+ break;
+ case DBGPRIV_MESSAGE:
+ strncpy(pszBuf, "PVR_K:(Message): ",
+ (ui32BufSiz - 1));
+ break;
+ case DBGPRIV_VERBOSE:
+ strncpy(pszBuf, "PVR_K:(Verbose): ",
+ (ui32BufSiz - 1));
+ break;
+ default:
+ strncpy(pszBuf,
+ "PVR_K:(Unknown message level)",
+ (ui32BufSiz - 1));
+ break;
+ }
+ } else {
+ strncpy(pszBuf, "PVR_K: ", (ui32BufSiz - 1));
+ }
+
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, vaArgs)) {
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n",
+ pszBuf);
+ } else {
+ if (!bTrace) {
+ if (BAppend
+ (pszBuf, ui32BufSiz, " [%lu, %s]", ui32Line,
+ pszFileName))
+ printk(KERN_INFO
+ "PVR_K:(Message Truncated): %s\n",
+ pszBuf);
+ else
+ printk(KERN_INFO "%s\n", pszBuf);
+ }
+ }
+
+ ReleaseBufferLock(ulLockFlags);
+ va_end(vaArgs);
+ }
+}
+
+void PVRSRVDebugAssertFail(const char *pszFile, u32 uLine)
+{
+ PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine,
+ "Debug assertion failed!");
+ BUG();
+}
+
+void PVRSRVTrace(const char *pszFormat, ...)
+{
+ va_list VArgs;
+ unsigned long ulLockFlags = 0; /* suppress gcc warning */
+ char *pszBuf;
+ u32 ui32BufSiz;
+
+ SelectBuffer(&pszBuf, &ui32BufSiz);
+
+ va_start(VArgs, pszFormat);
+ GetBufferLock(&ulLockFlags);
+ strncpy(pszBuf, "PVR: ", (ui32BufSiz - 1));
+ if (VBAppend(pszBuf, ui32BufSiz, pszFormat, VArgs))
+ printk(KERN_INFO "PVR_K:(Message Truncated): %s\n", pszBuf);
+ else
+ printk(KERN_INFO "%s\n", pszBuf);
+ ReleaseBufferLock(ulLockFlags);
+ va_end(VArgs);
+}
+
+void PVRDebugSetLevel(u32 uDebugLevel)
+{
+ printk(KERN_INFO "PVR: Setting Debug Level = 0x%x\n",
+ (unsigned)uDebugLevel);
+
+ gPVRDebugLevel = uDebugLevel;
+}
+
+int PVRDebugProcSetLevel(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+#define _PROC_SET_BUFFER_SZ 2
+ char data_buffer[_PROC_SET_BUFFER_SZ];
+
+ if (count != _PROC_SET_BUFFER_SZ) {
+ return -EINVAL;
+ } else {
+ if (copy_from_user(data_buffer, buffer, count))
+ return -EINVAL;
+ if (data_buffer[count - 1] != '\n')
+ return -EINVAL;
+ PVRDebugSetLevel(data_buffer[0] - '0');
+ }
+ return count;
+}
+
+int PVRDebugProcGetLevel(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ if (off == 0) {
+ *start = (char *)1;
+ return printAppend(page, count, 0, "%u\n", gPVRDebugLevel);
+ }
+ *eof = 1;
+ return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static struct dentry *debugfs_dentry;
+static u32 pvr_reset;
+
+static struct PVRSRV_DEVICE_NODE *get_sgx_node(void)
+{
+ struct SYS_DATA *sysdata;
+ struct PVRSRV_DEVICE_NODE *node;
+
+ if (SysAcquireData(&sysdata) != PVRSRV_OK)
+ return NULL;
+
+ for (node = sysdata->psDeviceNodeList; node; node = node->psNext)
+ if (node->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_SGX)
+ break;
+
+ return node;
+}
+
+static int pvr_dbg_reset(void *data, u64 val)
+{
+ struct PVRSRV_DEVICE_NODE *node;
+ enum PVRSRV_ERROR err;
+ int r = 0;
+
+ if (val != 1)
+ return 0;
+
+ pvr_lock();
+
+ if (pvr_is_disabled()) {
+ r = -ENODEV;
+ goto exit;
+ }
+
+ node = get_sgx_node();
+ if (!node) {
+ r = -ENODEV;
+ goto exit;
+ }
+
+ err = PVRSRVSetDevicePowerStateKM(node->sDevId.ui32DeviceIndex,
+ PVRSRV_POWER_STATE_D0);
+ if (err != PVRSRV_OK) {
+ r = -EIO;
+ goto exit;
+ }
+
+ HWRecoveryResetSGX(node);
+
+ SGXTestActivePowerEvent(node);
+exit:
+ pvr_unlock();
+
+ return r;
+}
+
+static int pvr_dbg_set(void *data, u64 val)
+{
+ u32 *var = data;
+
+ if (var == &pvr_reset)
+ return pvr_dbg_reset(data, val);
+
+ BUG();
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pvr_dbg_fops, NULL, pvr_dbg_set, "%llu\n");
+
+static int pvr_init_debugfs(void)
+{
+ debugfs_dentry = debugfs_create_file("reset_sgx", S_IWUGO, NULL,
+ &pvr_reset, &pvr_dbg_fops);
+
+ return debugfs_dentry ? 0 : -ENODEV;
+}
+
+static void pvr_cleanup_debugfs(void)
+{
+ debugfs_remove(debugfs_dentry);
+}
+
+#else /* !CONFIG_DEBUG_FS */
+
+static int pvr_init_debugfs(void)
+{
+ return 0;
+}
+
+static void pvr_cleanup_debugfs(void) { }
+
+#endif
+
+void pvr_dbg_init(void)
+{
+ mutex_init(&gsDebugMutexNonIRQ);
+ pvr_init_debugfs();
+}
+
+void pvr_dbg_cleanup(void)
+{
+ pvr_cleanup_debugfs();
+}
+
diff --git a/drivers/gpu/pvr/pvr_debug.h b/drivers/gpu/pvr/pvr_debug.h
new file mode 100644
index 00000000000..c8c7e75b9b1
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_debug.h
@@ -0,0 +1,110 @@
+/**********************************************************************
+ *
+ * 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 __PVR_DEBUG_H__
+#define __PVR_DEBUG_H__
+
+#include <linux/fs.h>
+
+#include "img_types.h"
+
+#define PVR_MAX_DEBUG_MESSAGE_LEN 512
+
+#define DBGPRIV_FATAL 0x01UL
+#define DBGPRIV_ERROR 0x02UL
+#define DBGPRIV_WARNING 0x04UL
+#define DBGPRIV_MESSAGE 0x08UL
+#define DBGPRIV_VERBOSE 0x10UL
+#define DBGPRIV_CALLTRACE 0x20UL
+#define DBGPRIV_ALLOC 0x40UL
+#define DBGPRIV_ALLLEVELS (DBGPRIV_FATAL | DBGPRIV_ERROR | \
+ DBGPRIV_WARNING | DBGPRIV_MESSAGE | \
+ DBGPRIV_VERBOSE)
+
+#define PVR_DBG_FATAL DBGPRIV_FATAL
+#define PVR_DBG_ERROR DBGPRIV_ERROR
+#define PVR_DBG_WARNING DBGPRIV_WARNING
+#define PVR_DBG_MESSAGE DBGPRIV_MESSAGE
+#define PVR_DBG_VERBOSE DBGPRIV_VERBOSE
+#define PVR_DBG_CALLTRACE DBGPRIV_CALLTRACE
+#define PVR_DBG_ALLOC DBGPRIV_ALLOC
+
+#if defined(CONFIG_PVR_DEBUG)
+
+#define PVR_ASSERT(EXPR) \
+ do { \
+ if (!(EXPR)) \
+ PVRSRVDebugAssertFail(__FILE__, __LINE__); \
+ } while (0)
+
+#define PVR_DPF(level, fmt, ...) \
+ PVRSRVDebugPrintf(level, __FILE__, __LINE__, fmt, ## __VA_ARGS__)
+
+#define PVR_TRACE(fmt, ...) \
+ PVRSRVTrace(fmt, ##__VA_ARGS__)
+
+void PVRSRVDebugAssertFail(const char *pszFile, u32 ui32Line);
+void PVRSRVDebugPrintf(u32 ui32DebugLevel, const char *pszFileName,
+ u32 ui32Line, const char *pszFormat, ...);
+void PVRSRVTrace(const char *pszFormat, ...);
+
+int PVRDebugProcSetLevel(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+int PVRDebugProcGetLevel(char *page, char **start, off_t off, int count,
+ int *eof, void *data);
+void PVRDebugSetLevel(u32 uDebugLevel);
+
+void pvr_dbg_init(void);
+void pvr_dbg_cleanup(void);
+
+#define PVR_DBG_BREAK
+
+#else
+
+#if defined(TIMING)
+
+#define PVR_ASSERT(EXPR) do { } while (0)
+#define PVR_DPF(level, fmt, ...) do { } while (0)
+#define PVR_TRACE(fmt, ...) \
+ PVRSRVTrace(fmt, ##__VA_ARGS__)
+#define PVR_DBG_BREAK do { } while (0)
+
+void PVRSRVTrace(const char *pszFormat, ...);
+
+#else
+
+#define PVR_ASSERT(EXPR) do { } while (0)
+#define PVR_DPF(level, fmt, ...) do { } while (0)
+#define PVR_TRACE(fmt, ...) do { } while (0)
+#define PVR_DBG_BREAK do { } while (0)
+
+static inline void pvr_dbg_init(void) {};
+static inline void pvr_dbg_cleanup(void) {};
+
+#endif
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/pvr_events.c b/drivers/gpu/pvr/pvr_events.c
new file mode 100644
index 00000000000..616fa0aeacb
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_events.c
@@ -0,0 +1,303 @@
+
+#include "pvr_events.h"
+#include "servicesint.h"
+#include "sgx_bridge.h"
+
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+
+#include <video/omapdss.h>
+
+static spinlock_t event_lock;
+static struct list_head sync_wait_list;
+static struct list_head flip_wait_list;
+static struct notifier_block dss_nb;
+
+static inline bool is_render_complete(const struct PVRSRV_SYNC_DATA *sync,
+ u32 write_ops_pending)
+{
+ return (int)sync->ui32WriteOpsComplete - (int)write_ops_pending >= 0;
+}
+
+static void pvr_signal_sync_event(struct pvr_pending_sync_event *e,
+ const struct timeval *now)
+{
+ e->event.tv_sec = now->tv_sec;
+ e->event.tv_usec = now->tv_usec;
+
+ list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+}
+
+int pvr_sync_event_req(struct PVRSRV_FILE_PRIVATE_DATA *priv,
+ const struct PVRSRV_KERNEL_SYNC_INFO *sync_info,
+ u64 user_data)
+{
+ struct pvr_pending_sync_event *e;
+ struct timeval now;
+ unsigned long flags;
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (e == NULL)
+ return -ENOMEM;
+
+ e->event.base.type = PVR_EVENT_SYNC;
+ e->event.base.length = sizeof(e->event);
+ e->event.sync_info = sync_info;
+ e->event.user_data = user_data;
+ e->base.event = &e->event.base;
+ e->base.file_priv = priv;
+ e->base.destroy = (void (*)(struct pvr_pending_event *))kfree;
+ e->base.write_ops_pending = sync_info->psSyncData->ui32WriteOpsPending;
+
+ do_gettimeofday(&now);
+ spin_lock_irqsave(&event_lock, flags);
+
+ if (priv->event_space < sizeof(e->event)) {
+ spin_unlock_irqrestore(&event_lock, flags);
+ kfree(e);
+ return -ENOMEM;
+ }
+
+ priv->event_space -= sizeof(e->event);
+
+ list_add_tail(&e->base.link, &sync_wait_list);
+ if (is_render_complete(sync_info->psSyncData,
+ e->base.write_ops_pending))
+ pvr_signal_sync_event(e, &now);
+
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return 0;
+}
+
+static void pvr_signal_flip_event(struct pvr_pending_flip_event *e,
+ const struct timeval *now)
+{
+ e->event.tv_sec = now->tv_sec;
+ e->event.tv_usec = now->tv_usec;
+
+ list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+
+ wake_up_interruptible(&e->base.file_priv->event_wait);
+}
+
+int pvr_flip_event_req(struct PVRSRV_FILE_PRIVATE_DATA *priv,
+ unsigned int overlay,
+ enum pvr_sync_wait_seq_type type, u64 user_data)
+{
+ struct pvr_pending_flip_event *e;
+ struct timeval now;
+ unsigned long flags;
+
+ e = kzalloc(sizeof(*e), GFP_KERNEL);
+ if (e == NULL)
+ return -ENOMEM;
+
+ switch (type) {
+ case _PVR_SYNC_WAIT_FLIP:
+ e->event.base.type = PVR_EVENT_FLIP;
+ e->dss_event = OMAP_DSS_NOTIFY_GO_OVL;
+ break;
+ case _PVR_SYNC_WAIT_UPDATE:
+ e->event.base.type = PVR_EVENT_UPDATE;
+ e->dss_event = OMAP_DSS_NOTIFY_UPDATE_OVL;
+ break;
+ default:
+ BUG();
+ }
+ e->event.base.length = sizeof(e->event);
+ e->base.event = &e->event.base;
+ e->event.overlay = overlay;
+ e->event.user_data = user_data;
+ e->base.file_priv = priv;
+ e->base.destroy = (void (*)(struct pvr_pending_event *))kfree;
+
+ do_gettimeofday(&now);
+ spin_lock_irqsave(&event_lock, flags);
+
+ if (priv->event_space < sizeof(e->event)) {
+ spin_unlock_irqrestore(&event_lock, flags);
+ kfree(e);
+ return -ENOMEM;
+ }
+
+ priv->event_space -= sizeof(e->event);
+
+ list_add_tail(&e->base.link, &flip_wait_list);
+
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return omap_dss_request_notify(e->dss_event, overlay);
+}
+
+static bool pvr_dequeue_event(struct PVRSRV_FILE_PRIVATE_DATA *priv,
+ size_t total, size_t max, struct pvr_pending_event **out)
+{
+ struct pvr_pending_event *e;
+ unsigned long flags;
+ bool ret = false;
+
+ spin_lock_irqsave(&event_lock, flags);
+
+ *out = NULL;
+ if (list_empty(&priv->event_list))
+ goto err;
+
+ e = list_first_entry(&priv->event_list, struct pvr_pending_event, link);
+ if (e->event->length + total > max)
+ goto err;
+
+ priv->event_space += e->event->length;
+ list_del(&e->link);
+ *out = e;
+ ret = true;
+
+err:
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return ret;
+}
+
+ssize_t pvr_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
+{
+ struct PVRSRV_FILE_PRIVATE_DATA *priv = filp->private_data;
+ struct pvr_pending_event *e;
+ size_t total;
+ ssize_t ret;
+
+ ret = wait_event_interruptible(priv->event_wait,
+ !list_empty(&priv->event_list));
+
+ if (ret < 0)
+ return ret;
+
+ total = 0;
+ while (pvr_dequeue_event(priv, total, count, &e)) {
+ if (copy_to_user(buf + total, e->event, e->event->length)) {
+ total = -EFAULT;
+ break;
+ }
+
+ total += e->event->length;
+ e->destroy(e);
+ }
+
+ return total;
+}
+
+unsigned int pvr_poll(struct file *filp, struct poll_table_struct *wait)
+{
+ struct PVRSRV_FILE_PRIVATE_DATA *priv = filp->private_data;
+ unsigned int mask = 0;
+
+ poll_wait(filp, &priv->event_wait, wait);
+
+ if (!list_empty(&priv->event_list))
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
+void pvr_handle_sync_events(void)
+{
+ struct pvr_pending_sync_event *e;
+ struct pvr_pending_sync_event *t;
+ struct timeval now;
+ unsigned long flags;
+
+ do_gettimeofday(&now);
+
+ spin_lock_irqsave(&event_lock, flags);
+
+ list_for_each_entry_safe(e, t, &sync_wait_list, base.link) {
+ if (!is_render_complete(e->event.sync_info->psSyncData,
+ e->base.write_ops_pending))
+ continue;
+
+ pvr_signal_sync_event(e, &now);
+ }
+
+ spin_unlock_irqrestore(&event_lock, flags);
+}
+
+static int dss_notifier_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct pvr_pending_flip_event *e;
+ struct pvr_pending_flip_event *t;
+ struct timeval now;
+ unsigned long flags;
+ long overlay = (long) data;
+
+ do_gettimeofday(&now);
+
+ spin_lock_irqsave(&event_lock, flags);
+
+ list_for_each_entry_safe(e, t, &flip_wait_list, base.link) {
+ if (!(e->dss_event & event))
+ continue;
+ if (e->event.overlay != overlay)
+ continue;
+
+ pvr_signal_flip_event(e, &now);
+ }
+
+ spin_unlock_irqrestore(&event_lock, flags);
+
+ return 0;
+}
+
+void pvr_release_events(struct PVRSRV_FILE_PRIVATE_DATA *priv)
+{
+ struct pvr_pending_event *w;
+ struct pvr_pending_event *z;
+ struct pvr_pending_sync_event *e;
+ struct pvr_pending_sync_event *t;
+ struct pvr_pending_flip_event *e2;
+ struct pvr_pending_flip_event *t2;
+ unsigned long flags;
+
+ spin_lock_irqsave(&event_lock, flags);
+
+ /* Remove pending waits */
+ list_for_each_entry_safe(e, t, &sync_wait_list, base.link)
+ if (e->base.file_priv == priv) {
+ list_del(&e->base.link);
+ e->base.destroy(&e->base);
+ }
+
+ list_for_each_entry_safe(e2, t2, &flip_wait_list, base.link)
+ if (e2->base.file_priv == priv) {
+ list_del(&e2->base.link);
+ e2->base.destroy(&e2->base);
+ }
+
+ /* Remove unconsumed events */
+ list_for_each_entry_safe(w, z, &priv->event_list, link)
+ w->destroy(w);
+
+ spin_unlock_irqrestore(&event_lock, flags);
+}
+
+void pvr_init_events(void)
+{
+ spin_lock_init(&event_lock);
+ INIT_LIST_HEAD(&sync_wait_list);
+ INIT_LIST_HEAD(&flip_wait_list);
+
+ dss_nb.notifier_call = dss_notifier_callback;
+ omap_dss_register_notifier(&dss_nb);
+}
+
+void pvr_exit_events(void)
+{
+ omap_dss_unregister_notifier(&dss_nb);
+}
diff --git a/drivers/gpu/pvr/pvr_events.h b/drivers/gpu/pvr/pvr_events.h
new file mode 100644
index 00000000000..11cfc119d28
--- /dev/null
+++ b/drivers/gpu/pvr/pvr_events.h
@@ -0,0 +1,99 @@
+
+#ifndef PVR_EVENTS_H
+#define PVR_EVENTS_H
+
+#include "servicesext.h"
+#include "private_data.h"
+#include <linux/list.h>
+#include <linux/file.h>
+#include <linux/poll.h>
+
+/*
+ * Header for events written back to userspace on the drm fd. The
+ * type defines the type of event, the length specifies the total
+ * length of the event (including the header), and user_data is
+ * typically a 64 bit value passed with the ioctl that triggered the
+ * event. A read on the drm fd will always only return complete
+ * events, that is, if for example the read buffer is 100 bytes, and
+ * there are two 64 byte events pending, only one will be returned.
+ */
+struct pvr_event {
+ __u32 type;
+ __u32 length;
+};
+
+#define PVR_EVENT_SYNC 0x01
+#define PVR_EVENT_FLIP 0x02
+#define PVR_EVENT_UPDATE 0x03 /* also uses struct pvr_event_flip */
+
+/*
+ * Every buffer used as a render target has a 'PVRSRV_KERNEL_SYNC_INFO'
+ * associated with it. This structure simply contains four counters, number of
+ * pending and completed read and write operations. Counters for pending
+ * operations are modified (incremented) by the kernel driver while the
+ * counters for completed operations are directly updated by the SGX micro
+ * kernel. Once both the read counters and the write counters mutually match,
+ * one has completed a full frame.
+ *
+ * Micro kernel issues interrupts whenever TA or 3D phases are completed. These
+ * interrupts, however, as such do not tell if any particular frame is
+ * completed. It is the responsibility of the kerner driver to determine this.
+ * Hence the core interrupt handler calls 'pvr_handle_sync_events' to check if
+ * one of the monitored render operations are finished. This is accomplished by
+ * examining the before-mentioned counters designated by the pending events.
+ */
+struct pvr_event_sync {
+ struct pvr_event base;
+ const struct PVRSRV_KERNEL_SYNC_INFO *sync_info;
+ __u64 user_data;
+ __u32 tv_sec;
+ __u32 tv_usec;
+};
+
+struct pvr_event_flip {
+ struct pvr_event base;
+ __u64 user_data;
+ __u32 tv_sec;
+ __u32 tv_usec;
+ __u32 overlay;
+};
+
+/* Event queued up for userspace to read */
+struct pvr_pending_event {
+ struct pvr_event *event;
+ struct list_head link;
+ struct PVRSRV_FILE_PRIVATE_DATA *file_priv;
+ void (*destroy)(struct pvr_pending_event *event);
+ u32 write_ops_pending;
+};
+
+struct pvr_pending_sync_event {
+ struct pvr_pending_event base;
+ struct pvr_event_sync event;
+};
+
+struct pvr_pending_flip_event {
+ struct pvr_pending_event base;
+ struct pvr_event_flip event;
+ unsigned int dss_event;
+};
+
+enum pvr_sync_wait_seq_type;
+
+void pvr_init_events(void);
+void pvr_exit_events(void);
+
+int pvr_sync_event_req(struct PVRSRV_FILE_PRIVATE_DATA *priv,
+ const struct PVRSRV_KERNEL_SYNC_INFO *sync_info,
+ u64 user_data);
+int pvr_flip_event_req(struct PVRSRV_FILE_PRIVATE_DATA *priv,
+ unsigned int overlay,
+ enum pvr_sync_wait_seq_type type, u64 user_data);
+ssize_t pvr_read(struct file *filp, char __user *buf, size_t count,
+ loff_t *off);
+unsigned int pvr_poll(struct file *filp, struct poll_table_struct *wait);
+void pvr_release_events(struct PVRSRV_FILE_PRIVATE_DATA *priv);
+
+void pvr_handle_sync_events(void);
+
+#endif /* PVR_EVENTS_H */
diff --git a/drivers/gpu/pvr/pvrconfig.h b/drivers/gpu/pvr/pvrconfig.h
new file mode 100644
index 00000000000..5f16f2faa47
--- /dev/null
+++ b/drivers/gpu/pvr/pvrconfig.h
@@ -0,0 +1,35 @@
+#ifndef _PVRCONFIG_H
+#define _PVRCONFIG_H
+
+#define SGX530 1
+
+#ifdef CONFIG_PVR_DEBUG
+# define PVR_BUILD_TYPE "debug"
+# define DEBUG 1
+#elif defined(CONFIG_PVR_TIMING)
+# define PVR_BUILD_TYPE "timing"
+# define TIMING 1
+#elif defined(CONFIG_PVR_RELEASE)
+# define PVR_BUILD_TYPE "release"
+#endif
+
+#ifdef CONFIG_PVR_NO_HARDWARE
+# define NO_HARDWARE 1
+#endif
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+# define DEBUG_LINUX_MEMORY_ALLOCATIONS 1
+# define DEBUG_LINUX_MEM_AREAS 1
+# define DEBUG_LINUX_MMAP_AREAS 1
+# define DEBUG_BRIDGE_KM 1
+#endif
+
+# if (defined CONFIG_PVR_DEBUG_PDUMP) || (defined CONFIG_PVR_DEBUG_PDUMP_MODULE)
+# define PDUMP 1
+# endif
+
+#ifdef CONFIG_PVR_EDM_DEBUG
+# define PVRSRV_USSE_EDM_STATUS_DEBUG 1
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/pvrmmap.h b/drivers/gpu/pvr/pvrmmap.h
new file mode 100644
index 00000000000..c84e4d89eff
--- /dev/null
+++ b/drivers/gpu/pvr/pvrmmap.h
@@ -0,0 +1,36 @@
+/**********************************************************************
+ *
+ * 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 __PVRMMAP_H__
+#define __PVRMMAP_H__
+
+enum PVRSRV_ERROR PVRPMapKMem(void *hModule, void **ppvLinAddr,
+ void *pvLinAddrKM, void **phMappingInfo,
+ void *hMHandle);
+
+IMG_BOOL PVRUnMapKMem(void *hModule, void *hMappingInfo, void *hMHandle);
+
+#endif
diff --git a/drivers/gpu/pvr/pvrmodule.h b/drivers/gpu/pvr/pvrmodule.h
new file mode 100644
index 00000000000..5f77d1c1fde
--- /dev/null
+++ b/drivers/gpu/pvr/pvrmodule.h
@@ -0,0 +1,31 @@
+/**********************************************************************
+ *
+ * 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 _PVRMODULE_H_
+#define _PVRMODULE_H_
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/gpu/pvr/pvrsrv.c b/drivers/gpu/pvr/pvrsrv.c
new file mode 100644
index 00000000000..332e0003160
--- /dev/null
+++ b/drivers/gpu/pvr/pvrsrv.c
@@ -0,0 +1,921 @@
+/**********************************************************************
+ *
+ * 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 <linux/io.h>
+
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "pvr_bridge_km.h"
+#include "handle.h"
+#include "perproc.h"
+#include "pdump_km.h"
+#include "ra.h"
+#include "pvr_events.h"
+
+#include "pvrversion.h"
+
+#define HASH_TAB_INIT_SIZE 32
+enum PVRSRV_ERROR AllocateDeviceID(struct SYS_DATA *psSysData, u32 *pui32DevID)
+{
+ struct SYS_DEVICE_ID *psDeviceWalker;
+ struct SYS_DEVICE_ID *psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+ while (psDeviceWalker < psDeviceEnd) {
+ if (!psDeviceWalker->bInUse) {
+ psDeviceWalker->bInUse = IMG_TRUE;
+ *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;
+}
+
+enum PVRSRV_ERROR FreeDeviceID(struct SYS_DATA *psSysData, u32 ui32DevID)
+{
+ struct SYS_DEVICE_ID *psDeviceWalker;
+ struct SYS_DEVICE_ID *psDeviceEnd;
+
+ psDeviceWalker = &psSysData->sDeviceID[0];
+ psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
+
+ while (psDeviceWalker < psDeviceEnd) {
+ if ((psDeviceWalker->uiID == ui32DevID) &&
+ (psDeviceWalker->bInUse)) {
+ psDeviceWalker->bInUse = IMG_FALSE;
+ 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;
+}
+
+enum PVRSRV_ERROR PVRSRVEnumerateDevicesKM(u32 *pui32NumDevices,
+ struct PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ u32 i;
+
+ if (!pui32NumDevices || !psDevIdList) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVEnumerateDevicesKM: Invalid params");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVEnumerateDevicesKM: Failed to get SysData");
+ return eError;
+ }
+
+ for (i = 0; i < PVRSRV_MAX_DEVICES; i++)
+ psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
+
+ *pui32NumDevices = 0;
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ for (i = 0; psDeviceNode != NULL; i++) {
+ if (psDeviceNode->sDevId.eDeviceType !=
+ PVRSRV_DEVICE_TYPE_EXT) {
+ *psDevIdList++ = psDeviceNode->sDevId;
+ (*pui32NumDevices)++;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVInit(struct SYS_DATA *psSysData)
+{
+ enum 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;
+
+ psSysData->eCurrentPowerState = PVRSRV_POWER_STATE_D0;
+ psSysData->eFailedPowerState = PVRSRV_POWER_Unspecified;
+
+#if defined(PDUMP)
+ psSysData->bPowerUpPDumped = IMG_FALSE;
+#endif
+
+ if (OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(struct PVRSRV_EVENTOBJECT),
+ (void **) &psSysData->psGlobalEventObject,
+ NULL) != PVRSRV_OK)
+
+ goto Error;
+
+ if (OSEventObjectCreate("PVRSRV_GLOBAL_EVENTOBJECT",
+ psSysData->psGlobalEventObject) != PVRSRV_OK)
+ goto Error;
+
+ return eError;
+
+Error:
+ PVRSRVDeInit(psSysData);
+ return eError;
+}
+
+void PVRSRVDeInit(struct SYS_DATA *psSysData)
+{
+ enum PVRSRV_ERROR eError;
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ 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(struct PVRSRV_EVENTOBJECT),
+ 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();
+}
+
+enum PVRSRV_ERROR PVRSRVRegisterDevice(struct SYS_DATA *psSysData,
+ enum PVRSRV_ERROR(*pfnRegisterDevice)
+ (struct PVRSRV_DEVICE_NODE *),
+ u32 ui32SOCInterruptBit,
+ u32 *pui32DeviceIndex)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DEVICE_NODE),
+ (void **) &psDeviceNode, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterDevice : "
+ "Failed to alloc memory for psDeviceNode");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDeviceNode, 0, sizeof(struct PVRSRV_DEVICE_NODE));
+
+ eError = pfnRegisterDevice(psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct 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);
+
+ psDeviceNode->psNext = psSysData->psDeviceNodeList;
+ psSysData->psDeviceNodeList = psDeviceNode;
+
+ *pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVInitialiseDevice(u32 ui32DevIndex)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVInitialiseDevice");
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVInitialiseDevice: Failed to get SysData");
+ return eError;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+
+ while (psDeviceNode) {
+ if (psDeviceNode->sDevId.ui32DeviceIndex == ui32DevIndex)
+ goto FoundDevice;
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVInitialiseDevice: requested device is not present");
+ return PVRSRV_ERROR_INIT_FAILURE;
+
+FoundDevice:
+
+ 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;
+ }
+ }
+
+ psDeviceNode->sync_table = HASH_Create(HASH_TAB_INIT_SIZE);
+ if (psDeviceNode->sync_table == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: "
+ "Couldn't create syncobject hash table");
+ eError = PVRSRV_ERROR_GENERIC;
+ return eError;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVFinaliseSystem");
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVFinaliseSystem: Failed to get SysData");
+ return eError;
+ }
+
+ if (bInitSuccessful) {
+ eError = SysFinalise();
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVFinaliseSystem: SysFinalise failed (%d)",
+ eError);
+ return eError;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ eError =
+ PVRSRVSetDevicePowerStateKM(
+ psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_POWER_Unspecified);
+ if (eError != PVRSRV_OK)
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVFinaliseSystem: "
+ "Failed PVRSRVSetDevicePowerStateKM "
+ "call (device index: %d)",
+ psDeviceNode->sDevId.ui32DeviceIndex);
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ if (psDeviceNode->pfnInitDeviceCompatCheck) {
+ eError = PVRSRVDevInitCompatCheck(psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVFinaliseSystem: "
+ "Failed PVRSRVDevInitCompatCheck "
+ "call (device index: %d)",
+ psDeviceNode->sDevId.
+ ui32DeviceIndex);
+ return eError;
+ }
+ }
+ psDeviceNode = psDeviceNode->psNext;
+
+ }
+
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVDevInitCompatCheck(struct PVRSRV_DEVICE_NODE
+ *psDeviceNode)
+{
+
+ return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
+}
+
+enum PVRSRV_ERROR PVRSRVAcquireDeviceDataKM(u32 ui32DevIndex,
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void **phDevCookie)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "PVRSRVAcquireDeviceDataKM");
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVAcquireDeviceDataKM: Failed to get SysData");
+ return eError;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+
+ if (eDeviceType != PVRSRV_DEVICE_TYPE_UNKNOWN) {
+ while (psDeviceNode) {
+ if (psDeviceNode->sDevId.eDeviceType == eDeviceType)
+ goto FoundDevice;
+ psDeviceNode = psDeviceNode->psNext;
+ }
+ } else {
+ while (psDeviceNode) {
+ if (psDeviceNode->sDevId.ui32DeviceIndex ==
+ ui32DevIndex) {
+ goto FoundDevice;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVAcquireDeviceDataKM: requested device is not present");
+ return PVRSRV_ERROR_INIT_FAILURE;
+
+FoundDevice:
+
+ PVR_ASSERT(psDeviceNode->ui32RefCount > 0);
+
+ if (phDevCookie)
+ *phDevCookie = (void *) psDeviceNode;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVDeinitialiseDevice(u32 ui32DevIndex)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_DEVICE_NODE **ppsDevNode;
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVDeinitialiseDevice: Failed to get SysData");
+ return eError;
+ }
+
+ ppsDevNode = &psSysData->psDeviceNodeList;
+ while (*ppsDevNode) {
+ if ((*ppsDevNode)->sDevId.ui32DeviceIndex == ui32DevIndex) {
+ psDeviceNode = *ppsDevNode;
+ goto FoundDevice;
+ }
+ ppsDevNode = &((*ppsDevNode)->psNext);
+ }
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVDeinitialiseDevice: requested device %d is not present",
+ ui32DevIndex);
+
+ return PVRSRV_ERROR_GENERIC;
+
+FoundDevice:
+
+ eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
+ PVRSRV_POWER_STATE_D3);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVDeinitialiseDevice: "
+ "Failed PVRSRVSetDevicePowerStateKM call");
+ return eError;
+ }
+
+ HASH_Delete(psDeviceNode->sync_table);
+
+ ResManFreeResByCriteria(psDeviceNode->hResManContext,
+ RESMAN_CRITERIA_RESTYPE,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ NULL, 0);
+
+ 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, IMG_TRUE);
+ psDeviceNode->hResManContext = NULL;
+
+ *ppsDevNode = psDeviceNode->psNext;
+
+ FreeDeviceID(psSysData, ui32DevIndex);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_DEVICE_NODE), psDeviceNode, NULL);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PollForValueKM(u32 __iomem *pui32LinMemAddr,
+ u32 ui32Value, u32 ui32Mask, u32 ui32Waitus,
+ u32 ui32Tries)
+{
+ u32 uiMaxTime;
+
+ uiMaxTime = ui32Tries * ui32Waitus;
+
+ LOOP_UNTIL_TIMEOUT(uiMaxTime) {
+ if ((readl(pui32LinMemAddr) & ui32Mask) == ui32Value)
+ return PVRSRV_OK;
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+
+enum PVRSRV_ERROR PVRSRVGetMiscInfoKM(struct PVRSRV_MISC_INFO *psMiscInfo)
+{
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+
+ 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)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVGetMiscInfoKM: invalid state request flags");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVGetMiscInfoKM: Failed to get SysData");
+ return eError;
+ }
+
+ 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)) {
+ struct RA_ARENA **ppArena;
+ struct BM_HEAP *psBMHeap;
+ struct BM_CONTEXT *psBMContext;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ 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 =
+ OSSNPrintf(pszStr, 100, "\nLocal Backing Store:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ RA_GetStats(*ppArena, &pszStr, &ui32StrLen);
+
+ ppArena++;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ CHECK_SPACE(ui32StrLen);
+ i32Count =
+ OSSNPrintf(pszStr, 100, "\n\nDevice Type %d:\n",
+ psDeviceNode->sDevId.eDeviceType);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ if (psDeviceNode->sDevMemoryInfo.pBMKernelContext) {
+ CHECK_SPACE(ui32StrLen);
+ i32Count =
+ OSSNPrintf(pszStr, 100,
+ "\nKernel Context:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ psBMHeap =
+ psDeviceNode->sDevMemoryInfo.
+ pBMKernelContext->psBMHeap;
+ while (psBMHeap) {
+ if (psBMHeap->pImportArena) {
+ RA_GetStats(psBMHeap->
+ pImportArena,
+ &pszStr,
+ &ui32StrLen);
+ }
+
+ if (psBMHeap->pVMArena) {
+ RA_GetStats(psBMHeap->pVMArena,
+ &pszStr,
+ &ui32StrLen);
+ }
+ psBMHeap = psBMHeap->psNext;
+ }
+ }
+
+ psBMContext = psDeviceNode->sDevMemoryInfo.pBMContext;
+ while (psBMContext) {
+ CHECK_SPACE(ui32StrLen);
+ i32Count =
+ OSSNPrintf(pszStr, 100,
+ "\nApplication Context (hDevMemContext) 0x%08X:\n",
+ (void *)psBMContext);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ psBMHeap = psBMContext->psBMHeap;
+ while (psBMHeap) {
+ if (psBMHeap->pImportArena) {
+ RA_GetStats(psBMHeap->
+ pImportArena,
+ &pszStr,
+ &ui32StrLen);
+ }
+
+ if (psBMHeap->pVMArena) {
+ RA_GetStats(psBMHeap->pVMArena,
+ &pszStr,
+ &ui32StrLen);
+ }
+ psBMHeap = psBMHeap->psNext;
+ }
+ psBMContext = psBMContext->psNext;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ i32Count = OSSNPrintf(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 = OSSNPrintf(pszStr, ui32LenStrPerNum, "%ld",
+ psMiscInfo->aui32DDKVersion[i]);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ if (i != 3) {
+ i32Count = OSSNPrintf(pszStr, 2, ".");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+enum 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) ==
+ IMG_TRUE) {
+ *pui32Total += ui32Total;
+ *pui32Available += ui32Available;
+
+ i++;
+ }
+
+ return PVRSRV_OK;
+}
+
+IMG_BOOL PVRSRVDeviceLISR(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct SYS_DATA *psSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ 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;
+}
+
+IMG_BOOL PVRSRVSystemLISR(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = pvSysData;
+ IMG_BOOL bStatus = IMG_FALSE;
+ u32 ui32InterruptSource;
+ u32 ui32ClearInterrupts = 0;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ if (!psSysData) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n");
+ goto out;
+ }
+
+ ui32InterruptSource = SysGetInterruptSource(psSysData, NULL);
+
+ if (ui32InterruptSource == 0)
+ goto out;
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode != NULL) {
+ if (psDeviceNode->pfnDeviceISR != NULL)
+ if (ui32InterruptSource & psDeviceNode->
+ ui32SOCInterruptBit) {
+ if ((*psDeviceNode->pfnDeviceISR)
+ (psDeviceNode->pvISRData))
+ bStatus = IMG_TRUE;
+
+ ui32ClearInterrupts |=
+ psDeviceNode->ui32SOCInterruptBit;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ SysClearInterrupts(psSysData, ui32ClearInterrupts);
+
+out:
+ return bStatus;
+}
+
+void PVRSRVMISR(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = pvSysData;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ if (!psSysData) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVMISR: Invalid params\n");
+ return;
+ }
+
+ pvr_lock();
+
+ if (pvr_is_disabled()) {
+ pvr_unlock();
+ return;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode != NULL) {
+ if (psDeviceNode->pfnDeviceMISR != NULL)
+ (*psDeviceNode->pfnDeviceMISR)(psDeviceNode->
+ pvISRData);
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ PVRSRVProcessQueues(IMG_FALSE);
+
+ if (psSysData->psGlobalEventObject) {
+ void *hOSEventKM =
+ psSysData->psGlobalEventObject->hOSEventKM;
+ if (hOSEventKM)
+ OSEventObjectSignal(hOSEventKM);
+ }
+
+ pvr_handle_sync_events();
+
+ pvr_unlock();
+}
+
+enum PVRSRV_ERROR PVRSRVProcessConnect(u32 ui32PID)
+{
+ return PVRSRVPerProcessDataConnect(ui32PID);
+}
+
+void PVRSRVProcessDisconnect(u32 ui32PID)
+{
+ PVRSRVPerProcessDataDisconnect(ui32PID);
+}
+
+enum PVRSRV_ERROR PVRSRVSaveRestoreLiveSegments(void *hArena, u8 *pbyBuffer,
+ u32 *puiBufSize, IMG_BOOL bSave)
+{
+ u32 uiBytesSaved = 0;
+ void *pvLocalMemCPUVAddr;
+ struct RA_SEGMENT_DETAILS sSegDetails;
+
+ if (hArena == NULL)
+ return PVRSRV_ERROR_INVALID_PARAMS;
+
+ sSegDetails.uiSize = 0;
+ sSegDetails.sCpuPhyAddr.uiAddr = 0;
+ sSegDetails.hSegment = NULL;
+
+ 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 = (void __force *)
+ 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) {
+ OSMemCopy(pbyBuffer, &sSegDetails.uiSize,
+ sizeof(sSegDetails.uiSize));
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pbyBuffer, pvLocalMemCPUVAddr,
+ sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ } else {
+ u32 uiSize;
+
+ OSMemCopy(&uiSize, pbyBuffer,
+ sizeof(sSegDetails.uiSize));
+
+ if (uiSize != sSegDetails.uiSize) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVSaveRestoreLiveSegments:"
+ " Segment size error");
+ } else {
+ pbyBuffer += sizeof(sSegDetails.uiSize);
+
+ OSMemCopy(pvLocalMemCPUVAddr, pbyBuffer,
+ sSegDetails.uiSize);
+ pbyBuffer += sSegDetails.uiSize;
+ }
+ }
+
+ uiBytesSaved +=
+ sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
+
+ OSUnMapPhysToLin((void __force __iomem *)
+ pvLocalMemCPUVAddr,
+ sSegDetails.uiSize,
+ PVRSRV_HAP_KERNEL_ONLY |
+ PVRSRV_HAP_UNCACHED, NULL);
+ }
+
+ if (pbyBuffer == NULL)
+ *puiBufSize = uiBytesSaved;
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/pvr/pvrversion.h b/drivers/gpu/pvr/pvrversion.h
new file mode 100644
index 00000000000..5dc477929fe
--- /dev/null
+++ b/drivers/gpu/pvr/pvrversion.h
@@ -0,0 +1,37 @@
+/**********************************************************************
+ *
+ * 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 _PVRVERSION_H_
+#define _PVRVERSION_H_
+
+#define PVRVERSION_MAJ 1
+#define PVRVERSION_MIN 4
+#define PVRVERSION_BRANCH 14
+#define PVRVERSION_BUILD 2514
+#define PVRVERSION_STRING "1.4.14.2514"
+#define PVRVERSION_FILE "eurasiacon.pj"
+
+#endif
diff --git a/drivers/gpu/pvr/queue.c b/drivers/gpu/pvr/queue.c
new file mode 100644
index 00000000000..b88b22fd6a2
--- /dev/null
+++ b/drivers/gpu/pvr/queue.c
@@ -0,0 +1,761 @@
+/**********************************************************************
+ *
+ * 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 "proc.h"
+
+static int QueuePrintCommands(struct PVRSRV_QUEUE_INFO *psQueue, char *buffer,
+ size_t size)
+{
+ off_t off = 0;
+ int cmds = 0;
+ u32 ui32ReadOffset = psQueue->ui32ReadOffset;
+ u32 ui32WriteOffset = psQueue->ui32WriteOffset;
+ struct PVRSRV_COMMAND *psCmd;
+
+ while (ui32ReadOffset != ui32WriteOffset) {
+ psCmd = (struct 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;
+}
+
+off_t QueuePrintQueues(char *buffer, size_t size, off_t off)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_QUEUE_INFO *psQueue;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return END_OF_FILE;
+
+ if (!off)
+ return printAppend(buffer, size, 0,
+ "Command Queues\nQueue CmdPtr "
+ "Pid Command Size DevInd DSC SSC #Data ...\n");
+
+ for (psQueue = psSysData->psQueueList; --off && psQueue;
+ psQueue = psQueue->psNextKM)
+ ;
+
+ return psQueue ?
+ QueuePrintCommands(psQueue, buffer, size) : END_OF_FILE;
+}
+
+#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)
+
+static u32 NearestPower2(u32 ui32Value)
+{
+ u32 ui32Temp, ui32Result = 1;
+
+ if (!ui32Value)
+ return 0;
+
+ ui32Temp = ui32Value - 1;
+ while (ui32Temp) {
+ ui32Result <<= 1;
+ ui32Temp >>= 1;
+ }
+
+ return ui32Result;
+}
+
+enum PVRSRV_ERROR PVRSRVCreateCommandQueueKM(u32 ui32QueueSize,
+ struct PVRSRV_QUEUE_INFO **ppsQueueInfo)
+{
+ struct PVRSRV_QUEUE_INFO *psQueueInfo;
+ u32 ui32Power2QueueSize = NearestPower2(ui32QueueSize);
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+ void *hMemBlock;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_QUEUE_INFO),
+ (void **) &psQueueInfo, &hMemBlock) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVCreateCommandQueueKM: "
+ "Failed to alloc queue struct");
+ goto ErrorExit;
+ }
+ OSMemSet(psQueueInfo, 0, sizeof(struct 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) != 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;
+
+ psQueueInfo->psNextKM = psSysData->psQueueList;
+ psSysData->psQueueList = psQueueInfo;
+
+ *ppsQueueInfo = psQueueInfo;
+
+ return PVRSRV_OK;
+
+ErrorExit:
+
+ if (psQueueInfo) {
+ if (psQueueInfo->pvLinQueueKM)
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_QUEUE_INFO),
+ psQueueInfo, psQueueInfo->hMemBlock[0]);
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+enum PVRSRV_ERROR PVRSRVDestroyCommandQueueKM(
+ struct PVRSRV_QUEUE_INFO *psQueueInfo)
+{
+ struct PVRSRV_QUEUE_INFO *psQueue;
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ psQueue = psSysData->psQueueList;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if (psQueueInfo->ui32ReadOffset ==
+ psQueueInfo->ui32WriteOffset) {
+ bTimeout = IMG_FALSE;
+ 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;
+ }
+
+ if (psQueue == psQueueInfo) {
+ psSysData->psQueueList = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM, psQueueInfo->hMemBlock[1]);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_QUEUE_INFO),
+ psQueueInfo, psQueueInfo->hMemBlock[0]);
+ } else {
+ while (psQueue) {
+ if (psQueue->psNextKM == psQueueInfo) {
+ psQueue->psNextKM = psQueueInfo->psNextKM;
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psQueueInfo->ui32QueueSize,
+ psQueueInfo->pvLinQueueKM,
+ psQueueInfo->hMemBlock[1]);
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_QUEUE_INFO),
+ psQueueInfo,
+ psQueueInfo->hMemBlock[0]);
+ break;
+ }
+ psQueue = psQueue->psNextKM;
+ }
+
+ if (!psQueue) {
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto ErrorExit;
+ }
+ }
+
+ErrorExit:
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVGetQueueSpaceKM(struct PVRSRV_QUEUE_INFO *psQueue,
+ u32 ui32ParamSize, void **ppvSpace)
+{
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+ 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 = IMG_FALSE;
+ break;
+ }
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout == IMG_TRUE) {
+ *ppvSpace = NULL;
+
+ return PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE;
+ } else {
+ *ppvSpace = (void *)(psQueue->ui32WriteOffset +
+ (u32)psQueue->pvLinQueueUM);
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVInsertCommandKM(struct PVRSRV_QUEUE_INFO *psQueue,
+ struct PVRSRV_COMMAND **ppsCommand,
+ u32 ui32DevIndex, u16 CommandType,
+ u32 ui32DstSyncCount,
+ struct PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ u32 ui32SrcSyncCount,
+ struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ u32 ui32DataByteSize)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_COMMAND *psCommand;
+ u32 ui32CommandSize;
+ u32 i;
+
+ ui32DataByteSize = (ui32DataByteSize + 3) & 0xFFFFFFFC;
+
+ ui32CommandSize = sizeof(struct PVRSRV_COMMAND) +
+ ((ui32DstSyncCount + ui32SrcSyncCount) *
+ sizeof(struct 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 =
+ (struct PVRSRV_SYNC_OBJECT *)(((u8 *) psCommand) +
+ sizeof(struct PVRSRV_COMMAND));
+
+ psCommand->psSrcSync =
+ (struct PVRSRV_SYNC_OBJECT *)(((u8 *) psCommand->psDstSync) +
+ (ui32DstSyncCount *
+ sizeof(struct PVRSRV_SYNC_OBJECT)));
+
+ psCommand->pvData =
+ (struct PVRSRV_SYNC_OBJECT *)(((u8 *) psCommand->psSrcSync) +
+ (ui32SrcSyncCount *
+ sizeof(struct 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], IMG_FALSE);
+ psCommand->psDstSync[i].ui32ReadOpsPending =
+ PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+ }
+
+ for (i = 0; i < ui32SrcSyncCount; i++) {
+ psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
+ psCommand->psSrcSync[i].ui32WriteOpsPending =
+ PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
+ psCommand->psSrcSync[i].ui32ReadOpsPending =
+ PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+ }
+
+ *ppsCommand = psCommand;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR PVRSRVSubmitCommandKM(struct PVRSRV_QUEUE_INFO *psQueue,
+ struct PVRSRV_COMMAND *psCommand)
+{
+
+ if (psCommand->ui32DstSyncCount > 0) {
+ psCommand->psDstSync = (struct PVRSRV_SYNC_OBJECT *)
+ (((u8 *)psQueue->pvLinQueueKM) +
+ psQueue->ui32WriteOffset +
+ sizeof(struct PVRSRV_COMMAND));
+ }
+
+ if (psCommand->ui32SrcSyncCount > 0) {
+ psCommand->psSrcSync = (struct PVRSRV_SYNC_OBJECT *)
+ (((u8 *)psQueue->pvLinQueueKM) +
+ psQueue->ui32WriteOffset +
+ sizeof(struct PVRSRV_COMMAND) +
+ (psCommand->ui32DstSyncCount *
+ sizeof(struct PVRSRV_SYNC_OBJECT)));
+ }
+
+ psCommand->pvData = (struct PVRSRV_SYNC_OBJECT *)
+ (((u8 *)psQueue->pvLinQueueKM) +
+ psQueue->ui32WriteOffset +
+ sizeof(struct PVRSRV_COMMAND) +
+ (psCommand->ui32DstSyncCount *
+ sizeof(struct PVRSRV_SYNC_OBJECT)) +
+ (psCommand->ui32SrcSyncCount *
+ sizeof(struct PVRSRV_SYNC_OBJECT)));
+
+ UPDATE_QUEUE_WOFF(psQueue, psCommand->ui32CmdSize);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR PVRSRVProcessCommand(struct SYS_DATA *psSysData,
+ struct PVRSRV_COMMAND *psCommand,
+ IMG_BOOL bFlush)
+{
+ struct PVRSRV_SYNC_OBJECT *psWalkerObj;
+ struct PVRSRV_SYNC_OBJECT *psEndObj;
+ u32 i;
+ struct COMMAND_COMPLETE_DATA *psCmdCompleteData;
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ u32 ui32WriteOpsComplete;
+ u32 ui32ReadOpsComplete;
+
+ psWalkerObj = psCommand->psDstSync;
+ psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
+ while (psWalkerObj < psEndObj) {
+ struct 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) {
+ struct 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 = IMG_TRUE;
+
+ psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
+ for (i = 0; i < psCommand->ui32DstSyncCount; i++)
+ psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
+
+ psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
+ for (i = 0; i < psCommand->ui32SrcSyncCount; i++)
+ psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
+
+ if (psSysData->ppfnCmdProcList[psCommand->ui32DevIndex]
+ [psCommand->CommandType]((void *)
+ psCmdCompleteData,
+ psCommand->ui32DataSize,
+ psCommand->pvData) == IMG_FALSE) {
+ psCmdCompleteData->bInUse = IMG_FALSE;
+ eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush)
+{
+ struct PVRSRV_QUEUE_INFO *psQueue;
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_COMMAND *psCommand;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ enum PVRSRV_ERROR eError;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ 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 = (struct 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);
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode != NULL) {
+ if (psDeviceNode->bReProcessDeviceCommandComplete &&
+ psDeviceNode->pfnDeviceCommandComplete != NULL) {
+ (*psDeviceNode->
+ pfnDeviceCommandComplete) (psDeviceNode);
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ return PVRSRV_OK;
+}
+
+void PVRSRVCommandCompleteKM(void *hCmdCookie, IMG_BOOL bScheduleMISR)
+{
+ u32 i;
+ struct COMMAND_COMPLETE_DATA *psCmdCompleteData =
+ (struct COMMAND_COMPLETE_DATA *)hCmdCookie;
+ struct SYS_DATA *psSysData;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return;
+
+ for (i = 0; i < psCmdCompleteData->ui32DstSyncCount; i++) {
+ psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->
+ ui32WriteOpsComplete++;
+ }
+
+ for (i = 0; i < psCmdCompleteData->ui32SrcSyncCount; i++) {
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->
+ ui32ReadOpsComplete++;
+ }
+
+ psCmdCompleteData->bInUse = IMG_FALSE;
+
+ PVRSRVCommandCompleteCallbacks();
+
+ if (bScheduleMISR)
+ OSScheduleMISR(psSysData);
+}
+
+void PVRSRVCommandCompleteCallbacks(void)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVCommandCompleteCallbacks: "
+ "SysAcquireData failed");
+ return;
+ }
+
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode != NULL) {
+ if (psDeviceNode->pfnDeviceCommandComplete != NULL)
+ (*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
+ psDeviceNode = psDeviceNode->psNext;
+ }
+}
+
+enum PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(u32 ui32DevIndex,
+ IMG_BOOL (**ppfnCmdProcList)(void *, u32, void *),
+ u32 ui32MaxSyncsPerCmd[][2], u32 ui32CmdCount)
+{
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+ u32 i;
+ u32 ui32AllocSize;
+ IMG_BOOL (**ppfnCmdProc)(void *, u32, void *);
+ struct 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;
+ }
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: SysAcquireData failed");
+ return eError;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32CmdCount *
+ sizeof(IMG_BOOL (*)(void *, u32, void *)),
+ (void **)&psSysData->ppfnCmdProcList[ui32DevIndex],
+ NULL);
+ 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(struct COMMAND_COMPLETE_DATA *);
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (void **) &psSysData->
+ ppsCmdCompleteData[ui32DevIndex], NULL);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRegisterCmdProcListKM: Failed to alloc CC data");
+ goto ErrorExit;
+ }
+
+ /* clear the list to ensure that we don't try to access uninitialised
+ * pointer in the 'error' execution path */
+ OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex], 0x00,
+ ui32AllocSize);
+
+ for (i = 0; i < ui32CmdCount; i++) {
+ ui32AllocSize = sizeof(struct COMMAND_COMPLETE_DATA)
+ + ((ui32MaxSyncsPerCmd[i][0] + ui32MaxSyncsPerCmd[i][1])
+ * sizeof(struct PVRSRV_SYNC_OBJECT));
+
+ eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32AllocSize,
+ (void **)&psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i],
+ NULL);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVRegisterCmdProcListKM: "
+ "Failed to alloc cmd %d",
+ i);
+ goto ErrorExit;
+ }
+
+ OSMemSet(psSysData->ppsCmdCompleteData[ui32DevIndex][i], 0x00,
+ ui32AllocSize);
+
+ psCmdCompleteData =
+ psSysData->ppsCmdCompleteData[ui32DevIndex][i];
+
+ psCmdCompleteData->psDstSync = (struct PVRSRV_SYNC_OBJECT *)
+ (((u32) psCmdCompleteData) +
+ sizeof(struct COMMAND_COMPLETE_DATA));
+ psCmdCompleteData->psSrcSync = (struct PVRSRV_SYNC_OBJECT *)
+ (((u32) psCmdCompleteData->psDstSync) +
+ (sizeof(struct 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) {
+ psCmdCompleteData =
+ psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i];
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psCmdCompleteData->ui32AllocSize,
+ psCmdCompleteData, NULL);
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(struct COMMAND_COMPLETE_DATA *),
+ psSysData->ppsCmdCompleteData[ui32DevIndex],
+ NULL);
+ }
+
+ if (psSysData->ppfnCmdProcList[ui32DevIndex] != NULL) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, 0,
+ psSysData->ppfnCmdProcList[ui32DevIndex], NULL);
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(u32 ui32DevIndex, u32 ui32CmdCount)
+{
+ struct SYS_DATA *psSysData;
+ enum PVRSRV_ERROR eError;
+ u32 i;
+
+ if (ui32DevIndex >= SYS_DEVICE_COUNT) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRemoveCmdProcListKM: invalid DeviceType 0x%x",
+ ui32DevIndex);
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "PVRSRVRemoveCmdProcListKM: SysAcquireData failed");
+ return eError;
+ }
+
+ 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) {
+ struct COMMAND_COMPLETE_DATA *
+ psCmdCompleteData = psSysData->
+ ppsCmdCompleteData[ui32DevIndex][i];
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ psCmdCompleteData->ui32AllocSize,
+ psCmdCompleteData, NULL);
+ }
+ }
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount * sizeof(struct COMMAND_COMPLETE_DATA *),
+ psSysData->ppsCmdCompleteData[ui32DevIndex], NULL);
+ }
+
+ if (psSysData->ppfnCmdProcList[ui32DevIndex] != NULL) {
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ ui32CmdCount *
+ sizeof(IMG_BOOL (*)(void *, u32, void *)),
+ psSysData->ppfnCmdProcList[ui32DevIndex], NULL);
+ }
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/pvr/queue.h b/drivers/gpu/pvr/queue.h
new file mode 100644
index 00000000000..92d9fe952c4
--- /dev/null
+++ b/drivers/gpu/pvr/queue.h
@@ -0,0 +1,81 @@
+/**********************************************************************
+ *
+ * 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 QUEUE_H
+#define QUEUE_H
+
+#define UPDATE_QUEUE_ROFF(psQueue, ui32Size) \
+ psQueue->ui32ReadOffset = (psQueue->ui32ReadOffset + ui32Size) \
+ & (psQueue->ui32QueueSize - 1);
+
+struct COMMAND_COMPLETE_DATA {
+ IMG_BOOL bInUse;
+
+ u32 ui32DstSyncCount;
+ u32 ui32SrcSyncCount;
+ struct PVRSRV_SYNC_OBJECT *psDstSync;
+ struct PVRSRV_SYNC_OBJECT *psSrcSync;
+ u32 ui32AllocSize;
+};
+
+enum PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush);
+
+#if defined(__KERNEL__)
+#include <linux/types.h>
+off_t QueuePrintQueues(char *buffer, size_t size, off_t off);
+#endif
+
+enum PVRSRV_ERROR PVRSRVCreateCommandQueueKM(u32 ui32QueueSize,
+ struct PVRSRV_QUEUE_INFO **ppsQueueInfo);
+enum PVRSRV_ERROR PVRSRVDestroyCommandQueueKM(
+ struct PVRSRV_QUEUE_INFO *psQueueInfo);
+
+enum PVRSRV_ERROR PVRSRVInsertCommandKM(struct PVRSRV_QUEUE_INFO *psQueue,
+ struct PVRSRV_COMMAND **ppsCommand, u32 ui32DevIndex,
+ u16 CommandType, u32 ui32DstSyncCount,
+ struct PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
+ u32 ui32SrcSyncCount,
+ struct PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
+ u32 ui32DataByteSize);
+
+enum PVRSRV_ERROR PVRSRVGetQueueSpaceKM(struct PVRSRV_QUEUE_INFO *psQueue,
+ u32 ui32ParamSize, void **ppvSpace);
+
+enum PVRSRV_ERROR PVRSRVSubmitCommandKM(struct PVRSRV_QUEUE_INFO *psQueue,
+ struct PVRSRV_COMMAND *psCommand);
+
+void PVRSRVCommandCompleteKM(void *hCmdCookie, IMG_BOOL bScheduleMISR);
+
+void PVRSRVCommandCompleteCallbacks(void);
+
+enum PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(u32 ui32DevIndex,
+ IMG_BOOL (**ppfnCmdProcList)(void *, u32, void *),
+ u32 ui32MaxSyncsPerCmd[][2], u32 ui32CmdCount);
+enum PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(u32 ui32DevIndex,
+ u32 ui32CmdCount);
+
+
+#endif
diff --git a/drivers/gpu/pvr/ra.c b/drivers/gpu/pvr/ra.c
new file mode 100644
index 00000000000..4c71af18839
--- /dev/null
+++ b/drivers/gpu/pvr/ra.c
@@ -0,0 +1,1164 @@
+/**********************************************************************
+ *
+ * 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"
+
+#include <linux/kernel.h>
+#include "proc.h"
+
+
+#define MINIMUM_HASH_SIZE 64
+
+struct BT {
+ enum bt_type {
+ btt_span,
+ btt_free,
+ btt_live
+ } type;
+
+ u32 base;
+ size_t uSize;
+
+ struct BT *pNextSegment;
+ struct BT *pPrevSegment;
+
+ struct BT *pNextFree;
+ struct BT *pPrevFree;
+
+ struct BM_MAPPING *psMapping;
+};
+struct BT;
+
+struct RA_ARENA {
+ char *name;
+ u32 uQuantum;
+ IMG_BOOL(*pImportAlloc)(void *, size_t uSize, size_t *pActualSize,
+ struct BM_MAPPING **ppsMapping, u32 uFlags,
+ u32 *pBase);
+ void (*pImportFree)(void *, u32, struct BM_MAPPING *psMapping);
+ void (*pBackingStoreFree)(void *, u32, u32, void *);
+ void *pImportHandle;
+#define FREE_TABLE_LIMIT 32
+ struct BT *aHeadFree[FREE_TABLE_LIMIT];
+ struct BT *pHeadSegment;
+ struct BT *pTailSegment;
+ struct HASH_TABLE *pSegmentHash;
+#ifdef RA_STATS
+ struct RA_STATISTICS sStatistics;
+#endif
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
+#define PROC_NAME_SIZE 32
+ char szProcInfoName[PROC_NAME_SIZE];
+ char szProcSegsName[PROC_NAME_SIZE];
+ IMG_BOOL bInitProcEntry;
+#endif
+};
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
+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
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
+static char *ReplaceSpaces(char *const pS)
+{
+ char *pT;
+
+ for (pT = pS; *pT != 0; pT++)
+ if (*pT == ' ' || *pT == '\t')
+ *pT = '_';
+
+ return pS;
+}
+#endif
+
+static IMG_BOOL _RequestAllocFail(void *_h, size_t _uSize, size_t *_pActualSize,
+ struct BM_MAPPING **_ppsMapping,
+ u32 _uFlags, u32 *_pBase)
+{
+ PVR_UNREFERENCED_PARAMETER(_h);
+ PVR_UNREFERENCED_PARAMETER(_uSize);
+ PVR_UNREFERENCED_PARAMETER(_pActualSize);
+ PVR_UNREFERENCED_PARAMETER(_ppsMapping);
+ PVR_UNREFERENCED_PARAMETER(_uFlags);
+ PVR_UNREFERENCED_PARAMETER(_pBase);
+
+ return IMG_FALSE;
+}
+
+static u32 pvr_log2(size_t n)
+{
+ u32 l = 0;
+ n >>= 1;
+ while (n > 0) {
+ n >>= 1;
+ l++;
+ }
+ return l;
+}
+
+static enum PVRSRV_ERROR _SegmentListInsertAfter(struct RA_ARENA *pArena,
+ struct BT *pInsertionPoint,
+ struct 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 enum PVRSRV_ERROR _SegmentListInsert(struct RA_ARENA *pArena,
+ struct BT *pBT)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (pArena->pHeadSegment == NULL) {
+ pArena->pHeadSegment = pArena->pTailSegment = pBT;
+ pBT->pNextSegment = pBT->pPrevSegment = NULL;
+ } else {
+ struct 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(struct RA_ARENA *pArena, struct 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 struct BT *_SegmentSplit(struct RA_ARENA *pArena, struct BT *pBT,
+ size_t uSize)
+{
+ struct 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(struct BT),
+ (void **) &pNeighbour, NULL) != PVRSRV_OK)
+ return NULL;
+
+ 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;
+ return pNeighbour;
+}
+
+static void _FreeListInsert(struct RA_ARENA *pArena, struct 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(struct RA_ARENA *pArena, struct 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 struct BT *_BuildSpanMarker(u32 base, size_t uSize)
+{
+ struct BT *pBT;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct BT),
+ (void **) &pBT, NULL) != PVRSRV_OK)
+ return NULL;
+
+ pBT->type = btt_span;
+ pBT->base = base;
+ pBT->uSize = uSize;
+ pBT->psMapping = NULL;
+
+ return pBT;
+}
+
+static struct BT *_BuildBT(u32 base, size_t uSize)
+{
+ struct BT *pBT;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct BT),
+ (void **) &pBT, NULL) != PVRSRV_OK)
+ return NULL;
+
+ pBT->type = btt_free;
+ pBT->base = base;
+ pBT->uSize = uSize;
+
+ return pBT;
+}
+
+static struct BT *_InsertResource(struct RA_ARENA *pArena, u32 base,
+ size_t uSize)
+{
+ struct 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 (_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 struct BT *_InsertResourceSpan(struct RA_ARENA *pArena, u32 base,
+ size_t uSize)
+{
+ enum PVRSRV_ERROR eError;
+ struct BT *pSpanStart;
+ struct BT *pSpanEnd;
+ struct 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;
+ pSpanEnd = _BuildSpanMarker(base + uSize, 0);
+ if (pSpanEnd == NULL)
+ goto fail_end;
+
+ pBT = _BuildBT(base, uSize);
+ if (pBT == NULL)
+ goto fail_bt;
+
+ 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(struct BT), pBT, NULL);
+fail_bt:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pSpanEnd, NULL);
+fail_end:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pSpanStart, NULL);
+fail_start:
+ return NULL;
+}
+
+static void _FreeBT(struct RA_ARENA *pArena, struct BT *pBT,
+ IMG_BOOL bFreeBackingStore)
+{
+ struct BT *pNeighbour;
+ u32 uOrigBase;
+ size_t 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(struct 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(struct 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) {
+ struct BT *next = pBT->pNextSegment;
+ struct 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(struct BT), next,
+ NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), prev,
+ NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pBT,
+ NULL);
+ } else
+ _FreeListInsert(pArena, pBT);
+}
+
+static int alloc_from_bt(struct RA_ARENA *arena, struct BT *bt, u32 start,
+ size_t size, u32 align,
+ struct BM_MAPPING **new_mapping, u32 *new_base)
+{
+ _FreeListRemove(arena, bt);
+ PVR_ASSERT(bt->type == btt_free);
+#ifdef RA_STATS
+ arena->sStatistics.uLiveSegmentCount++;
+ arena->sStatistics.uFreeSegmentCount--;
+ arena->sStatistics.uFreeResourceCount -= bt->uSize;
+#endif
+ if (start > bt->base) {
+ struct BT *next_bt;
+
+ next_bt = _SegmentSplit(arena, bt, start - bt->base);
+
+ if (!next_bt) {
+ PVR_DPF(PVR_DBG_ERROR, "_AttemptAllocAligned: "
+ "Front split failed");
+
+ _FreeListInsert(arena, bt);
+ return -1;
+ }
+
+ _FreeListInsert(arena, bt);
+#ifdef RA_STATS
+ arena->sStatistics.uFreeSegmentCount++;
+ arena->sStatistics.uFreeResourceCount += bt->uSize;
+#endif
+ bt = next_bt;
+ }
+
+ if (bt->uSize > size) {
+ struct BT *next_bt;
+ next_bt = _SegmentSplit(arena, bt, size);
+
+ if (!next_bt) {
+ PVR_DPF(PVR_DBG_ERROR, "_AttemptAllocAligned: "
+ "Back split failed");
+
+ _FreeListInsert(arena, bt);
+ return -1;
+ }
+
+ _FreeListInsert(arena, next_bt);
+#ifdef RA_STATS
+ arena->sStatistics.uFreeSegmentCount++;
+ arena->sStatistics.uFreeResourceCount += next_bt->uSize;
+#endif
+ }
+
+ bt->type = btt_live;
+
+ if (!HASH_Insert(arena->pSegmentHash, bt->base, (u32)bt)) {
+ _FreeBT(arena, bt, IMG_FALSE);
+ return -1;
+ }
+
+ if (new_mapping)
+ *new_mapping = bt->psMapping;
+
+ *new_base = bt->base;
+
+ return 0;
+}
+
+static IMG_BOOL _AttemptAllocAligned(struct RA_ARENA *pArena, size_t uSize,
+ struct BM_MAPPING **ppsMapping, u32 uFlags, u32 uAlignment,
+ u32 *base)
+{
+ u32 uIndex;
+ PVR_ASSERT(pArena != NULL);
+ if (pArena == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "_AttemptAllocAligned: invalid parameter - pArena");
+ return IMG_FALSE;
+ }
+
+ uIndex = pvr_log2(uSize);
+
+ while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex] == NULL)
+ uIndex++;
+
+ for (; uIndex < FREE_TABLE_LIMIT; uIndex++) {
+ struct BT *pBT;
+
+ pBT = pArena->aHeadFree[uIndex];
+ if (!pBT)
+ continue;
+
+ for (; pBT != NULL; pBT = pBT->pNextFree) {
+ u32 aligned_base;
+
+ if (uAlignment > 1)
+ aligned_base = (pBT->base + uAlignment -
+ 1) / uAlignment * uAlignment;
+ 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)
+ continue;
+
+ if (pBT->psMapping && pBT->psMapping->ui32Flags !=
+ uFlags) {
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "AttemptAllocAligned: mismatch in "
+ "flags. Import has %x, request was %x",
+ pBT->psMapping->ui32Flags, uFlags);
+ continue;
+ }
+
+ if (alloc_from_bt(pArena, pBT, aligned_base, uSize,
+ uFlags, ppsMapping, base) < 0)
+ return IMG_FALSE;
+
+ return IMG_TRUE;
+ }
+ }
+
+ return IMG_FALSE;
+}
+
+struct RA_ARENA *RA_Create(char *name, u32 base, size_t uSize,
+ struct BM_MAPPING *psMapping, size_t uQuantum,
+ IMG_BOOL(*imp_alloc) (void *, size_t uSize,
+ size_t *pActualSize,
+ struct BM_MAPPING **ppsMapping,
+ u32 _flags, u32 *pBase),
+ void (*imp_free) (void *, u32, struct BM_MAPPING *),
+ void(*backingstore_free) (void *, u32, u32, void *),
+ void *pImportHandle)
+{
+ struct RA_ARENA *pArena;
+ struct BT *pBT;
+ int i;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "RA_Create: "
+ "name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
+ name, base, uSize, imp_alloc, imp_free);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*pArena),
+ (void **) &pArena, NULL) != PVRSRV_OK)
+ goto arena_fail;
+
+ pArena->name = name;
+ pArena->pImportAlloc =
+ (imp_alloc != NULL) ? imp_alloc : _RequestAllocFail;
+ pArena->pImportFree = imp_free;
+ pArena->pBackingStoreFree = backingstore_free;
+ pArena->pImportHandle = pImportHandle;
+ for (i = 0; i < FREE_TABLE_LIMIT; i++)
+ pArena->aHeadFree[i] = NULL;
+ pArena->pHeadSegment = NULL;
+ pArena->pTailSegment = NULL;
+ pArena->uQuantum = uQuantum;
+
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount = 0;
+ pArena->sStatistics.uLiveSegmentCount = 0;
+ pArena->sStatistics.uFreeSegmentCount = 0;
+ pArena->sStatistics.uFreeResourceCount = 0;
+ pArena->sStatistics.uTotalResourceCount = 0;
+ pArena->sStatistics.uCumulativeAllocs = 0;
+ pArena->sStatistics.uCumulativeFrees = 0;
+ pArena->sStatistics.uImportCount = 0;
+ pArena->sStatistics.uExportCount = 0;
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
+ if (strcmp(pArena->name, "") != 0) {
+ int ret;
+ int (*pfnCreateProcEntry) (const char *, read_proc_t,
+ write_proc_t, void *);
+
+ pArena->bInitProcEntry =
+ !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
+
+ pfnCreateProcEntry = pArena->bInitProcEntry ? CreateProcEntry :
+ CreatePerProcessProcEntry;
+
+ ret = snprintf(pArena->szProcInfoName,
+ sizeof(pArena->szProcInfoName), "ra_info_%s",
+ pArena->name);
+ if (ret > 0 && ret < sizeof(pArena->szProcInfoName)) {
+ (void)pfnCreateProcEntry(ReplaceSpaces
+ (pArena->szProcInfoName),
+ RA_DumpInfo, NULL, pArena);
+ } else {
+ pArena->szProcInfoName[0] = 0;
+ PVR_DPF(PVR_DBG_ERROR, "RA_Create: "
+ "couldn't create ra_info proc entry for arena %s",
+ pArena->name);
+ }
+
+ ret = snprintf(pArena->szProcSegsName,
+ sizeof(pArena->szProcSegsName), "ra_segs_%s",
+ pArena->name);
+ if (ret > 0 && ret < sizeof(pArena->szProcInfoName)) {
+ (void)pfnCreateProcEntry(ReplaceSpaces
+ (pArena->szProcSegsName),
+ RA_DumpSegs, NULL, pArena);
+ } else {
+ pArena->szProcSegsName[0] = 0;
+ PVR_DPF(PVR_DBG_ERROR, "RA_Create: "
+ "couldn't create ra_segs proc entry for arena %s",
+ pArena->name);
+ }
+ }
+#endif
+
+ pArena->pSegmentHash = HASH_Create(MINIMUM_HASH_SIZE);
+ if (pArena->pSegmentHash == NULL)
+ goto hash_fail;
+ if (uSize > 0) {
+ uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
+ pBT = _InsertResource(pArena, base, uSize);
+ if (pBT == NULL)
+ goto insert_fail;
+ pBT->psMapping = psMapping;
+
+ }
+ return pArena;
+
+insert_fail:
+ HASH_Delete(pArena->pSegmentHash);
+hash_fail:
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RA_ARENA), pArena,
+ NULL);
+arena_fail:
+ return NULL;
+}
+
+void RA_Delete(struct RA_ARENA *pArena)
+{
+ u32 uIndex;
+
+ PVR_ASSERT(pArena != NULL);
+
+ if (pArena == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "RA_Delete: invalid parameter - pArena");
+ return;
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE, "RA_Delete: name='%s'", pArena->name);
+
+ for (uIndex = 0; uIndex < FREE_TABLE_LIMIT; uIndex++)
+ pArena->aHeadFree[uIndex] = NULL;
+
+ while (pArena->pHeadSegment != NULL) {
+ struct BT *pBT = pArena->pHeadSegment;
+ PVR_ASSERT(pBT->type == btt_free);
+ _SegmentListRemove(pArena, pBT);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pBT,
+ NULL);
+#ifdef RA_STATS
+ pArena->sStatistics.uSpanCount--;
+#endif
+ }
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
+ {
+ void (*pfnRemoveProcEntry) (const char *);
+
+ pfnRemoveProcEntry =
+ pArena->
+ bInitProcEntry ? RemoveProcEntry :
+ RemovePerProcessProcEntry;
+
+ if (pArena->szProcInfoName[0] != 0)
+ pfnRemoveProcEntry(pArena->szProcInfoName);
+
+ if (pArena->szProcSegsName[0] != 0)
+ pfnRemoveProcEntry(pArena->szProcSegsName);
+ }
+#endif
+ HASH_Delete(pArena->pSegmentHash);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RA_ARENA), pArena,
+ NULL);
+}
+
+IMG_BOOL RA_TestDelete(struct RA_ARENA *pArena)
+{
+ PVR_ASSERT(pArena != NULL);
+
+ if (pArena != NULL)
+ while (pArena->pHeadSegment != NULL) {
+ struct BT *pBT = pArena->pHeadSegment;
+ if (pBT->type != btt_free)
+ return IMG_FALSE;
+ }
+
+ return IMG_TRUE;
+}
+
+IMG_BOOL RA_Add(struct RA_ARENA *pArena, u32 base, size_t uSize)
+{
+ PVR_ASSERT(pArena != NULL);
+
+ if (pArena == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "RA_Add: invalid parameter - pArena");
+ return IMG_FALSE;
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base,
+ uSize);
+
+ uSize = (uSize + pArena->uQuantum - 1) /
+ pArena->uQuantum * pArena->uQuantum;
+ return (IMG_BOOL)(_InsertResource(pArena, base, uSize) != NULL);
+}
+
+IMG_BOOL RA_Alloc(struct RA_ARENA *pArena, size_t uRequestSize,
+ struct BM_MAPPING **ppsMapping, u32 uFlags, u32 uAlignment,
+ u32 *base)
+{
+ IMG_BOOL bResult;
+ size_t uSize = uRequestSize;
+
+ PVR_ASSERT(pArena != NULL);
+
+ if (pArena == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "RA_Alloc: invalid parameter - pArena");
+ return IMG_FALSE;
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
+ "arena='%s', size=0x%x(0x%x), alignment=0x%x",
+ pArena->name, uSize, uRequestSize, uAlignment);
+
+ bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
+ uAlignment, base);
+ if (!bResult) {
+ struct BM_MAPPING *psImportMapping;
+ u32 import_base;
+ size_t uImportSize = uSize;
+
+ if (uAlignment > pArena->uQuantum)
+ uImportSize += (uAlignment - 1);
+
+ uImportSize =
+ ((uImportSize + pArena->uQuantum - 1) /
+ pArena->uQuantum) * pArena->uQuantum;
+
+ bResult =
+ pArena->pImportAlloc(pArena->pImportHandle, uImportSize,
+ &uImportSize, &psImportMapping, uFlags,
+ &import_base);
+ if (bResult) {
+ struct BT *pBT;
+ pBT = _InsertResourceSpan(pArena, import_base,
+ uImportSize);
+
+ if (pBT == NULL) {
+ pArena->pImportFree(pArena->pImportHandle,
+ import_base,
+ psImportMapping);
+ PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
+ "name='%s', size=0x%x failed!",
+ pArena->name, uSize);
+
+ return IMG_FALSE;
+ }
+ pBT->psMapping = psImportMapping;
+#ifdef RA_STATS
+ pArena->sStatistics.uFreeSegmentCount++;
+ pArena->sStatistics.uFreeResourceCount += uImportSize;
+ pArena->sStatistics.uImportCount++;
+ pArena->sStatistics.uSpanCount++;
+#endif
+ bResult = _AttemptAllocAligned(pArena, uSize,
+ ppsMapping, uFlags, uAlignment,
+ base);
+ if (!bResult)
+ PVR_DPF(PVR_DBG_MESSAGE, "RA_Alloc: "
+ "name='%s' uAlignment failed!",
+ pArena->name);
+ }
+ }
+#ifdef RA_STATS
+ if (bResult)
+ pArena->sStatistics.uCumulativeAllocs++;
+#endif
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
+ pArena->name, uSize, *base, bResult);
+
+ return bResult;
+}
+
+void RA_Free(struct RA_ARENA *pArena, u32 base, IMG_BOOL bFreeBackingStore)
+{
+ struct BT *pBT;
+
+ PVR_ASSERT(pArena != NULL);
+
+ if (pArena == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "RA_Free: invalid parameter - pArena");
+ return;
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "RA_Free: name='%s', base=0x%x", pArena->name, base);
+
+ pBT = (struct BT *)HASH_Remove(pArena->pSegmentHash, base);
+ PVR_ASSERT(pBT != NULL);
+
+ if (pBT) {
+ PVR_ASSERT(pBT->base == base);
+
+#ifdef RA_STATS
+ pArena->sStatistics.uCumulativeFrees++;
+#endif
+
+ _FreeBT(pArena, pBT, bFreeBackingStore);
+ }
+}
+
+IMG_BOOL RA_GetNextLiveSegment(void *hArena,
+ struct RA_SEGMENT_DETAILS *psSegDetails)
+{
+ struct BT *pBT;
+
+ if (psSegDetails->hSegment) {
+ pBT = (struct BT *)psSegDetails->hSegment;
+ } else {
+ struct RA_ARENA *pArena = (struct RA_ARENA *)hArena;
+ pBT = pArena->pHeadSegment;
+ }
+
+ while (pBT != NULL) {
+ if (pBT->type == btt_live) {
+ psSegDetails->uiSize = pBT->uSize;
+ psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
+ psSegDetails->hSegment = (void *) pBT->pNextSegment;
+
+ return IMG_TRUE;
+ }
+
+ pBT = pBT->pNextSegment;
+ }
+
+ psSegDetails->uiSize = 0;
+ psSegDetails->sCpuPhyAddr.uiAddr = 0;
+ psSegDetails->hSegment = (void *) -1;
+
+ return IMG_FALSE;
+}
+
+#if (defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)) || \
+ defined(RA_STATS)
+static char *_BTType(int eType)
+{
+ switch (eType) {
+ case btt_span:
+ return "span";
+ case btt_free:
+ return "free";
+ case btt_live:
+ return "live";
+ }
+ return "junk";
+}
+#endif
+
+#if defined(ENABLE_RA_DUMP)
+void RA_Dump(struct RA_ARENA *pArena)
+{
+ struct BT *pBT;
+ PVR_ASSERT(pArena != NULL);
+ PVR_DPF(PVR_DBG_MESSAGE, "Arena '%s':", pArena->name);
+ PVR_DPF(PVR_DBG_MESSAGE,
+ " alloc=%08X free=%08X handle=%08X quantum=%d",
+ pArena->pImportAlloc, pArena->pImportFree,
+ pArena->pImportHandle, pArena->uQuantum);
+ PVR_DPF(PVR_DBG_MESSAGE, " segment Chain:");
+ if (pArena->pHeadSegment != NULL &&
+ pArena->pHeadSegment->pPrevSegment != NULL)
+ PVR_DPF(PVR_DBG_MESSAGE,
+ " error: head boundary tag has invalid pPrevSegment");
+ if (pArena->pTailSegment != NULL &&
+ pArena->pTailSegment->pNextSegment != NULL)
+ PVR_DPF(PVR_DBG_MESSAGE,
+ " error: tail boundary tag has invalid pNextSegment");
+
+ for (pBT = pArena->pHeadSegment; pBT != NULL; pBT = pBT->pNextSegment)
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "\tbase=0x%x size=0x%x type=%s ref=%08X",
+ (u32) pBT->base, pBT->uSize, _BTType(pBT->type),
+ pBT->pRef);
+
+}
+#endif
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_DEBUG_EXTRA)
+static int RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
+ void *data)
+{
+ struct BT *pBT = NULL;
+ int len = 0;
+ struct RA_ARENA *pArena = (struct RA_ARENA *)data;
+
+ if (count < 80) {
+ *start = (char *)0;
+ return 0;
+ }
+ *eof = 0;
+ *start = (char *)1;
+ if (off == 0)
+ return printAppend(page, count, 0,
+ "Arena \"%s\"\nBase Size Type Ref\n",
+ pArena->name);
+ for (pBT = pArena->pHeadSegment; --off && pBT;
+ pBT = pBT->pNextSegment)
+ ;
+ if (pBT)
+ len = printAppend(page, count, 0, "%08x %8x %4s %08x\n",
+ (unsigned)pBT->base, (unsigned)pBT->uSize,
+ _BTType(pBT->type), (unsigned)pBT->psMapping);
+ else
+ *eof = 1;
+ return len;
+}
+
+static int RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
+ void *data)
+{
+ int len = 0;
+ struct RA_ARENA *pArena = (struct RA_ARENA *)data;
+
+ if (count < 80) {
+ *start = (char *)0;
+ return 0;
+ }
+ *eof = 0;
+ switch (off) {
+ case 0:
+ len = printAppend(page, count, 0, "quantum\t\t\t%u\n",
+ pArena->uQuantum);
+ break;
+ case 1:
+ len = printAppend(page, count, 0, "import_handle\t\t%08X\n",
+ (unsigned)pArena->pImportHandle);
+ break;
+#ifdef RA_STATS
+ case 2:
+ len = printAppend(page, count, 0, "span count\t\t%u\n",
+ pArena->sStatistics.uSpanCount);
+ break;
+ case 3:
+ len = printAppend(page, count, 0, "live segment count\t%u\n",
+ pArena->sStatistics.uLiveSegmentCount);
+ break;
+ case 4:
+ len = printAppend(page, count, 0, "free segment count\t%u\n",
+ pArena->sStatistics.uFreeSegmentCount);
+ break;
+ case 5:
+ len = printAppend(page, count, 0,
+ "free resource count\t%u (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (unsigned)pArena->sStatistics.
+ uFreeResourceCount);
+ break;
+ case 6:
+ len = printAppend(page, count, 0, "total allocs\t\t%u\n",
+ pArena->sStatistics.uCumulativeAllocs);
+ break;
+ case 7:
+ len = printAppend(page, count, 0, "total frees\t\t%u\n",
+ pArena->sStatistics.uCumulativeFrees);
+ break;
+ case 8:
+ len = printAppend(page, count, 0, "import count\t\t%u\n",
+ pArena->sStatistics.uImportCount);
+ break;
+ case 9:
+ len = printAppend(page, count, 0, "export count\t\t%u\n",
+ pArena->sStatistics.uExportCount);
+ break;
+#endif
+
+ default:
+ *eof = 1;
+ }
+ *start = (char *)1;
+ return len;
+}
+#endif
+
+#ifdef RA_STATS
+enum PVRSRV_ERROR RA_GetStats(struct RA_ARENA *pArena, char **ppszStr,
+ u32 *pui32StrLen)
+{
+ char *pszStr = *ppszStr;
+ u32 ui32StrLen = *pui32StrLen;
+ s32 i32Count;
+ struct BT *pBT;
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100,
+ " allocCB=%08X freeCB=%08X handle=%08X quantum=%d\n",
+ pArena->pImportAlloc, pArena->pImportFree,
+ pArena->pImportHandle, pArena->uQuantum);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%lu\n",
+ pArena->sStatistics.uSpanCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%lu\n",
+ pArena->sStatistics.uLiveSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%lu\n",
+ pArena->sStatistics.uFreeSegmentCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n",
+ pArena->sStatistics.uFreeResourceCount,
+ (unsigned)pArena->sStatistics.uFreeResourceCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n",
+ pArena->sStatistics.uCumulativeAllocs);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n",
+ pArena->sStatistics.uCumulativeFrees);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%lu\n",
+ pArena->sStatistics.uImportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%lu\n",
+ pArena->sStatistics.uExportCount);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+
+ if (pArena->pHeadSegment != NULL &&
+ pArena->pHeadSegment->pPrevSegment != NULL) {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100,
+ " error: head boundary tag has invalid pPrevSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ if (pArena->pTailSegment != NULL &&
+ pArena->pTailSegment->pNextSegment != NULL) {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100,
+ " error: tail boundary tag has invalid pNextSegment\n");
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ for (pBT = pArena->pHeadSegment; pBT != NULL;
+ pBT = pBT->pNextSegment) {
+ CHECK_SPACE(ui32StrLen);
+ i32Count = OSSNPrintf(pszStr, 100,
+ "\tbase=0x%x size=0x%x type=%s ref=%08X\n",
+ (u32) pBT->base, pBT->uSize, _BTType(pBT->type),
+ pBT->psMapping);
+ UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
+ }
+
+ *ppszStr = pszStr;
+ *pui32StrLen = ui32StrLen;
+
+ return PVRSRV_OK;
+}
+#endif
diff --git a/drivers/gpu/pvr/ra.h b/drivers/gpu/pvr/ra.h
new file mode 100644
index 00000000000..2f9ceeaca62
--- /dev/null
+++ b/drivers/gpu/pvr/ra.h
@@ -0,0 +1,107 @@
+/**********************************************************************
+ *
+ * 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 _RA_H_
+#define _RA_H_
+
+#include "img_types.h"
+#include "hash.h"
+#include "osfunc.h"
+
+struct RA_ARENA;
+struct BM_MAPPING;
+
+#define RA_STATS
+
+struct RA_STATISTICS {
+ u32 uSpanCount;
+ u32 uLiveSegmentCount;
+ u32 uFreeSegmentCount;
+ u32 uTotalResourceCount;
+ u32 uFreeResourceCount;
+ u32 uCumulativeAllocs;
+ u32 uCumulativeFrees;
+ u32 uImportCount;
+ u32 uExportCount;
+};
+struct RA_STATISTICS;
+
+struct RA_SEGMENT_DETAILS {
+ u32 uiSize;
+ struct IMG_CPU_PHYADDR sCpuPhyAddr;
+ void *hSegment;
+};
+struct RA_SEGMENT_DETAILS;
+
+struct RA_ARENA *RA_Create(char *name, u32 base, size_t uSize,
+ struct BM_MAPPING *psMapping, size_t uQuantum,
+ IMG_BOOL(*imp_alloc)(void *_h, size_t uSize,
+ size_t *pActualSize,
+ struct BM_MAPPING **ppsMapping,
+ u32 uFlags, u32 *pBase),
+ void (*imp_free)(void *, u32, struct BM_MAPPING *),
+ void (*backingstore_free)(void *, u32, u32, void *),
+ void *import_handle);
+
+void RA_Delete(struct RA_ARENA *pArena);
+
+IMG_BOOL RA_TestDelete(struct RA_ARENA *pArena);
+
+IMG_BOOL RA_Add(struct RA_ARENA *pArena, u32 base, size_t uSize);
+
+IMG_BOOL RA_Alloc(struct RA_ARENA *pArena, size_t uSize,
+ struct BM_MAPPING **ppsMapping, u32 uFlags, u32 uAlignment,
+ u32 *pBase);
+
+void RA_Free(struct RA_ARENA *pArena, u32 base, IMG_BOOL bFreeBackingStore);
+
+#ifdef RA_STATS
+
+#define CHECK_SPACE(total) \
+{ \
+ if (total < 100) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+}
+
+#define UPDATE_SPACE(str, count, total) \
+{ \
+ if (count == -1) \
+ return PVRSRV_ERROR_INVALID_PARAMS; \
+ else { \
+ str += count; \
+ total -= count; \
+ } \
+}
+
+IMG_BOOL RA_GetNextLiveSegment(void *hArena,
+ struct RA_SEGMENT_DETAILS *psSegDetails);
+
+enum PVRSRV_ERROR RA_GetStats(struct RA_ARENA *pArena, char **ppszStr,
+ u32 *pui32StrLen);
+
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/resman.c b/drivers/gpu/pvr/resman.c
new file mode 100644
index 00000000000..f05c2d7faa3
--- /dev/null
+++ b/drivers/gpu/pvr/resman.c
@@ -0,0 +1,568 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/sched.h>
+#include <linux/hardirq.h>
+
+#include <linux/semaphore.h>
+
+#include "services_headers.h"
+#include "resman.h"
+
+static DEFINE_SEMAPHORE(lock);
+
+#define ACQUIRE_SYNC_OBJ do { \
+ if (in_interrupt()) { \
+ printk(KERN_ERR "ISR cannot take RESMAN mutex\n"); \
+ BUG(); \
+ } else \
+ down(&lock); \
+} while (0)
+#define RELEASE_SYNC_OBJ up(&lock)
+
+
+#define RESMAN_SIGNATURE 0x12345678
+
+struct RESMAN_ITEM {
+#ifdef CONFIG_PVR_DEBUG
+ u32 ui32Signature;
+#endif
+ struct RESMAN_ITEM **ppsThis;
+ struct RESMAN_ITEM *psNext;
+
+ u32 ui32Flags;
+ u32 ui32ResType;
+
+ void *pvParam;
+ u32 ui32Param;
+
+ enum PVRSRV_ERROR (*pfnFreeResource)(void *pvParam, u32 ui32Param);
+};
+
+struct RESMAN_CONTEXT {
+#ifdef CONFIG_PVR_DEBUG
+ u32 ui32Signature;
+#endif
+ struct RESMAN_CONTEXT **ppsThis;
+ struct RESMAN_CONTEXT *psNext;
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc;
+ struct RESMAN_ITEM *psResItemList;
+
+};
+
+struct RESMAN_LIST {
+ struct RESMAN_CONTEXT *psContextList;
+};
+
+static struct RESMAN_LIST *gpsResList;
+
+#define PRINT_RESLIST(x, y, z)
+
+static void FreeResourceByPtr(struct RESMAN_ITEM *psItem,
+ IMG_BOOL bExecuteCallback);
+
+static int FreeResourceByCriteria(struct RESMAN_CONTEXT *psContext,
+ u32 ui32SearchCriteria,
+ u32 ui32ResType, void *pvParam,
+ u32 ui32Param,
+ IMG_BOOL bExecuteCallback);
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+static void ValidateResList(struct RESMAN_LIST *psResList);
+#define VALIDATERESLIST() ValidateResList(gpsResList)
+#else
+#define VALIDATERESLIST()
+#endif
+
+enum PVRSRV_ERROR ResManInit(void)
+{
+ if (gpsResList == NULL) {
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(*gpsResList),
+ (void **) &gpsResList,
+ NULL) != PVRSRV_OK)
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+
+ gpsResList->psContextList = NULL;
+
+ VALIDATERESLIST();
+ }
+
+ return PVRSRV_OK;
+}
+
+void ResManDeInit(void)
+{
+ if (gpsResList != NULL)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList),
+ gpsResList, NULL);
+}
+
+enum PVRSRV_ERROR PVRSRVResManConnect(void *hPerProc,
+ struct RESMAN_CONTEXT **phResManContext)
+{
+ enum PVRSRV_ERROR eError;
+ struct RESMAN_CONTEXT *psResManContext;
+
+ ACQUIRE_SYNC_OBJ;
+
+ VALIDATERESLIST();
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
+ (void **) &psResManContext, NULL);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "PVRSRVResManConnect: "
+ "ERROR allocating new RESMAN context struct");
+
+ VALIDATERESLIST();
+ RELEASE_SYNC_OBJ;
+
+ return eError;
+ }
+#ifdef CONFIG_PVR_DEBUG
+ psResManContext->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psResManContext->psResItemList = NULL;
+ psResManContext->psPerProc = hPerProc;
+
+ psResManContext->psNext = gpsResList->psContextList;
+ psResManContext->ppsThis = &gpsResList->psContextList;
+ gpsResList->psContextList = psResManContext;
+ if (psResManContext->psNext)
+ psResManContext->psNext->ppsThis = &(psResManContext->psNext);
+
+ VALIDATERESLIST();
+
+ RELEASE_SYNC_OBJ;
+
+ *phResManContext = psResManContext;
+
+ return PVRSRV_OK;
+}
+
+static inline bool warn_unfreed_res(void)
+{
+ return !(current->flags & PF_SIGNALED);
+}
+
+static int free_one_res(struct RESMAN_CONTEXT *ctx, u32 restype)
+{
+ int freed;
+
+ freed = FreeResourceByCriteria(ctx, RESMAN_CRITERIA_RESTYPE, restype,
+ NULL, 0, IMG_TRUE);
+ if (freed && warn_unfreed_res())
+ PVR_DPF(DBGPRIV_WARNING, "pvr: %s: cleaning up %d "
+ "unfreed resource of type %d\n",
+ current->comm, freed, restype);
+
+ return freed;
+}
+
+void PVRSRVResManDisconnect(struct RESMAN_CONTEXT *ctx, IMG_BOOL bKernelContext)
+{
+
+ ACQUIRE_SYNC_OBJ;
+
+ VALIDATERESLIST();
+
+ PRINT_RESLIST(gpsResList, ctx, IMG_TRUE);
+
+ if (!bKernelContext) {
+ int i = 0;
+
+ i += free_one_res(ctx, RESMAN_TYPE_OS_USERMODE_MAPPING);
+ i += free_one_res(ctx, RESMAN_TYPE_EVENT_OBJECT);
+ i += free_one_res(ctx, RESMAN_TYPE_HW_RENDER_CONTEXT);
+ i += free_one_res(ctx, RESMAN_TYPE_HW_TRANSFER_CONTEXT);
+ i += free_one_res(ctx, RESMAN_TYPE_HW_2D_CONTEXT);
+ i += free_one_res(ctx, RESMAN_TYPE_TRANSFER_CONTEXT);
+ i += free_one_res(ctx, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK);
+ i += free_one_res(ctx, RESMAN_TYPE_SHARED_PB_DESC);
+ i += free_one_res(ctx, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN);
+ i += free_one_res(ctx, RESMAN_TYPE_DISPLAYCLASS_DEVICE);
+ i += free_one_res(ctx, RESMAN_TYPE_BUFFERCLASS_DEVICE);
+ i += free_one_res(ctx, RESMAN_TYPE_DEVICECLASSMEM_MAPPING);
+ i += free_one_res(ctx, RESMAN_TYPE_DEVICEMEM_WRAP);
+ i += free_one_res(ctx, RESMAN_TYPE_DEVICEMEM_MAPPING);
+ i += free_one_res(ctx, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION);
+ i += free_one_res(ctx, RESMAN_TYPE_DEVICEMEM_ALLOCATION);
+ i += free_one_res(ctx, RESMAN_TYPE_DEVICEMEM_CONTEXT);
+
+ if (i && warn_unfreed_res())
+ pr_warning("pvr: %s: cleaning up %d "
+ "unfreed resources\n",
+ current->comm, i);
+ }
+
+ PVR_ASSERT(ctx->psResItemList == NULL);
+
+ *(ctx->ppsThis) = ctx->psNext;
+ if (ctx->psNext)
+ ctx->psNext->ppsThis = ctx->ppsThis;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RESMAN_CONTEXT),
+ ctx, NULL);
+
+ VALIDATERESLIST();
+
+ PRINT_RESLIST(gpsResList, ctx, IMG_FALSE);
+
+ RELEASE_SYNC_OBJ;
+}
+
+struct RESMAN_ITEM *ResManRegisterRes(struct RESMAN_CONTEXT *psResManContext,
+ u32 ui32ResType, void *pvParam,
+ u32 ui32Param,
+ enum PVRSRV_ERROR (*pfnFreeResource)
+ (void *pvParam, u32 ui32Param))
+{
+ struct RESMAN_ITEM *psNewResItem;
+
+ PVR_ASSERT(psResManContext != NULL);
+ PVR_ASSERT(ui32ResType != 0);
+
+ if (psResManContext == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "ResManRegisterRes: "
+ "invalid parameter - psResManContext");
+ return (struct RESMAN_ITEM *)NULL;
+ }
+
+ ACQUIRE_SYNC_OBJ;
+
+ VALIDATERESLIST();
+
+ PVR_DPF(PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
+ "Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
+ "FreeFunc %08X",
+ psResManContext, ui32ResType, (u32) pvParam,
+ ui32Param, pfnFreeResource);
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct RESMAN_ITEM), (void **) &psNewResItem,
+ NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "ResManRegisterRes: "
+ "ERROR allocating new resource item");
+
+ RELEASE_SYNC_OBJ;
+
+ return (struct RESMAN_ITEM *)NULL;
+ }
+
+#ifdef CONFIG_PVR_DEBUG
+ psNewResItem->ui32Signature = RESMAN_SIGNATURE;
+#endif
+ psNewResItem->ui32ResType = ui32ResType;
+ psNewResItem->pvParam = pvParam;
+ psNewResItem->ui32Param = ui32Param;
+ psNewResItem->pfnFreeResource = pfnFreeResource;
+ psNewResItem->ui32Flags = 0;
+
+ psNewResItem->ppsThis = &psResManContext->psResItemList;
+ psNewResItem->psNext = psResManContext->psResItemList;
+ psResManContext->psResItemList = psNewResItem;
+ if (psNewResItem->psNext)
+ psNewResItem->psNext->ppsThis = &psNewResItem->psNext;
+
+ VALIDATERESLIST();
+
+ RELEASE_SYNC_OBJ;
+
+ return psNewResItem;
+}
+
+void ResManFreeResByPtr(struct RESMAN_ITEM *psResItem)
+{
+ BUG_ON(!psResItem);
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "ResManFreeResByPtr: freeing resource at %08X", psResItem);
+
+ ACQUIRE_SYNC_OBJ;
+
+ VALIDATERESLIST();
+
+ FreeResourceByPtr(psResItem, IMG_TRUE);
+
+ VALIDATERESLIST();
+
+ RELEASE_SYNC_OBJ;
+}
+
+void ResManFreeResByCriteria(struct RESMAN_CONTEXT *psResManContext,
+ u32 ui32SearchCriteria, u32 ui32ResType,
+ void *pvParam, u32 ui32Param)
+{
+ PVR_ASSERT(psResManContext != NULL);
+
+ ACQUIRE_SYNC_OBJ;
+
+ VALIDATERESLIST();
+
+ PVR_DPF(PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
+ "Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
+ psResManContext, ui32SearchCriteria, ui32ResType,
+ (u32) pvParam, ui32Param);
+
+ (void)FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
+ ui32ResType, pvParam, ui32Param,
+ IMG_TRUE);
+
+ VALIDATERESLIST();
+
+ RELEASE_SYNC_OBJ;
+}
+
+enum PVRSRV_ERROR ResManDissociateRes(struct RESMAN_ITEM *psResItem,
+ struct RESMAN_CONTEXT *psNewResManContext)
+{
+ PVR_ASSERT(psResItem != NULL);
+
+ if (psResItem == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "ResManDissociateRes: invalid parameter - psResItem");
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#ifdef CONFIG_PVR_DEBUG
+ PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ if (psNewResManContext != NULL) {
+ if (psResItem->psNext)
+ psResItem->psNext->ppsThis = psResItem->ppsThis;
+ *psResItem->ppsThis = psResItem->psNext;
+
+ psResItem->ppsThis = &psNewResManContext->psResItemList;
+ psResItem->psNext = psNewResManContext->psResItemList;
+ psNewResManContext->psResItemList = psResItem;
+ if (psResItem->psNext)
+ psResItem->psNext->ppsThis = &psResItem->psNext;
+ } else {
+ FreeResourceByPtr(psResItem, IMG_FALSE);
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR ResManFindResourceByPtr(
+ struct RESMAN_CONTEXT *psResManContext,
+ struct RESMAN_ITEM *psItem)
+{
+ struct RESMAN_ITEM *psCurItem;
+
+ PVR_ASSERT(psResManContext != NULL);
+ PVR_ASSERT(psItem != NULL);
+
+ if ((psItem == NULL) || (psResManContext == NULL)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "ResManFindResourceByPtr: invalid parameter");
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+#ifdef CONFIG_PVR_DEBUG
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+#endif
+
+ ACQUIRE_SYNC_OBJ;
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ psItem, psItem->psNext);
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ psResManContext,
+ psItem->ui32ResType, (u32) psItem->pvParam,
+ psItem->ui32Param, psItem->pfnFreeResource,
+ psItem->ui32Flags);
+
+ psCurItem = psResManContext->psResItemList;
+
+ while (psCurItem != NULL) {
+ if (psCurItem != psItem) {
+ psCurItem = psCurItem->psNext;
+ } else {
+ RELEASE_SYNC_OBJ;
+ return PVRSRV_OK;
+ }
+ }
+
+ RELEASE_SYNC_OBJ;
+
+ return PVRSRV_ERROR_NOT_OWNER;
+}
+
+static void FreeResourceByPtr(struct RESMAN_ITEM *psItem,
+ IMG_BOOL bExecuteCallback)
+{
+ PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
+ psItem, psItem->psNext);
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
+ "Param 0x%x, FnCall %08X, Flags 0x%x",
+ psItem->ui32ResType, (u32) psItem->pvParam,
+ psItem->ui32Param, psItem->pfnFreeResource,
+ psItem->ui32Flags);
+
+ if (psItem->psNext)
+ psItem->psNext->ppsThis = psItem->ppsThis;
+ *psItem->ppsThis = psItem->psNext;
+
+ RELEASE_SYNC_OBJ;
+
+ if (bExecuteCallback &&
+ psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param) !=
+ PVRSRV_OK)
+ PVR_DPF(PVR_DBG_ERROR, "FreeResourceByPtr: "
+ "ERROR calling FreeResource function");
+
+ ACQUIRE_SYNC_OBJ;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct RESMAN_ITEM), psItem,
+ NULL);
+}
+
+static struct RESMAN_ITEM *find_res_by_crit(struct RESMAN_CONTEXT *res_ctx,
+ u32 crit, u32 res_type,
+ void *ppar, u32 upar)
+{
+ struct RESMAN_ITEM *item;
+
+ for (item = res_ctx->psResItemList; item; item = item->psNext) {
+ if ((crit & RESMAN_CRITERIA_RESTYPE) &&
+ item->ui32ResType != res_type)
+ continue;
+ else if ((crit & RESMAN_CRITERIA_PVOID_PARAM) &&
+ item->pvParam != ppar)
+ continue;
+ else if ((crit & RESMAN_CRITERIA_UI32_PARAM) &&
+ item->ui32Param != upar)
+ continue;
+
+ break;
+ }
+
+ return item;
+}
+
+struct RESMAN_CONTEXT *pvr_get_resman_ctx(void *resource)
+{
+ struct RESMAN_CONTEXT *ctx;
+
+ for (ctx = gpsResList->psContextList; ctx; ctx = ctx->psNext) {
+ struct RESMAN_ITEM *item;
+
+ item = find_res_by_crit(ctx, RESMAN_CRITERIA_PVOID_PARAM,
+ 0, resource, 0);
+ if (item)
+ return ctx;
+ }
+ return NULL;
+}
+
+struct PVRSRV_PER_PROCESS_DATA *pvr_get_proc_by_ctx(struct RESMAN_CONTEXT *ctx)
+{
+ return ctx->psPerProc;
+}
+
+static int FreeResourceByCriteria(struct RESMAN_CONTEXT *psResManContext,
+ u32 ui32SearchCriteria, u32 ui32ResType,
+ void *pvParam, u32 ui32Param,
+ IMG_BOOL bExecuteCallback)
+{
+ struct RESMAN_ITEM *item;
+ int freed = 0;
+
+ do {
+ item = find_res_by_crit(psResManContext,
+ ui32SearchCriteria, ui32ResType,
+ pvParam, ui32Param);
+ if (item) {
+ FreeResourceByPtr(item, bExecuteCallback);
+ freed++;
+ }
+ } while (item);
+
+ return freed;
+}
+
+#ifdef CONFIG_PVR_DEBUG_EXTRA
+static void ValidateResList(struct RESMAN_LIST *psResList)
+{
+ struct RESMAN_ITEM *psCurItem, **ppsThisItem;
+ struct RESMAN_CONTEXT *psCurContext, **ppsThisContext;
+
+ if (psResList == NULL) {
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "ValidateResList: resman not initialised yet");
+ return;
+ }
+
+ psCurContext = psResList->psContextList;
+ ppsThisContext = &psResList->psContextList;
+
+ while (psCurContext != NULL) {
+ PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
+ if (psCurContext->ppsThis != ppsThisContext) {
+ PVR_DPF(PVR_DBG_WARNING, "psCC=%08X "
+ "psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
+ psCurContext, psCurContext->ppsThis,
+ psCurContext->psNext, ppsThisContext);
+ PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
+ }
+
+ psCurItem = psCurContext->psResItemList;
+ ppsThisItem = &psCurContext->psResItemList;
+ while (psCurItem != NULL) {
+ PVR_ASSERT(psCurItem->ui32Signature ==
+ RESMAN_SIGNATURE);
+ if (psCurItem->ppsThis != ppsThisItem) {
+ PVR_DPF(PVR_DBG_WARNING, "psCurItem=%08X "
+ "psCurItem->ppsThis=%08X "
+ "psCurItem->psNext=%08X "
+ "ppsThisItem=%08X",
+ psCurItem, psCurItem->ppsThis,
+ psCurItem->psNext, ppsThisItem);
+ PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
+ }
+
+ ppsThisItem = &psCurItem->psNext;
+ psCurItem = psCurItem->psNext;
+ }
+
+ ppsThisContext = &psCurContext->psNext;
+ psCurContext = psCurContext->psNext;
+ }
+}
+#endif
diff --git a/drivers/gpu/pvr/resman.h b/drivers/gpu/pvr/resman.h
new file mode 100644
index 00000000000..f9a28f35315
--- /dev/null
+++ b/drivers/gpu/pvr/resman.h
@@ -0,0 +1,95 @@
+/**********************************************************************
+ *
+ * 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 __RESMAN_H__
+#define __RESMAN_H__
+
+enum {
+ RESMAN_TYPE_SHARED_PB_DESC = 1,
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ RESMAN_TYPE_HW_2D_CONTEXT,
+ RESMAN_TYPE_TRANSFER_CONTEXT,
+
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN,
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+
+ RESMAN_TYPE_BUFFERCLASS_DEVICE,
+
+ RESMAN_TYPE_OS_USERMODE_MAPPING,
+
+ RESMAN_TYPE_DEVICEMEM_CONTEXT,
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_MAPPING,
+ RESMAN_TYPE_DEVICEMEM_WRAP,
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION,
+ RESMAN_TYPE_EVENT_OBJECT,
+ RESMAN_TYPE_SHARED_MEM_INFO,
+
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION
+};
+
+#define RESMAN_CRITERIA_ALL 0x00000000
+#define RESMAN_CRITERIA_RESTYPE 0x00000001
+#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002
+#define RESMAN_CRITERIA_UI32_PARAM 0x00000004
+
+struct RESMAN_ITEM;
+struct RESMAN_CONTEXT;
+
+enum PVRSRV_ERROR ResManInit(void);
+void ResManDeInit(void);
+
+struct RESMAN_ITEM *ResManRegisterRes(struct RESMAN_CONTEXT *hResManContext,
+ u32 ui32ResType, void *pvParam,
+ u32 ui32Param,
+ enum PVRSRV_ERROR (*pfnFreeResource)
+ (void *pvParam, u32 ui32Param));
+
+void ResManFreeResByPtr(struct RESMAN_ITEM *psResItem);
+
+void ResManFreeResByCriteria(struct RESMAN_CONTEXT *hResManContext,
+ u32 ui32SearchCriteria, u32 ui32ResType, void *pvParam,
+ u32 ui32Param);
+
+enum PVRSRV_ERROR ResManDissociateRes(struct RESMAN_ITEM *psResItem,
+ struct RESMAN_CONTEXT
+ *psNewResManContext);
+
+enum PVRSRV_ERROR ResManFindResourceByPtr(struct RESMAN_CONTEXT *hResManContext,
+ struct RESMAN_ITEM *psItem);
+
+struct RESMAN_CONTEXT *pvr_get_resman_ctx(void *resource);
+struct PVRSRV_PER_PROCESS_DATA *pvr_get_proc_by_ctx(struct RESMAN_CONTEXT *ctx);
+
+enum PVRSRV_ERROR PVRSRVResManConnect(void *hPerProc,
+ struct RESMAN_CONTEXT **phResManContext);
+
+void PVRSRVResManDisconnect(struct RESMAN_CONTEXT *hResManContext,
+ IMG_BOOL bKernelContext);
+
+#endif
diff --git a/drivers/gpu/pvr/services.h b/drivers/gpu/pvr/services.h
new file mode 100644
index 00000000000..33d4931317d
--- /dev/null
+++ b/drivers/gpu/pvr/services.h
@@ -0,0 +1,237 @@
+/**********************************************************************
+ *
+ * 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 __SERVICES_H__
+#define __SERVICES_H__
+
+
+#include "img_defs.h"
+#include "servicesext.h"
+#include "pdumpdefs.h"
+
+struct SYS_DATA;
+
+#define PVRSRV_4K_PAGE_SIZE 4096UL
+
+#define PVRSRV_MAX_CMD_SIZE 1024
+
+#define PVRSRV_MAX_DEVICES 16
+
+#define EVENTOBJNAME_MAXLENGTH 50
+
+#define PVRSRV_MEM_READ (1UL<<0)
+#define PVRSRV_MEM_WRITE (1UL<<1)
+#define PVRSRV_MEM_CACHE_CONSISTENT (1UL<<2)
+#define PVRSRV_MEM_NO_SYNCOBJ (1UL<<3)
+#define PVRSRV_MEM_INTERLEAVED (1UL<<4)
+#define PVRSRV_MEM_DUMMY (1UL<<5)
+#define PVRSRV_MEM_EDM_PROTECT (1UL<<6)
+#define PVRSRV_MEM_ZERO (1UL<<7)
+#define PVRSRV_MEM_USER_SUPPLIED_DEVVADDR (1UL<<8)
+#define PVRSRV_MEM_RAM_BACKED_ALLOCATION (1UL<<9)
+#define PVRSRV_MEM_NO_RESMAN (1UL<<10)
+#define PVRSRV_MEM_EXPORTED (1UL<<11)
+
+#define PVRSRV_HAP_CACHED (1UL<<12)
+#define PVRSRV_HAP_UNCACHED (1UL<<13)
+#define PVRSRV_HAP_WRITECOMBINE (1UL<<14)
+#define PVRSRV_HAP_CACHETYPE_MASK (PVRSRV_HAP_CACHED | \
+ PVRSRV_HAP_UNCACHED | \
+ PVRSRV_HAP_WRITECOMBINE)
+#define PVRSRV_HAP_KERNEL_ONLY (1UL<<15)
+#define PVRSRV_HAP_SINGLE_PROCESS (1UL<<16)
+#define PVRSRV_HAP_MULTI_PROCESS (1UL<<17)
+#define PVRSRV_HAP_FROM_EXISTING_PROCESS (1UL<<18)
+#define PVRSRV_HAP_NO_CPU_VIRTUAL (1UL<<19)
+#define PVRSRV_HAP_MAPTYPE_MASK (PVRSRV_HAP_KERNEL_ONLY | \
+ PVRSRV_HAP_SINGLE_PROCESS | \
+ PVRSRV_HAP_MULTI_PROCESS | \
+ PVRSRV_HAP_FROM_EXISTING_PROCESS | \
+ PVRSRV_HAP_NO_CPU_VIRTUAL)
+#define PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT 24
+
+#define PVRSRV_MAP_NOUSERVIRTUAL (1UL << 27)
+
+#define PVRSRV_NO_CONTEXT_LOSS 0
+#define PVRSRV_SEVERE_LOSS_OF_CONTEXT 1
+#define PVRSRV_PRE_STATE_CHANGE_MASK 0x80
+
+#define PVRSRV_DEFAULT_DEV_COOKIE 1
+
+#define PVRSRV_MISC_INFO_TIMER_PRESENT (1UL << 0)
+#define PVRSRV_MISC_INFO_CLOCKGATE_PRESENT (1UL << 1)
+#define PVRSRV_MISC_INFO_MEMSTATS_PRESENT (1UL << 2)
+#define PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT (1UL << 3)
+#define PVRSRV_MISC_INFO_DDKVERSION_PRESENT (1UL << 4)
+
+#define PVRSRV_PDUMP_MAX_FILENAME_SIZE 20
+#define PVRSRV_PDUMP_MAX_COMMENT_SIZE 200
+
+#define PVRSRV_CHANGEDEVMEM_ATTRIBS_CACHECOHERENT 0x00000001
+
+#define PVRSRV_MAPEXTMEMORY_FLAGS_ALTERNATEVA 0x00000001
+#define PVRSRV_MAPEXTMEMORY_FLAGS_PHYSCONTIG 0x00000002
+
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WOP_INC 0x00000001
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_ROP_INC 0x00000002
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_WOC_INC 0x00000004
+#define PVRSRV_MODIFYSYNCOPS_FLAGS_ROC_INC 0x00000008
+
+enum PVRSRV_DEVICE_TYPE {
+ PVRSRV_DEVICE_TYPE_UNKNOWN = 0,
+ PVRSRV_DEVICE_TYPE_MBX1 = 1,
+ PVRSRV_DEVICE_TYPE_MBX1_LITE = 2,
+
+ PVRSRV_DEVICE_TYPE_M24VA = 3,
+ PVRSRV_DEVICE_TYPE_MVDA2 = 4,
+ PVRSRV_DEVICE_TYPE_MVED1 = 5,
+ PVRSRV_DEVICE_TYPE_MSVDX = 6,
+
+ PVRSRV_DEVICE_TYPE_SGX = 7,
+
+ PVRSRV_DEVICE_TYPE_VGX = 8,
+
+ PVRSRV_DEVICE_TYPE_EXT = 9,
+
+ PVRSRV_DEVICE_TYPE_LAST = 9,
+
+ PVRSRV_DEVICE_TYPE_FORCE_I32 = 0x7fffffff
+};
+
+#define HEAP_ID(_dev_ , _dev_heap_idx_) \
+ (((_dev_) << 24) | ((_dev_heap_idx_) & ((1 << 24) - 1)))
+
+#define HEAP_IDX(_heap_id_) \
+ ((_heap_id_) & ((1 << 24) - 1))
+
+#define HEAP_DEV(_heap_id_) \
+ ((_heap_id_) >> 24)
+
+#define PVRSRV_UNDEFINED_HEAP_ID (~0LU)
+
+enum IMG_MODULE_ID {
+ IMG_EGL = 0x00000001,
+ IMG_OPENGLES1 = 0x00000002,
+ IMG_OPENGLES2 = 0x00000003,
+ IMG_D3DM = 0x00000004,
+ IMG_SRV_UM = 0x00000005,
+ IMG_OPENVG = 0x00000006,
+ IMG_SRVCLIENT = 0x00000007,
+ IMG_VISTAKMD = 0x00000008,
+ IMG_VISTA3DNODE = 0x00000009,
+ IMG_VISTAMVIDEONODE = 0x0000000A,
+ IMG_VISTAVPBNODE = 0x0000000B,
+ IMG_OPENGL = 0x0000000C,
+ IMG_D3D = 0x0000000D
+};
+
+struct PVRSRV_CONNECTION {
+ void *hServices;
+ u32 ui32ProcessID;
+};
+
+struct PVRSRV_DEV_DATA {
+ struct PVRSRV_CONNECTION sConnection;
+ void *hDevCookie;
+};
+
+struct PVRSRV_HWREG {
+ u32 ui32RegAddr;
+ u32 ui32RegVal;
+};
+
+struct PVRSRV_MEMBLK {
+ struct IMG_DEV_VIRTADDR sDevVirtAddr;
+ void *hOSMemHandle;
+ void *hOSWrapMem;
+ void *hBuffer;
+ void *hResItem;
+ struct IMG_SYS_PHYADDR *psIntSysPAddr;
+};
+
+struct PVRSRV_KERNEL_MEM_INFO;
+
+struct PVRSRV_CLIENT_MEM_INFO {
+ void *pvLinAddr;
+ void *pvLinAddrKM;
+ struct IMG_DEV_VIRTADDR sDevVAddr;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+ u32 ui32Flags;
+ u32 ui32ClientFlags;
+ u32 ui32AllocSize;
+ struct PVRSRV_CLIENT_SYNC_INFO *psClientSyncInfo;
+ void *hMappingInfo;
+ void *hKernelMemInfo;
+ void *hResItem;
+ struct PVRSRV_CLIENT_MEM_INFO *psNext;
+};
+
+#define PVRSRV_MAX_CLIENT_HEAPS (32)
+struct PVRSRV_HEAP_INFO {
+ u32 ui32HeapID;
+ void *hDevMemHeap;
+ struct IMG_DEV_VIRTADDR sDevVAddrBase;
+ u32 ui32HeapByteSize;
+ u32 ui32Attribs;
+};
+
+struct PVRSRV_DEVICE_IDENTIFIER {
+ enum PVRSRV_DEVICE_TYPE eDeviceType;
+ enum PVRSRV_DEVICE_CLASS eDeviceClass;
+ u32 ui32DeviceIndex;
+
+};
+
+struct PVRSRV_EVENTOBJECT {
+ char szName[EVENTOBJNAME_MAXLENGTH];
+ void *hOSEventKM;
+};
+
+struct PVRSRV_MISC_INFO {
+ u32 ui32StateRequest;
+ u32 ui32StatePresent;
+
+ void *pvSOCTimerRegisterKM;
+ void *pvSOCTimerRegisterUM;
+ void *hSOCTimerRegisterOSMemHandle;
+ void *hSOCTimerRegisterMappingInfo;
+
+ void *pvSOCClockGateRegs;
+ u32 ui32SOCClockGateRegsSize;
+
+ char *pszMemoryStr;
+ u32 ui32MemoryStrLen;
+
+ struct PVRSRV_EVENTOBJECT sGlobalEventObject;
+ void *hOSGlobalEvent;
+
+ u32 aui32DDKVersion[4];
+};
+
+enum PVRSRV_ERROR AllocateDeviceID(struct SYS_DATA *psSysData, u32 *pui32DevID);
+enum PVRSRV_ERROR FreeDeviceID(struct SYS_DATA *psSysData, u32 ui32DevID);
+
+#endif
diff --git a/drivers/gpu/pvr/services_headers.h b/drivers/gpu/pvr/services_headers.h
new file mode 100644
index 00000000000..d443faef645
--- /dev/null
+++ b/drivers/gpu/pvr/services_headers.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 SERVICES_HEADERS_H
+#define SERVICES_HEADERS_H
+
+#include "img_defs.h"
+#include "services.h"
+#include "servicesint.h"
+#include "power.h"
+#include "resman.h"
+#include "queue.h"
+#include "srvkm.h"
+#include "kerneldisplay.h"
+#include "syscommon.h"
+#include "pvr_debug.h"
+#include "osfunc.h"
+
+#endif
diff --git a/drivers/gpu/pvr/servicesext.h b/drivers/gpu/pvr/servicesext.h
new file mode 100644
index 00000000000..3a1cb43b286
--- /dev/null
+++ b/drivers/gpu/pvr/servicesext.h
@@ -0,0 +1,435 @@
+/**********************************************************************
+ *
+ * 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(__SERVICESEXT_H__)
+#define __SERVICESEXT_H__
+
+#include "img_types.h"
+
+#define PVRSRV_LOCKFLG_READONLY 1
+
+enum PVRSRV_ERROR {
+ PVRSRV_OK = 0,
+ PVRSRV_ERROR_GENERIC = 1,
+ PVRSRV_ERROR_OUT_OF_MEMORY = 2,
+ PVRSRV_ERROR_TOO_FEW_BUFFERS = 3,
+ PVRSRV_ERROR_SYMBOL_NOT_FOUND = 4,
+ PVRSRV_ERROR_OUT_OF_HSPACE = 5,
+ PVRSRV_ERROR_INVALID_PARAMS = 6,
+ PVRSRV_ERROR_TILE_MAP_FAILED = 7,
+ PVRSRV_ERROR_INIT_FAILURE = 8,
+ PVRSRV_ERROR_CANT_REGISTER_CALLBACK = 9,
+ PVRSRV_ERROR_INVALID_DEVICE = 10,
+ PVRSRV_ERROR_NOT_OWNER = 11,
+ PVRSRV_ERROR_BAD_MAPPING = 12,
+ PVRSRV_ERROR_TIMEOUT = 13,
+ PVRSRV_ERROR_NO_PRIMARY = 14,
+ PVRSRV_ERROR_FLIP_CHAIN_EXISTS = 15,
+ PVRSRV_ERROR_CANNOT_ACQUIRE_SYSDATA = 16,
+ PVRSRV_ERROR_SCENE_INVALID = 17,
+ PVRSRV_ERROR_STREAM_ERROR = 18,
+ PVRSRV_ERROR_INVALID_INTERRUPT = 19,
+ PVRSRV_ERROR_FAILED_DEPENDENCIES = 20,
+ PVRSRV_ERROR_CMD_NOT_PROCESSED = 21,
+ PVRSRV_ERROR_CMD_TOO_BIG = 22,
+ PVRSRV_ERROR_DEVICE_REGISTER_FAILED = 23,
+ PVRSRV_ERROR_FIFO_SPACE = 24,
+ PVRSRV_ERROR_TA_RECOVERY = 25,
+ PVRSRV_ERROR_INDOSORLOWPOWER = 26,
+ PVRSRV_ERROR_TOOMANYBUFFERS = 27,
+ PVRSRV_ERROR_NOT_SUPPORTED = 28,
+ PVRSRV_ERROR_PROCESSING_BLOCKED = 29,
+
+ PVRSRV_ERROR_CANNOT_FLUSH_QUEUE = 31,
+ PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE = 32,
+ PVRSRV_ERROR_CANNOT_GET_RENDERDETAILS = 33,
+ PVRSRV_ERROR_RETRY = 34,
+
+ PVRSRV_ERROR_DDK_VERSION_MISMATCH = 35,
+ PVRSRV_ERROR_BUILD_MISMATCH = 36,
+
+ PVRSRV_ERROR_FORCE_I32 = 0x7fffffff
+};
+
+enum PVRSRV_DEVICE_CLASS {
+ PVRSRV_DEVICE_CLASS_3D = 0,
+ PVRSRV_DEVICE_CLASS_DISPLAY = 1,
+ PVRSRV_DEVICE_CLASS_BUFFER = 2,
+ PVRSRV_DEVICE_CLASS_VIDEO = 3,
+
+ PVRSRV_DEVICE_CLASS_FORCE_I32 = 0x7fffffff
+};
+
+enum PVR_POWER_STATE {
+ PVRSRV_POWER_Unspecified = -1,
+ PVRSRV_POWER_STATE_D0 = 0,
+ PVRSRV_POWER_STATE_D1 = 1,
+ PVRSRV_POWER_STATE_D2 = 2,
+ PVRSRV_POWER_STATE_D3 = 3,
+ PVRSRV_POWER_STATE_D4 = 4,
+
+ PVRSRV_POWER_STATE_FORCE_I32 = 0x7fffffff
+};
+
+enum PVRSRV_PIXEL_FORMAT {
+ PVRSRV_PIXEL_FORMAT_UNKNOWN = 0,
+ PVRSRV_PIXEL_FORMAT_RGB565 = 1,
+ PVRSRV_PIXEL_FORMAT_RGB555 = 2,
+ PVRSRV_PIXEL_FORMAT_RGB888 = 3,
+ PVRSRV_PIXEL_FORMAT_BGR888 = 4,
+ PVRSRV_PIXEL_FORMAT_GREY_SCALE = 8,
+ PVRSRV_PIXEL_FORMAT_PAL12 = 13,
+ PVRSRV_PIXEL_FORMAT_PAL8 = 14,
+ PVRSRV_PIXEL_FORMAT_PAL4 = 15,
+ PVRSRV_PIXEL_FORMAT_PAL2 = 16,
+ PVRSRV_PIXEL_FORMAT_PAL1 = 17,
+ PVRSRV_PIXEL_FORMAT_ARGB1555 = 18,
+ PVRSRV_PIXEL_FORMAT_ARGB4444 = 19,
+ PVRSRV_PIXEL_FORMAT_ARGB8888 = 20,
+ PVRSRV_PIXEL_FORMAT_ABGR8888 = 21,
+ PVRSRV_PIXEL_FORMAT_YV12 = 22,
+ PVRSRV_PIXEL_FORMAT_I420 = 23,
+ PVRSRV_PIXEL_FORMAT_IMC2 = 25,
+
+ PVRSRV_PIXEL_FORMAT_XRGB8888,
+ PVRSRV_PIXEL_FORMAT_XBGR8888,
+ PVRSRV_PIXEL_FORMAT_XRGB4444,
+ PVRSRV_PIXEL_FORMAT_ARGB8332,
+ PVRSRV_PIXEL_FORMAT_A2RGB10,
+ PVRSRV_PIXEL_FORMAT_A2BGR10,
+ PVRSRV_PIXEL_FORMAT_P8,
+ PVRSRV_PIXEL_FORMAT_L8,
+ PVRSRV_PIXEL_FORMAT_A8L8,
+ PVRSRV_PIXEL_FORMAT_A4L4,
+ PVRSRV_PIXEL_FORMAT_L16,
+ PVRSRV_PIXEL_FORMAT_L6V5U5,
+ PVRSRV_PIXEL_FORMAT_V8U8,
+ PVRSRV_PIXEL_FORMAT_V16U16,
+ PVRSRV_PIXEL_FORMAT_QWVU8888,
+ PVRSRV_PIXEL_FORMAT_XLVU8888,
+ PVRSRV_PIXEL_FORMAT_QWVU16,
+ PVRSRV_PIXEL_FORMAT_D16,
+ PVRSRV_PIXEL_FORMAT_D24S8,
+ PVRSRV_PIXEL_FORMAT_D24X8,
+
+ PVRSRV_PIXEL_FORMAT_ABGR16,
+ PVRSRV_PIXEL_FORMAT_ABGR16F,
+ PVRSRV_PIXEL_FORMAT_ABGR32,
+ PVRSRV_PIXEL_FORMAT_ABGR32F,
+ PVRSRV_PIXEL_FORMAT_B10GR11,
+ PVRSRV_PIXEL_FORMAT_GR88,
+ PVRSRV_PIXEL_FORMAT_BGR32,
+ PVRSRV_PIXEL_FORMAT_GR32,
+ PVRSRV_PIXEL_FORMAT_E5BGR9,
+
+ PVRSRV_PIXEL_FORMAT_DXT1,
+ PVRSRV_PIXEL_FORMAT_DXT23,
+ PVRSRV_PIXEL_FORMAT_DXT45,
+
+ PVRSRV_PIXEL_FORMAT_R8G8_B8G8,
+ PVRSRV_PIXEL_FORMAT_G8R8_G8B8,
+
+ PVRSRV_PIXEL_FORMAT_NV11,
+ PVRSRV_PIXEL_FORMAT_NV12,
+
+ PVRSRV_PIXEL_FORMAT_YUY2,
+ PVRSRV_PIXEL_FORMAT_YUV420,
+ PVRSRV_PIXEL_FORMAT_YUV444,
+ PVRSRV_PIXEL_FORMAT_VUY444,
+ PVRSRV_PIXEL_FORMAT_YUYV,
+ PVRSRV_PIXEL_FORMAT_YVYU,
+ PVRSRV_PIXEL_FORMAT_UYVY,
+ PVRSRV_PIXEL_FORMAT_VYUY,
+
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_UYVY,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YUYV,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_YVYU,
+ PVRSRV_PIXEL_FORMAT_FOURCC_ORG_VYUY,
+
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32F,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_UINT,
+ PVRSRV_PIXEL_FORMAT_A32B32G32R32_SINT,
+
+ PVRSRV_PIXEL_FORMAT_B32G32R32,
+ PVRSRV_PIXEL_FORMAT_B32G32R32F,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_UINT,
+ PVRSRV_PIXEL_FORMAT_B32G32R32_SINT,
+
+ PVRSRV_PIXEL_FORMAT_G32R32,
+ PVRSRV_PIXEL_FORMAT_G32R32F,
+ PVRSRV_PIXEL_FORMAT_G32R32_UINT,
+ PVRSRV_PIXEL_FORMAT_G32R32_SINT,
+
+ PVRSRV_PIXEL_FORMAT_D32F,
+ PVRSRV_PIXEL_FORMAT_R32,
+ PVRSRV_PIXEL_FORMAT_R32F,
+ PVRSRV_PIXEL_FORMAT_R32_UINT,
+ PVRSRV_PIXEL_FORMAT_R32_SINT,
+
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16F,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SINT,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_SNORM,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UINT,
+ PVRSRV_PIXEL_FORMAT_A16B16G16R16_UNORM,
+
+ PVRSRV_PIXEL_FORMAT_G16R16,
+ PVRSRV_PIXEL_FORMAT_G16R16F,
+ PVRSRV_PIXEL_FORMAT_G16R16_UINT,
+ PVRSRV_PIXEL_FORMAT_G16R16_UNORM,
+ PVRSRV_PIXEL_FORMAT_G16R16_SINT,
+ PVRSRV_PIXEL_FORMAT_G16R16_SNORM,
+
+ PVRSRV_PIXEL_FORMAT_R16,
+ PVRSRV_PIXEL_FORMAT_R16F,
+ PVRSRV_PIXEL_FORMAT_R16_UINT,
+ PVRSRV_PIXEL_FORMAT_R16_UNORM,
+ PVRSRV_PIXEL_FORMAT_R16_SINT,
+ PVRSRV_PIXEL_FORMAT_R16_SNORM,
+
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UINT,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_UNORM,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SINT,
+ PVRSRV_PIXEL_FORMAT_A8B8G8R8_SNORM,
+
+ PVRSRV_PIXEL_FORMAT_G8R8,
+ PVRSRV_PIXEL_FORMAT_G8R8_UINT,
+ PVRSRV_PIXEL_FORMAT_G8R8_UNORM,
+ PVRSRV_PIXEL_FORMAT_G8R8_SINT,
+ PVRSRV_PIXEL_FORMAT_G8R8_SNORM,
+
+ PVRSRV_PIXEL_FORMAT_A8,
+ PVRSRV_PIXEL_FORMAT_R8,
+ PVRSRV_PIXEL_FORMAT_R8_UINT,
+ PVRSRV_PIXEL_FORMAT_R8_UNORM,
+ PVRSRV_PIXEL_FORMAT_R8_SINT,
+ PVRSRV_PIXEL_FORMAT_R8_SNORM,
+
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UNORM,
+ PVRSRV_PIXEL_FORMAT_A2B10G10R10_UINT,
+
+ PVRSRV_PIXEL_FORMAT_B10G11R11,
+ PVRSRV_PIXEL_FORMAT_B10G11R11F,
+
+ PVRSRV_PIXEL_FORMAT_X24G8R32,
+ PVRSRV_PIXEL_FORMAT_G8R24,
+ PVRSRV_PIXEL_FORMAT_E5B9G9R9,
+ PVRSRV_PIXEL_FORMAT_R1,
+
+ PVRSRV_PIXEL_FORMAT_BC1,
+ PVRSRV_PIXEL_FORMAT_BC1_UNORM,
+ PVRSRV_PIXEL_FORMAT_BC1_SRGB,
+ PVRSRV_PIXEL_FORMAT_BC2,
+ PVRSRV_PIXEL_FORMAT_BC2_UNORM,
+ PVRSRV_PIXEL_FORMAT_BC2_SRGB,
+ PVRSRV_PIXEL_FORMAT_BC3,
+ PVRSRV_PIXEL_FORMAT_BC3_UNORM,
+ PVRSRV_PIXEL_FORMAT_BC3_SRGB,
+ PVRSRV_PIXEL_FORMAT_BC4,
+ PVRSRV_PIXEL_FORMAT_BC4_UNORM,
+ PVRSRV_PIXEL_FORMAT_BC4_SNORM,
+ PVRSRV_PIXEL_FORMAT_BC5,
+ PVRSRV_PIXEL_FORMAT_BC5_UNORM,
+ PVRSRV_PIXEL_FORMAT_BC5_SNORM,
+
+ PVRSRV_PIXEL_FORMAT_FORCE_I32 = 0x7fffffff,
+};
+
+enum PVRSRV_ALPHA_FORMAT {
+ PVRSRV_ALPHA_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_ALPHA_FORMAT_PRE = 0x00000001,
+ PVRSRV_ALPHA_FORMAT_NONPRE = 0x00000002,
+ PVRSRV_ALPHA_FORMAT_MASK = 0x0000000F,
+};
+
+enum PVRSRV_COLOURSPACE_FORMAT {
+ PVRSRV_COLOURSPACE_FORMAT_UNKNOWN = 0x00000000,
+ PVRSRV_COLOURSPACE_FORMAT_LINEAR = 0x00010000,
+ PVRSRV_COLOURSPACE_FORMAT_NONLINEAR = 0x00020000,
+ PVRSRV_COLOURSPACE_FORMAT_MASK = 0x000F0000,
+};
+
+enum PVRSRV_ROTATION {
+ PVRSRV_ROTATE_0 = 0,
+ PVRSRV_ROTATE_90 = 1,
+ PVRSRV_ROTATE_180 = 2,
+ PVRSRV_ROTATE_270 = 3,
+ PVRSRV_FLIP_Y
+};
+
+#define PVRSRV_CREATE_SWAPCHAIN_SHARED (1<<0)
+#define PVRSRV_CREATE_SWAPCHAIN_QUERY (1<<1)
+#define PVRSRV_CREATE_SWAPCHAIN_OEMOVERLAY (1<<2)
+
+struct PVRSRV_SYNC_DATA {
+
+ u32 ui32WriteOpsPending;
+ volatile u32 ui32WriteOpsComplete;
+
+ u32 ui32ReadOpsPending;
+ volatile u32 ui32ReadOpsComplete;
+
+ u32 ui32LastOpDumpVal;
+ u32 ui32LastReadOpDumpVal;
+
+};
+
+struct PVRSRV_CLIENT_SYNC_INFO {
+ struct PVRSRV_SYNC_DATA *psSyncData;
+ struct IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+ struct IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+ void *hMappingInfo;
+ void *hKernelSyncInfo;
+};
+
+struct PVRSRV_RESOURCE {
+ volatile u32 ui32Lock;
+ u32 ui32ID;
+};
+
+struct IMG_RECT {
+ s32 x0;
+ s32 y0;
+ s32 x1;
+ s32 y1;
+};
+
+struct IMG_RECT_16 {
+ s16 x0;
+ s16 y0;
+ s16 x1;
+ s16 y1;
+};
+
+struct DISPLAY_DIMS {
+ u32 ui32ByteStride;
+ u32 ui32Width;
+ u32 ui32Height;
+};
+
+struct DISPLAY_FORMAT {
+ enum PVRSRV_PIXEL_FORMAT pixelformat;
+};
+
+struct DISPLAY_SURF_ATTRIBUTES {
+ enum PVRSRV_PIXEL_FORMAT pixelformat;
+ struct DISPLAY_DIMS sDims;
+};
+
+struct DISPLAY_MODE_INFO {
+ enum PVRSRV_PIXEL_FORMAT pixelformat;
+ struct DISPLAY_DIMS sDims;
+ u32 ui32RefreshHZ;
+ u32 ui32OEMFlags;
+};
+
+#define MAX_DISPLAY_NAME_SIZE (50)
+
+struct DISPLAY_INFO {
+ u32 ui32MaxSwapChains;
+ u32 ui32MaxSwapChainBuffers;
+ u32 ui32MinSwapInterval;
+ u32 ui32MaxSwapInterval;
+ char szDisplayName[MAX_DISPLAY_NAME_SIZE];
+};
+
+struct ACCESS_INFO {
+ u32 ui32Size;
+ u32 ui32FBPhysBaseAddress;
+ u32 ui32FBMemAvailable;
+ u32 ui32SysPhysBaseAddress;
+ u32 ui32SysSize;
+ u32 ui32DevIRQ;
+};
+
+struct PVRSRV_CURSOR_SHAPE {
+ u16 ui16Width;
+ u16 ui16Height;
+ s16 i16XHot;
+ s16 i16YHot;
+
+ void *pvMask;
+ s16 i16MaskByteStride;
+
+ void *pvColour;
+ s16 i16ColourByteStride;
+ enum PVRSRV_PIXEL_FORMAT eColourPixelFormat;
+};
+
+#define PVRSRV_SET_CURSOR_VISIBILITY (1<<0)
+#define PVRSRV_SET_CURSOR_POSITION (1<<1)
+#define PVRSRV_SET_CURSOR_SHAPE (1<<2)
+#define PVRSRV_SET_CURSOR_ROTATION (1<<3)
+
+struct PVRSRV_CURSOR_INFO {
+ u32 ui32Flags;
+ IMG_BOOL bVisible;
+ s16 i16XPos;
+ s16 i16YPos;
+ struct PVRSRV_CURSOR_SHAPE sCursorShape;
+ u32 ui32Rotation;
+};
+
+struct PVRSRV_REGISTRY_INFO {
+ u32 ui32DevCookie;
+ char *pszKey;
+ char *pszValue;
+ char *pszBuf;
+ u32 ui32BufSize;
+};
+
+enum PVRSRV_ERROR PVRSRVReadRegistryString(
+ struct PVRSRV_REGISTRY_INFO *psRegInfo);
+enum PVRSRV_ERROR PVRSRVWriteRegistryString(
+ struct PVRSRV_REGISTRY_INFO *psRegInfo);
+
+#define PVRSRV_BC_FLAGS_YUVCSC_CONFORMANT_RANGE (0 << 0)
+#define PVRSRV_BC_FLAGS_YUVCSC_FULL_RANGE (1 << 0)
+
+#define PVRSRV_BC_FLAGS_YUVCSC_BT601 (0 << 1)
+#define PVRSRV_BC_FLAGS_YUVCSC_BT709 (1 << 1)
+
+struct BUFFER_INFO {
+ u32 ui32BufferCount;
+ u32 ui32BufferDeviceID;
+ enum PVRSRV_PIXEL_FORMAT pixelformat;
+ u32 ui32ByteStride;
+ u32 ui32Width;
+ u32 ui32Height;
+ u32 ui32Flags;
+};
+
+enum OVERLAY_DEINTERLACE_MODE {
+ WEAVE = 0x0,
+ BOB_ODD,
+ BOB_EVEN,
+ BOB_EVEN_NONINTERLEAVED
+};
+
+#endif
diff --git a/drivers/gpu/pvr/servicesint.h b/drivers/gpu/pvr/servicesint.h
new file mode 100644
index 00000000000..a81adff8f49
--- /dev/null
+++ b/drivers/gpu/pvr/servicesint.h
@@ -0,0 +1,181 @@
+/**********************************************************************
+ *
+ * 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(__SERVICESINT_H__)
+#define __SERVICESINT_H__
+
+
+#include "services.h"
+#include "sysinfo.h"
+
+#define HWREC_DEFAULT_TIMEOUT 500
+
+#define DRIVERNAME_MAXLENGTH 100
+
+struct PVRSRV_KERNEL_MEM_INFO {
+
+ void *pvLinAddrKM;
+ struct IMG_DEV_VIRTADDR sDevVAddr;
+ u32 ui32Flags;
+ u32 ui32AllocSize;
+ struct PVRSRV_MEMBLK sMemBlk;
+
+ void *pvSysBackupBuffer;
+
+ u32 ui32RefCount;
+
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+};
+
+struct PVRSRV_KERNEL_SYNC_INFO {
+ struct PVRSRV_SYNC_DATA *psSyncData;
+ struct IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+ struct IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+ struct PVRSRV_KERNEL_MEM_INFO *psSyncDataMemInfoKM;
+
+ /*
+ * This stores the physical address of the buffer that
+ * this syncobject manages (if provided)
+ */
+ struct IMG_SYS_PHYADDR phys_addr;
+ void *dev_cookie;
+ u32 refcount;
+};
+
+struct PVRSRV_DEVICE_SYNC_OBJECT {
+
+ u32 ui32ReadOpsPendingVal;
+ struct IMG_DEV_VIRTADDR sReadOpsCompleteDevVAddr;
+ u32 ui32WriteOpsPendingVal;
+ struct IMG_DEV_VIRTADDR sWriteOpsCompleteDevVAddr;
+};
+
+struct PVRSRV_SYNC_OBJECT {
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfoKM;
+ u32 ui32WriteOpsPending;
+ u32 ui32ReadOpsPending;
+};
+
+struct PVRSRV_COMMAND {
+ u32 ui32CmdSize;
+ u32 ui32DevIndex;
+ u32 CommandType;
+ u32 ui32DstSyncCount;
+ u32 ui32SrcSyncCount;
+ struct PVRSRV_SYNC_OBJECT *psDstSync;
+ struct PVRSRV_SYNC_OBJECT *psSrcSync;
+ u32 ui32DataSize;
+ u32 ui32ProcessID;
+ void *pvData;
+};
+
+struct PVRSRV_QUEUE_INFO {
+ void *pvLinQueueKM;
+ void *pvLinQueueUM;
+ volatile u32 ui32ReadOffset;
+ volatile u32 ui32WriteOffset;
+ u32 *pui32KickerAddrKM;
+ u32 *pui32KickerAddrUM;
+ u32 ui32QueueSize;
+
+ u32 ui32ProcessID;
+
+ void *hMemBlock[2];
+
+ struct PVRSRV_QUEUE_INFO *psNextKM;
+};
+
+struct PVRSRV_DEVICECLASS_BUFFER {
+ enum PVRSRV_ERROR (*pfnGetBufferAddr)(void *, void *,
+ struct IMG_SYS_PHYADDR **, u32 *,
+ void __iomem **, void **, IMG_BOOL *);
+ void *hDevMemContext;
+ void *hExtDevice;
+ void *hExtBuffer;
+ struct PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+};
+
+struct PVRSRV_CLIENT_DEVICECLASS_INFO {
+ void *hDeviceKM;
+ void *hServices;
+};
+
+static inline u32 PVRSRVGetWriteOpsPending(
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ u32 ui32WriteOpsPending;
+
+ if (bIsReadOp)
+ ui32WriteOpsPending =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ else
+ ui32WriteOpsPending =
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+ return ui32WriteOpsPending;
+}
+
+static inline u32 PVRSRVGetReadOpsPending(
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ u32 ui32ReadOpsPending;
+
+ if (bIsReadOp)
+ ui32ReadOpsPending =
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ else
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ return ui32ReadOpsPending;
+}
+
+enum PVRSRV_ERROR PVRSRVQueueCommand(void *hQueueInfo,
+ struct PVRSRV_COMMAND *psCommand);
+
+enum PVRSRV_ERROR PVRSRVGetMMUContextPDDevPAddr(
+ const struct PVRSRV_CONNECTION *psConnection,
+ void *hDevMemContext,
+ struct IMG_DEV_PHYADDR *sPDDevPAddr);
+
+enum PVRSRV_ERROR PVRSRVAllocSharedSysMem(
+ const struct PVRSRV_CONNECTION *psConnection,
+ u32 ui32Flags, u32 ui32Size,
+ struct PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+enum PVRSRV_ERROR PVRSRVFreeSharedSysMem(
+ const struct PVRSRV_CONNECTION *psConnection,
+ struct PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+enum PVRSRV_ERROR PVRSRVUnrefSharedSysMem(
+ const struct PVRSRV_CONNECTION *psConnection,
+ struct PVRSRV_CLIENT_MEM_INFO *psClientMemInfo);
+
+enum PVRSRV_ERROR PVRSRVMapMemInfoMem(
+ const struct PVRSRV_CONNECTION *psConnection,
+ void *hKernelMemInfo,
+ struct PVRSRV_CLIENT_MEM_INFO **ppsClientMemInfo);
+
+#endif
diff --git a/drivers/gpu/pvr/sgx530defs.h b/drivers/gpu/pvr/sgx530defs.h
new file mode 100644
index 00000000000..1a796eed27a
--- /dev/null
+++ b/drivers/gpu/pvr/sgx530defs.h
@@ -0,0 +1,471 @@
+/**********************************************************************
+ *
+ * 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 _SGX530DEFS_KM_H_
+#define _SGX530DEFS_KM_H_
+
+#define EUR_CR_CLKGATECTL 0x0000
+#define EUR_CR_CLKGATECTL_2D_CLKG_MASK 0x00000003
+#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT 0
+#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000030
+#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 4
+#define EUR_CR_CLKGATECTL_TSP_CLKG_MASK 0x00000300
+#define EUR_CR_CLKGATECTL_TSP_CLKG_SHIFT 8
+#define EUR_CR_CLKGATECTL_TA_CLKG_MASK 0x00003000
+#define EUR_CR_CLKGATECTL_TA_CLKG_SHIFT 12
+#define EUR_CR_CLKGATECTL_DPM_CLKG_MASK 0x00030000
+#define EUR_CR_CLKGATECTL_DPM_CLKG_SHIFT 16
+#define EUR_CR_CLKGATECTL_USE_CLKG_MASK 0x00300000
+#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT 20
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000
+#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+
+#define EUR_CR_CLKGATESTATUS 0x0004
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK 0x00000001
+#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT 0
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000010
+#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 4
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_MASK 0x00000100
+#define EUR_CR_CLKGATESTATUS_TSP_CLKS_SHIFT 8
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00001000
+#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 12
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_MASK 0x00010000
+#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK 0x00100000
+#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+
+#define EUR_CR_CLKGATECTLOVR 0x0008
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK 0x00000003
+#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT 0
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000030
+#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 4
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_MASK 0x00000300
+#define EUR_CR_CLKGATECTLOVR_TSP_CLKO_SHIFT 8
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x00003000
+#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 12
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_MASK 0x00030000
+#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK 0x00300000
+#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+
+#define EUR_CR_CORE_ID 0x0010
+#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFF
+#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
+#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000
+#define EUR_CR_CORE_ID_ID_SHIFT 16
+
+#define EUR_CR_CORE_REVISION 0x0014
+#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FF
+#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
+#define EUR_CR_CORE_REVISION_MINOR_MASK 0x0000FF00
+#define EUR_CR_CORE_REVISION_MINOR_SHIFT 8
+#define EUR_CR_CORE_REVISION_MAJOR_MASK 0x00FF0000
+#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
+#define EUR_CR_CORE_MAKE_REV(maj, min, maint) ( \
+ (((maj) << EUR_CR_CORE_REVISION_MAJOR_SHIFT) & \
+ EUR_CR_CORE_REVISION_MAJOR_MASK) | \
+ (((min) << EUR_CR_CORE_REVISION_MINOR_SHIFT) & \
+ EUR_CR_CORE_REVISION_MINOR_MASK) | \
+ (((maint) << EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT) & \
+ EUR_CR_CORE_REVISION_MAINTENANCE_MASK) \
+ )
+#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000
+#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+
+#define EUR_CR_DESIGNER_REV_FIELD1 0x0018
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFF
+#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+
+#define EUR_CR_DESIGNER_REV_FIELD2 0x001C
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFF
+#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+
+#define EUR_CR_SOFT_RESET 0x0080
+#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001
+#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
+#define EUR_CR_SOFT_RESET_TWOD_RESET_MASK 0x00000002
+#define EUR_CR_SOFT_RESET_TWOD_RESET_SHIFT 1
+#define EUR_CR_SOFT_RESET_DPM_RESET_MASK 0x00000004
+#define EUR_CR_SOFT_RESET_DPM_RESET_SHIFT 2
+#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00000008
+#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 3
+#define EUR_CR_SOFT_RESET_USE_RESET_MASK 0x00000010
+#define EUR_CR_SOFT_RESET_USE_RESET_SHIFT 4
+#define EUR_CR_SOFT_RESET_ISP_RESET_MASK 0x00000020
+#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
+#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000040
+#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 6
+
+#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_MASK 0x00000002
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001
+#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+
+#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_MASK 0x00000002
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001
+#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+
+#define EUR_CR_EVENT_STATUS2 0x0118
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_MASK 0x00000002
+#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001
+#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+
+#define EUR_CR_EVENT_STATUS 0x012C
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000
+#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_STATUS_TIMER_MASK 0x20000000
+#define EUR_CR_EVENT_STATUS_TIMER_SHIFT 29
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_MASK 0x10000000
+#define EUR_CR_EVENT_STATUS_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_MASK 0x08000000
+#define EUR_CR_EVENT_STATUS_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000
+#define EUR_CR_EVENT_STATUS_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_MASK 0x01000000
+#define EUR_CR_EVENT_STATUS_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_MASK 0x00800000
+#define EUR_CR_EVENT_STATUS_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_MASK 0x00400000
+#define EUR_CR_EVENT_STATUS_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_MASK 0x00200000
+#define EUR_CR_EVENT_STATUS_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_STATUS_OTPM_INV_MASK 0x00100000
+#define EUR_CR_EVENT_STATUS_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_MASK 0x00080000
+#define EUR_CR_EVENT_STATUS_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK 0x00040000
+#define EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_STATUS_ISP_HALT_MASK 0x00020000
+#define EUR_CR_EVENT_STATUS_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_MASK 0x00010000
+#define EUR_CR_EVENT_STATUS_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_MASK 0x00008000
+#define EUR_CR_EVENT_STATUS_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_STATUS_SW_EVENT_MASK 0x00004000
+#define EUR_CR_EVENT_STATUS_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_MASK 0x00002000
+#define EUR_CR_EVENT_STATUS_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_MASK 0x00001000
+#define EUR_CR_EVENT_STATUS_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_MASK 0x00000800
+#define EUR_CR_EVENT_STATUS_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_MASK 0x00000400
+#define EUR_CR_EVENT_STATUS_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_MASK 0x00000200
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_MASK 0x00000100
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_MASK 0x00000080
+#define EUR_CR_EVENT_STATUS_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_MASK 0x00000040
+#define EUR_CR_EVENT_STATUS_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_MASK 0x00000020
+#define EUR_CR_EVENT_STATUS_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_MASK 0x00000010
+#define EUR_CR_EVENT_STATUS_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_MASK 0x00000008
+#define EUR_CR_EVENT_STATUS_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002
+#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001
+#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+
+#define EUR_CR_EVENT_HOST_ENABLE 0x0130
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000
+#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_MASK 0x20000000
+#define EUR_CR_EVENT_HOST_ENABLE_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_MASK 0x10000000
+#define EUR_CR_EVENT_HOST_ENABLE_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_MASK 0x08000000
+#define EUR_CR_EVENT_HOST_ENABLE_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000
+#define EUR_CR_EVENT_HOST_ENABLE_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_MASK 0x01000000
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_MASK 0x00800000
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_MASK 0x00400000
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_MASK 0x00200000
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_MASK 0x00100000
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_MASK 0x00080000
+#define EUR_CR_EVENT_HOST_ENABLE_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_MASK 0x00040000
+#define EUR_CR_EVENT_HOST_ENABLE_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_MASK 0x00020000
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_MASK 0x00010000
+#define EUR_CR_EVENT_HOST_ENABLE_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_MASK 0x00008000
+#define EUR_CR_EVENT_HOST_ENABLE_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_MASK 0x00004000
+#define EUR_CR_EVENT_HOST_ENABLE_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_MASK 0x00002000
+#define EUR_CR_EVENT_HOST_ENABLE_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_MASK 0x00001000
+#define EUR_CR_EVENT_HOST_ENABLE_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_MASK 0x00000800
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_MASK 0x00000400
+#define EUR_CR_EVENT_HOST_ENABLE_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_MASK 0x00000200
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_MASK 0x00000100
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_MASK 0x00000080
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_MASK 0x00000040
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_MASK 0x00000020
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_MASK 0x00000010
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_MASK 0x00000008
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001
+#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+
+#define EUR_CR_EVENT_HOST_CLEAR 0x0134
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000
+#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_MASK 0x20000000
+#define EUR_CR_EVENT_HOST_CLEAR_TIMER_SHIFT 29
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_MASK 0x10000000
+#define EUR_CR_EVENT_HOST_CLEAR_TA_DPM_FAULT_SHIFT 28
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_MASK 0x08000000
+#define EUR_CR_EVENT_HOST_CLEAR_TWOD_COMPLETE_SHIFT 27
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_MASK 0x04000000
+#define EUR_CR_EVENT_HOST_CLEAR_MADD_CACHE_INVALCOMPLETE_SHIFT 26
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_MASK 0x02000000
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_ZLS_SHIFT 25
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_MASK 0x01000000
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_TA_MEM_FREE_SHIFT 24
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_MASK 0x00800000
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_END_TILE_SHIFT 23
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_MASK 0x00400000
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_INITEND_SHIFT 22
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_MASK 0x00200000
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_LOADED_SHIFT 21
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_MASK 0x00100000
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_INV_SHIFT 20
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_MASK 0x00080000
+#define EUR_CR_EVENT_HOST_CLEAR_OTPM_FLUSHED_SHIFT 19
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_MASK 0x00040000
+#define EUR_CR_EVENT_HOST_CLEAR_PIXELBE_END_RENDER_SHIFT 18
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_MASK 0x00020000
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_HALT_SHIFT 17
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_MASK 0x00010000
+#define EUR_CR_EVENT_HOST_CLEAR_ISP_VISIBILITY_FAIL_SHIFT 16
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_MASK 0x00008000
+#define EUR_CR_EVENT_HOST_CLEAR_BREAKPOINT_SHIFT 15
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK 0x00004000
+#define EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_SHIFT 14
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_MASK 0x00002000
+#define EUR_CR_EVENT_HOST_CLEAR_TA_FINISHED_SHIFT 13
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_MASK 0x00001000
+#define EUR_CR_EVENT_HOST_CLEAR_TA_TERMINATE_SHIFT 12
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_MASK 0x00000800
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_CLEAR_SHIFT 11
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_MASK 0x00000400
+#define EUR_CR_EVENT_HOST_CLEAR_TPC_FLUSH_SHIFT 10
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_MASK 0x00000200
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_CLEAR_SHIFT 9
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_MASK 0x00000100
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_LOAD_SHIFT 8
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_MASK 0x00000080
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_CONTROL_STORE_SHIFT 7
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_MASK 0x00000040
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_CLEAR_SHIFT 6
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_MASK 0x00000020
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_LOAD_SHIFT 5
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_MASK 0x00000010
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_STATE_STORE_SHIFT 4
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_MASK 0x00000008
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_REACHED_MEM_THRESH_SHIFT 3
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_MASK 0x00000004
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_GBL_SHIFT 2
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_MASK 0x00000002
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001
+#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+
+#define EUR_CR_PDS 0x0ABC
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_MASK 0x00000040
+#define EUR_CR_PDS_DOUT_TIMEOUT_DISABLE_SHIFT 6
+
+#define EUR_CR_PDS_EXEC_BASE 0x0AB8
+#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000
+#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+
+#define EUR_CR_EVENT_KICKER 0x0AC4
+#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0
+#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+
+#define EUR_CR_EVENT_KICK 0x0AC8
+#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001
+#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+
+#define EUR_CR_EVENT_TIMER 0x0ACC
+#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000
+#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
+#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFF
+#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+
+#define EUR_CR_PDS_INV0 0x0AD0
+#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001
+#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+
+#define EUR_CR_PDS_INV1 0x0AD4
+#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001
+#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+
+#define EUR_CR_PDS_INV2 0x0AD8
+#define EUR_CR_PDS_INV2_DSC_MASK 0x00000001
+#define EUR_CR_PDS_INV2_DSC_SHIFT 0
+
+#define EUR_CR_PDS_INV3 0x0ADC
+#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001
+#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+
+#define EUR_CR_PDS_INV_CSC 0x0AE0
+#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001
+#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+
+#define EUR_CR_PDS_PC_BASE 0x0B2C
+#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x3FFFFFFF
+#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+
+#define EUR_CR_BIF_CTRL 0x0C00
+#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001
+#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
+#define EUR_CR_BIF_CTRL_PAUSE_MASK 0x00000002
+#define EUR_CR_BIF_CTRL_PAUSE_SHIFT 1
+#define EUR_CR_BIF_CTRL_FLUSH_MASK 0x00000004
+#define EUR_CR_BIF_CTRL_FLUSH_SHIFT 2
+#define EUR_CR_BIF_CTRL_INVALDC_MASK 0x00000008
+#define EUR_CR_BIF_CTRL_INVALDC_SHIFT 3
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK 0x00000010
+#define EUR_CR_BIF_CTRL_CLEAR_FAULT_SHIFT 4
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_MASK 0x00000100
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_CACHE_SHIFT 8
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_MASK 0x00000200
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_VDM_SHIFT 9
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_MASK 0x00000400
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TE_SHIFT 10
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_MASK 0x00000800
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TWOD_SHIFT 11
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_MASK 0x00001000
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_PBE_SHIFT 12
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_MASK 0x00002000
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_TSPP_SHIFT 13
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_MASK 0x00004000
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000
+#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+
+#define EUR_CR_BIF_INT_STAT 0x0C04
+#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFF
+#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_MASK 0x00004000
+#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
+#define EUR_CR_BIF_FAULT 0x0C08
+#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000
+#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+
+#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000
+#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+
+#define EUR_CR_BIF_TWOD_REQ_BASE 0x0C88
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK 0x0FF00000
+#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+
+#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000
+#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+
+#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FF
+#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+
+#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000
+#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+
+#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000
+#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+
+#define EUR_CR_2D_BLIT_STATUS 0x0E04
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFF
+#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
+#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000
+#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+
+#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001
+#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MASK 0x0000000E
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_SHIFT 1
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_MASK 0x00000FF0
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000
+#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+
+#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFF
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_MASK 0x00FFF000
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000
+#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+
+#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
+#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFF
+#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
+#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000
+#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
+#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
+
+#endif
diff --git a/drivers/gpu/pvr/sgx_bridge.h b/drivers/gpu/pvr/sgx_bridge.h
new file mode 100644
index 00000000000..9b83616b920
--- /dev/null
+++ b/drivers/gpu/pvr/sgx_bridge.h
@@ -0,0 +1,397 @@
+/**********************************************************************
+ *
+ * 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(__SGX_BRIDGE_H__)
+#define __SGX_BRIDGE_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "pvr_bridge.h"
+
+#define PVRSRV_BRIDGE_SGX_CMD_BASE (PVRSRV_BRIDGE_LAST_NON_DEVICE_CMD+1)
+#define PVRSRV_BRIDGE_SGX_GETCLIENTINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+0)
+#define PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+1)
+#define PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+2)
+#define PVRSRV_BRIDGE_SGX_DOKICK \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+3)
+#define PVRSRV_BRIDGE_SGX_GETPHYSPAGEADDR \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+4)
+#define PVRSRV_BRIDGE_SGX_READREGISTRYDWORD \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+5)
+#define PVRSRV_BRIDGE_SGX_SCHEDULECOMMAND \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+6)
+
+#define PVRSRV_BRIDGE_SGX_2DQUERYBLTSCOMPLETE \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+9)
+
+#define PVRSRV_BRIDGE_SGX_GETMMUPDADDR \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+10)
+
+#define PVRSRV_BRIDGE_SGX_SUBMITTRANSFER \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+13)
+#define PVRSRV_BRIDGE_SGX_GETMISCINFO \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+14)
+#define PVRSRV_BRIDGE_SGXINFO_FOR_SRVINIT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+15)
+#define PVRSRV_BRIDGE_SGX_DEVINITPART2 \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+16)
+
+#define PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+17)
+#define PVRSRV_BRIDGE_SGX_UNREFSHAREDPBDESC \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+18)
+#define PVRSRV_BRIDGE_SGX_ADDSHAREDPBDESC \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+19)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+20)
+#define PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+21)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_RENDER_CONTEXT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+22)
+#define PVRSRV_BRIDGE_SGX_REGISTER_HW_TRANSFER_CONTEXT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+26)
+#define PVRSRV_BRIDGE_SGX_UNREGISTER_HW_TRANSFER_CONTEXT \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+27)
+
+#define PVRSRV_BRIDGE_SGX_SCHEDULE_PROCESS_QUEUES \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+28)
+
+#define PVRSRV_BRIDGE_SGX_READ_DIFF_COUNTERS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+29)
+#define PVRSRV_BRIDGE_SGX_READ_HWPERF_CB \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+30)
+
+#if defined(PDUMP)
+#define PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+31)
+#define PVRSRV_BRIDGE_SGX_PDUMP_3D_SIGNATURE_REGISTERS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+32)
+#define PVRSRV_BRIDGE_SGX_PDUMP_COUNTER_REGISTERS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+33)
+#define PVRSRV_BRIDGE_SGX_PDUMP_TA_SIGNATURE_REGISTERS \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+34)
+#define PVRSRV_BRIDGE_SGX_PDUMP_HWPERFCB \
+ PVRSRV_IOWR(PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+#endif
+
+#define PVRSRV_BRIDGE_LAST_SGX_CMD (PVRSRV_BRIDGE_SGX_CMD_BASE+35)
+
+struct PVRSRV_BRIDGE_IN_GETPHYSPAGEADDR {
+ u32 ui32BridgeFlags;
+ void *hDevMemHeap;
+ struct IMG_DEV_VIRTADDR sDevVAddr;
+};
+
+struct PVRSRV_BRIDGE_OUT_GETPHYSPAGEADDR {
+ enum PVRSRV_ERROR eError;
+ struct IMG_DEV_PHYADDR DevPAddr;
+ struct IMG_CPU_PHYADDR CpuPAddr;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_GETMMU_PDADDR {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hDevMemContext;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGX_GETMMU_PDADDR {
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_GETCLIENTINFO {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO {
+ struct SGX_INTERNAL_DEVINFO sSGXInternalDevInfo;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_GETINTERNALDEVINFO {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_OUT_GETCLIENTINFO {
+ struct SGX_CLIENT_INFO sClientInfo;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_RELEASECLIENTINFO {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct SGX_CLIENT_INFO sClientInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_ISPBREAKPOLL {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_IN_DOKICK {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct SGX_CCB_KICK sCCBKick;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_SCHEDULE_PROCESS_QUEUES {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_IN_SUBMITTRANSFER {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct PVRSRV_TRANSFER_SGX_KICK sKick;
+};
+
+
+struct PVRSRV_BRIDGE_IN_READREGDWORD {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ char *pszKey;
+ char *pszValue;
+};
+
+struct PVRSRV_BRIDGE_OUT_READREGDWORD {
+ enum PVRSRV_ERROR eError;
+ u32 ui32Data;
+};
+
+struct PVRSRV_BRIDGE_IN_SCHEDULECOMMAND {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ enum SGXMKIF_COMMAND_TYPE eCommandType;
+ struct SGXMKIF_COMMAND *psCommandData;
+
+};
+
+struct PVRSRV_BRIDGE_IN_SGXGETMISCINFO {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct SGX_MISC_INFO __user *psMiscInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_SGXINFO_FOR_SRVINIT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGXINFO_FOR_SRVINIT {
+ enum PVRSRV_ERROR eError;
+ struct SGX_BRIDGE_INFO_FOR_SRVINIT sInitInfo;
+};
+
+struct PVRSRV_BRIDGE_IN_SGXDEVINITPART2 {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct SGX_BRIDGE_INIT_INFO sInitInfo;
+};
+
+enum pvr_sync_wait_seq_type {
+ _PVR_SYNC_WAIT_BLOCK,
+ _PVR_SYNC_WAIT_NONBLOCK,
+ _PVR_SYNC_WAIT_EVENT,
+ _PVR_SYNC_WAIT_FLIP,
+ _PVR_SYNC_WAIT_UPDATE,
+};
+
+struct PVRSRV_BRIDGE_IN_2DQUERYBLTSCOMPLETE {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hKernSyncInfo;
+ u64 user_data;
+ enum pvr_sync_wait_seq_type type;
+};
+
+#define PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS 10
+
+struct PVRSRV_BRIDGE_IN_SGXFINDSHAREDPBDESC {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ IMG_BOOL bLockOnFailure;
+ u32 ui32TotalPBSize;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGXFINDSHAREDPBDESC {
+ void *hKernelMemInfo;
+ void *hSharedPBDesc;
+ void *hSharedPBDescKernelMemInfoHandle;
+ void *hHWPBDescKernelMemInfoHandle;
+ void *hBlockKernelMemInfoHandle;
+ void *ahSharedPBDescSubKernelMemInfoHandles
+ [PVRSRV_BRIDGE_SGX_SHAREDPBDESC_MAX_SUBMEMINFOS];
+ u32 ui32SharedPBDescSubKernelMemInfoHandlesCount;
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_SGXUNREFSHAREDPBDESC {
+ u32 ui32BridgeFlags;
+ void *hSharedPBDesc;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGXUNREFSHAREDPBDESC {
+ enum PVRSRV_ERROR eError;
+};
+
+struct PVRSRV_BRIDGE_IN_SGXADDSHAREDPBDESC {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hSharedPBDescKernelMemInfo;
+ void *hHWPBDescKernelMemInfo;
+ void *hBlockKernelMemInfo;
+ u32 ui32TotalPBSize;
+ void * __user *phKernelMemInfoHandles;
+ u32 ui32KernelMemInfoHandlesCount;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGXADDSHAREDPBDESC {
+ enum PVRSRV_ERROR eError;
+ void *hSharedPBDesc;
+};
+
+#ifdef PDUMP
+struct PVRSRV_BRIDGE_IN_PDUMP_BUFFER_ARRAY {
+ u32 ui32BridgeFlags;
+ struct SGX_KICKTA_DUMP_BUFFER __user *psBufferArray;
+ u32 ui32BufferArrayLength;
+ IMG_BOOL bDumpPolls;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_3D_SIGNATURE_REGISTERS {
+ u32 ui32BridgeFlags;
+ u32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ u32 *pui32Registers;
+ u32 ui32NumRegisters;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_COUNTER_REGISTERS {
+ u32 ui32BridgeFlags;
+ u32 ui32DumpFrameNum;
+ IMG_BOOL bLastFrame;
+ u32 *pui32Registers;
+ u32 ui32NumRegisters;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_TA_SIGNATURE_REGISTERS {
+ u32 ui32BridgeFlags;
+ u32 ui32DumpFrameNum;
+ u32 ui32TAKickCount;
+ IMG_BOOL bLastFrame;
+ u32 *pui32Registers;
+ u32 ui32NumRegisters;
+};
+
+struct PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ char szFileName[PVRSRV_PDUMP_MAX_FILENAME_SIZE];
+ u32 ui32FileOffset;
+ u32 ui32PDumpFlags;
+
+};
+
+#endif
+
+struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_RENDER_CONTEXT {
+ enum PVRSRV_ERROR eError;
+ void *hHWRenderContext;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_RENDER_CONTEXT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hHWRenderContext;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_TRANSFER_CONTEXT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGX_REGISTER_HW_TRANSFER_CONTEXT {
+ enum PVRSRV_ERROR eError;
+ void *hHWTransferContext;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_UNREGISTER_HW_TRANSFER_CONTEXT {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ void *hHWTransferContext;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_FLUSH_HW_RENDER_TARGET {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ struct IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_READ_DIFF_COUNTERS {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ u32 ui32Reg;
+ IMG_BOOL bNew;
+ u32 ui32New;
+ u32 ui32NewReset;
+ u32 ui32CountersReg;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGX_READ_DIFF_COUNTERS {
+ enum PVRSRV_ERROR eError;
+ u32 ui32Old;
+ u32 ui32Time;
+ IMG_BOOL bActive;
+ struct PVRSRV_SGXDEV_DIFF_INFO sDiffs;
+};
+
+struct PVRSRV_BRIDGE_IN_SGX_READ_HWPERF_CB {
+ u32 ui32BridgeFlags;
+ void *hDevCookie;
+ u32 ui32ArraySize;
+ struct PVRSRV_SGX_HWPERF_CB_ENTRY __user *psHWPerfCBData;
+};
+
+struct PVRSRV_BRIDGE_OUT_SGX_READ_HWPERF_CB {
+ enum PVRSRV_ERROR eError;
+ u32 ui32DataCount;
+ u32 ui32ClockSpeed;
+ u32 ui32HostTimeStamp;
+};
+
+#endif
diff --git a/drivers/gpu/pvr/sgx_bridge_km.h b/drivers/gpu/pvr/sgx_bridge_km.h
new file mode 100644
index 00000000000..3389b0cd23f
--- /dev/null
+++ b/drivers/gpu/pvr/sgx_bridge_km.h
@@ -0,0 +1,109 @@
+/**********************************************************************
+ *
+ * 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(__SGX_BRIDGE_KM_H__)
+#define __SGX_BRIDGE_KM_H__
+
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgx_bridge.h"
+#include "pvr_bridge.h"
+#include "perproc.h"
+
+
+enum PVRSRV_ERROR SGXSubmitTransferKM(void *hDevHandle,
+ struct PVRSRV_TRANSFER_SGX_KICK *psKick);
+
+
+enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle, struct SGX_CCB_KICK *psCCBKick,
+ int max_3dstat_val);
+
+enum PVRSRV_ERROR SGXGetPhysPageAddrKM(void *hDevMemHeap,
+ struct IMG_DEV_VIRTADDR sDevVAddr,
+ struct IMG_DEV_PHYADDR *pDevPAddr,
+ struct IMG_CPU_PHYADDR *pCpuPAddr);
+
+enum PVRSRV_ERROR SGXGetMMUPDAddrKM(void *hDevCookie,
+ void *hDevMemContext, struct IMG_DEV_PHYADDR *psPDDevPAddr);
+
+enum PVRSRV_ERROR SGXGetClientInfoKM(void *hDevCookie,
+ struct SGX_CLIENT_INFO *psClientInfo);
+
+enum PVRSRV_ERROR SGXGetMiscInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct SGX_MISC_INFO *psMiscInfo,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg,
+ u32 *pui32Old, IMG_BOOL bNew, u32 ui32New,
+ u32 ui32NewReset, u32 ui32CountersReg,
+ u32 *pui32Time, IMG_BOOL *pbActive,
+ struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs);
+enum PVRSRV_ERROR SGXReadHWPerfCBKM(void *hDevHandle, u32 ui32ArraySize,
+ struct PVRSRV_SGX_HWPERF_CB_ENTRY *psHWPerfCBData,
+ u32 *pui32DataCount, u32 *pui32ClockSpeed,
+ u32 *pui32HostTimeStamp);
+
+enum PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(
+ struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete);
+
+enum PVRSRV_ERROR SGXGetInfoForSrvinitKM(void *hDevHandle,
+ struct SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo);
+
+enum PVRSRV_ERROR DevInitSGXPart2KM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevHandle,
+ struct SGX_BRIDGE_INIT_INFO *psInitInfo);
+
+enum PVRSRV_ERROR SGXFindSharedPBDescKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevCookie, IMG_BOOL bLockOnFailure, u32 ui32TotalPBSize,
+ void **phSharedPBDesc,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
+ u32 *ui32SharedPBDescSubKernelMemInfosCount);
+
+enum PVRSRV_ERROR SGXUnrefSharedPBDescKM(void *hSharedPBDesc);
+
+enum PVRSRV_ERROR SGXAddSharedPBDescKM(
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevCookie,
+ struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
+ struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
+ u32 ui32TotalPBSize, void **phSharedPBDesc,
+ struct PVRSRV_KERNEL_MEM_INFO **psSharedPBDescSubKernelMemInfos,
+ u32 ui32SharedPBDescSubKernelMemInfosCount);
+
+enum PVRSRV_ERROR SGXGetInternalDevInfoKM(void *hDevCookie,
+ struct SGX_INTERNAL_DEVINFO *psSGXInternalDevInfo);
+
+int sgx_force_reset(void);
+
+#endif
diff --git a/drivers/gpu/pvr/sgx_options.h b/drivers/gpu/pvr/sgx_options.h
new file mode 100644
index 00000000000..67402fecd31
--- /dev/null
+++ b/drivers/gpu/pvr/sgx_options.h
@@ -0,0 +1,178 @@
+/**********************************************************************
+ *
+ * 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(CONFIG_PVR_DEBUG_EXTRA) || defined(INTERNAL_TEST)
+#define DEBUG_SET_OFFSET OPTIONS_BIT0
+#define OPTIONS_BIT0 0x1
+#else
+#define OPTIONS_BIT0 0x0
+#endif
+
+#if defined(PDUMP) || defined(INTERNAL_TEST)
+#define PDUMP_SET_OFFSET OPTIONS_BIT1
+#define OPTIONS_BIT1 (0x1 << 1)
+#else
+#define OPTIONS_BIT1 0x0
+#endif
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined(INTERNAL_TEST)
+#define PVRSRV_USSE_EDM_STATUS_DEBUG_SET_OFFSET OPTIONS_BIT2
+#define OPTIONS_BIT2 (0x1 << 2)
+#else
+#define OPTIONS_BIT2 0x0
+#endif
+
+#define SUPPORT_HW_RECOVERY_SET_OFFSET OPTIONS_BIT3
+#define OPTIONS_BIT3 (0x1 << 3)
+
+#define PVR_SECURE_HANDLES_SET_OFFSET OPTIONS_BIT4
+#define OPTIONS_BIT4 (0x1 << 4)
+
+#if defined(INTERNAL_TEST)
+#define SGX_BYPASS_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT5
+#define OPTIONS_BIT5 (0x1 << 5)
+#else
+#define OPTIONS_BIT5 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_DMS_AGE_ENABLE_SET_OFFSET OPTIONS_BIT6
+#define OPTIONS_BIT6 (0x1 << 6)
+#else
+#define OPTIONS_BIT6 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_DONT_SWITCH_OFF_FEATURES_SET_OFFSET OPTIONS_BIT7
+#define OPTIONS_BIT7 (0x1 << 7)
+#else
+#define OPTIONS_BIT7 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_FAST_DPM_INIT_SET_OFFSET OPTIONS_BIT8
+#define OPTIONS_BIT8 (0x1 << 8)
+#else
+#define OPTIONS_BIT8 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_FEATURE_DCU_SET_OFFSET OPTIONS_BIT9
+#define OPTIONS_BIT9 (0x1 << 9)
+#else
+#define OPTIONS_BIT9 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_FEATURE_MP_SET_OFFSET OPTIONS_BIT10
+#define OPTIONS_BIT10 (0x1 << 10)
+#else
+#define OPTIONS_BIT10 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_FEATURE_MULTITHREADED_UKERNEL_SET_OFFSET OPTIONS_BIT11
+#define OPTIONS_BIT11 (0x1 << 11)
+#else
+#define OPTIONS_BIT11 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_FEATURE_OVERLAPPED_SPM_SET_OFFSET OPTIONS_BIT12
+#define OPTIONS_BIT12 (0x1 << 12)
+#else
+#define OPTIONS_BIT12 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_FEATURE_RENDER_TARGET_ARRAYS_SET_OFFSET OPTIONS_BIT13
+#define OPTIONS_BIT13 (0x1 << 13)
+#else
+#define OPTIONS_BIT13 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_FEATURE_SYSTEM_CACHE_SET_OFFSET OPTIONS_BIT14
+#define OPTIONS_BIT14 (0x1 << 14)
+#else
+#define OPTIONS_BIT14 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define SGX_SUPPORT_HWPROFILING_SET_OFFSET OPTIONS_BIT15
+#define OPTIONS_BIT15 (0x1 << 15)
+#else
+#define OPTIONS_BIT15 0x0
+#endif
+
+#define SUPPORT_ACTIVE_POWER_MANAGEMENT_SET_OFFSET OPTIONS_BIT16
+#define OPTIONS_BIT16 (0x1 << 16)
+
+#if defined(INTERNAL_TEST)
+#define SUPPORT_DISPLAYCONTROLLER_TILING_SET_OFFSET OPTIONS_BIT17
+#define OPTIONS_BIT17 (0x1 << 17)
+#else
+#define OPTIONS_BIT17 0x0
+#endif
+
+#define SUPPORT_PERCONTEXT_PB_SET_OFFSET OPTIONS_BIT18
+#define OPTIONS_BIT18 (0x1 << 18)
+
+#define OPTIONS_BIT19 (0x1 << 19)
+
+#if defined(INTERNAL_TEST)
+#define SUPPORT_SGX_MMU_DUMMY_PAGE_SET_OFFSET OPTIONS_BIT20
+#define OPTIONS_BIT20 (0x1 << 20)
+#else
+#define OPTIONS_BIT20 0x0
+#endif
+
+#define SUPPORT_SGX_PRIORITY_SCHEDULING_SET_OFFSET OPTIONS_BIT21
+#define OPTIONS_BIT21 (0x1 << 21)
+
+#if defined(INTERNAL_TEST)
+#define USE_SUPPORT_NO_TA3D_OVERLAP_SET_OFFSET OPTIONS_BIT22
+#define OPTIONS_BIT22 (0x1 << 22)
+#else
+#define OPTIONS_BIT22 0x0
+#endif
+
+#if defined(INTERNAL_TEST)
+#define OPTIONS_HIGHBYTE \
+ ((SGX_FEATURE_MP_CORE_COUNT-1) << SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET)
+#define SGX_FEATURE_MP_CORE_COUNT_SET_OFFSET 28UL
+#define SGX_FEATURE_MP_CORE_COUNT_SET_MASK 0xFF
+#else
+#define OPTIONS_HIGHBYTE 0x0
+#endif
+
+#define SGX_BUILD_OPTIONS ( \
+ OPTIONS_BIT0 | OPTIONS_BIT1 | OPTIONS_BIT2 | OPTIONS_BIT3 | \
+ OPTIONS_BIT4 | OPTIONS_BIT5 | OPTIONS_BIT6 | OPTIONS_BIT7 | \
+ OPTIONS_BIT8 | OPTIONS_BIT9 | OPTIONS_BIT10 | OPTIONS_BIT11 | \
+ OPTIONS_BIT12 | OPTIONS_BIT13 | OPTIONS_BIT14 | OPTIONS_BIT15 | \
+ OPTIONS_BIT16 | OPTIONS_BIT17 | OPTIONS_BIT18 | OPTIONS_BIT19 | \
+ OPTIONS_BIT20 | OPTIONS_BIT21 | OPTIONS_BIT22 | OPTIONS_HIGHBYTE)
diff --git a/drivers/gpu/pvr/sgxapi_km.h b/drivers/gpu/pvr/sgxapi_km.h
new file mode 100644
index 00000000000..8ca76ffbf49
--- /dev/null
+++ b/drivers/gpu/pvr/sgxapi_km.h
@@ -0,0 +1,238 @@
+/**********************************************************************
+ *
+ * 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 __SGXAPI_KM_H__
+#define __SGXAPI_KM_H__
+
+
+#include "sgxdefs.h"
+
+#if defined(__KERNEL__)
+#include <linux/unistd.h>
+#else
+#include <unistd.h>
+#endif
+
+#define SGX_UNDEFINED_HEAP_ID (~0LU)
+#define SGX_GENERAL_HEAP_ID 0
+#define SGX_TADATA_HEAP_ID 1
+#define SGX_KERNEL_CODE_HEAP_ID 2
+#define SGX_KERNEL_DATA_HEAP_ID 3
+#define SGX_PIXELSHADER_HEAP_ID 4
+#define SGX_VERTEXSHADER_HEAP_ID 5
+#define SGX_PDSPIXEL_CODEDATA_HEAP_ID 6
+#define SGX_PDSVERTEX_CODEDATA_HEAP_ID 7
+#define SGX_SYNCINFO_HEAP_ID 8
+#define SGX_3DPARAMETERS_HEAP_ID 9
+#define SGX_MAX_HEAP_ID 10
+
+#define SGX_MAX_TA_STATUS_VALS 32
+#define SGX_MAX_3D_STATUS_VALS_OLD 2
+#define SGX_MAX_3D_STATUS_VALS 4
+
+#define SGX_MAX_SRC_SYNCS 4
+
+#define PVRSRV_SGX_HWPERF_NUM_COUNTERS 9
+
+#define PVRSRV_SGX_HWPERF_INVALID 0x1
+
+#define PVRSRV_SGX_HWPERF_TRANSFER 0x2
+#define PVRSRV_SGX_HWPERF_TA 0x3
+#define PVRSRV_SGX_HWPERF_3D 0x4
+#define PVRSRV_SGX_HWPERF_2D 0x5
+
+#define PVRSRV_SGX_HWPERF_MK_EVENT 0x101
+#define PVRSRV_SGX_HWPERF_MK_TA 0x102
+#define PVRSRV_SGX_HWPERF_MK_3D 0x103
+#define PVRSRV_SGX_HWPERF_MK_2D 0x104
+
+#define PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT 28
+#define PVRSRV_SGX_HWPERF_TYPE_OP_MASK \
+ ((1 << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT) - 1)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_START \
+ (0 << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+#define PVRSRV_SGX_HWPERF_TYPE_OP_END \
+ (1 << PVRSRV_SGX_HWPERF_TYPE_STARTEND_BIT)
+
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_START \
+ (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TRANSFER_END \
+ (PVRSRV_SGX_HWPERF_TRANSFER | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_START \
+ (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_TA_END \
+ (PVRSRV_SGX_HWPERF_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_START \
+ (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_3D_END \
+ (PVRSRV_SGX_HWPERF_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_START \
+ (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_2D_END \
+ (PVRSRV_SGX_HWPERF_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_START \
+ (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_EVENT_END \
+ (PVRSRV_SGX_HWPERF_MK_EVENT | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_START \
+ (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_TA_END \
+ (PVRSRV_SGX_HWPERF_MK_TA | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_START \
+ (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_3D_END \
+ (PVRSRV_SGX_HWPERF_MK_3D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_START \
+ (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_START)
+#define PVRSRV_SGX_HWPERF_TYPE_MK_2D_END \
+ (PVRSRV_SGX_HWPERF_MK_2D | PVRSRV_SGX_HWPERF_TYPE_OP_END)
+
+#define PVRSRV_SGX_HWPERF_OFF 0x0
+#define PVRSRV_SGX_HWPERF_GRAPHICS_ON (1UL << 0)
+#define PVRSRV_SGX_HWPERF_MK_EXECUTION_ON (1UL << 1)
+
+struct PVRSRV_SGX_HWPERF_CB_ENTRY {
+ u32 ui32FrameNo;
+ u32 ui32Type;
+ u32 ui32Ordinal;
+ u32 ui32Clocksx16;
+ u32 ui32Counters[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+};
+
+struct PVRSRV_SGX_HWPERF_CBDATA {
+ u32 ui32FrameNo;
+ u32 ui32Type;
+ u32 ui32StartTimeWraps;
+ u32 ui32StartTime;
+ u32 ui32EndTimeWraps;
+ u32 ui32EndTime;
+ u32 ui32ClockSpeed;
+ u32 ui32TimeMax;
+};
+
+struct SGX_MISC_INFO_HWPERF_RETRIEVE_CB {
+ struct PVRSRV_SGX_HWPERF_CBDATA *psHWPerfData;
+ u32 ui32ArraySize;
+ u32 ui32DataCount;
+ u32 ui32Time;
+};
+
+struct CTL_STATUS {
+ struct IMG_DEV_VIRTADDR sStatusDevAddr;
+ u32 ui32StatusValue;
+};
+
+enum SGX_MISC_INFO_REQUEST {
+ SGX_MISC_INFO_REQUEST_CLOCKSPEED = 0,
+ SGX_MISC_INFO_REQUEST_SGXREV,
+ SGX_MISC_INFO_REQUEST_DRIVER_SGXREV,
+ SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS,
+ SGX_MISC_INFO_REQUEST_HWPERF_CB_ON,
+ SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF,
+ SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB,
+ SGX_MISC_INFO_REQUEST_FORCE_I16 = 0x7fff
+};
+
+struct PVRSRV_SGX_MISCINFO_FEATURES {
+ u32 ui32CoreRev;
+ u32 ui32CoreID;
+ u32 ui32DDKVersion;
+ u32 ui32DDKBuild;
+ u32 ui32CoreIdSW;
+ u32 ui32CoreRevSW;
+ u32 ui32BuildOptions;
+};
+
+struct SGX_MISC_INFO {
+ enum SGX_MISC_INFO_REQUEST eRequest;
+
+ union {
+ u32 reserved;
+ struct PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+ u32 ui32SGXClockSpeed;
+ u32 ui32NewHWPerfStatus;
+ struct SGX_MISC_INFO_HWPERF_RETRIEVE_CB sRetrieveCB;
+ } uData;
+};
+
+#define SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH 256
+
+struct SGX_KICKTA_DUMPBITMAP {
+ struct IMG_DEV_VIRTADDR sDevBaseAddr;
+ u32 ui32Flags;
+ u32 ui32Width;
+ u32 ui32Height;
+ u32 ui32Stride;
+ u32 ui32PDUMPFormat;
+ u32 ui32BytesPP;
+ char pszName[SGX_KICKTA_DUMPBITMAP_MAX_NAME_LENGTH];
+};
+
+#define PVRSRV_SGX_PDUMP_CONTEXT_MAX_BITMAP_ARRAY_SIZE 16
+
+struct PVRSRV_SGX_PDUMP_CONTEXT {
+ u32 ui32CacheControl;
+};
+
+struct SGX_KICKTA_DUMP_ROFF {
+ void *hKernelMemInfo;
+ u32 uiAllocIndex;
+ u32 ui32Offset;
+ u32 ui32Value;
+ char *pszName;
+};
+
+struct SGX_KICKTA_DUMP_BUFFER {
+ u32 ui32SpaceUsed;
+ u32 ui32Start;
+ u32 ui32End;
+ u32 ui32BufferSize;
+ u32 ui32BackEndLength;
+ u32 uiAllocIndex;
+ void *hKernelMemInfo;
+ void *pvLinAddr;
+ char *pszName;
+};
+
+#ifdef PDUMP
+struct SGX_KICKTA_PDUMP {
+
+ struct SGX_KICKTA_DUMPBITMAP *psPDumpBitmapArray;
+ u32 ui32PDumpBitmapSize;
+
+ struct SGX_KICKTA_DUMP_BUFFER *psBufferArray;
+ u32 ui32BufferArraySize;
+
+ struct SGX_KICKTA_DUMP_ROFF *psROffArray;
+ u32 ui32ROffArraySize;
+};
+#endif
+
+#define SGX_MAX_TRANSFER_STATUS_VALS 2
+#define SGX_MAX_TRANSFER_SYNC_OPS 5
+
+#endif
diff --git a/drivers/gpu/pvr/sgxconfig.h b/drivers/gpu/pvr/sgxconfig.h
new file mode 100644
index 00000000000..589e26475e1
--- /dev/null
+++ b/drivers/gpu/pvr/sgxconfig.h
@@ -0,0 +1,75 @@
+/**********************************************************************
+ *
+ * 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 __SGXCONFIG_H__
+#define __SGXCONFIG_H__
+
+#define DEV_DEVICE_TYPE PVRSRV_DEVICE_TYPE_SGX
+#define DEV_DEVICE_CLASS PVRSRV_DEVICE_CLASS_3D
+
+#define DEV_MAJOR_VERSION 1
+#define DEV_MINOR_VERSION 0
+
+#define SGX_GENERAL_HEAP_BASE 0x01800000
+#define SGX_GENERAL_HEAP_SIZE (0x06C00000-0x00001000)
+
+#define SGX_3DPARAMETERS_HEAP_BASE 0x08400000
+#define SGX_3DPARAMETERS_HEAP_SIZE (0x04000000-0x00001000)
+
+#define SGX_TADATA_HEAP_BASE 0x0C400000
+#define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000)
+
+#define SGX_SYNCINFO_HEAP_BASE 0x0D400000
+#define SGX_SYNCINFO_HEAP_SIZE (0x00400000-0x00001000)
+
+#define SGX_PDSPIXEL_CODEDATA_HEAP_BASE 0x0D800000
+#define SGX_PDSPIXEL_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+#define SGX_PDSVERTEX_CODEDATA_HEAP_BASE 0x0E000000
+#define SGX_PDSVERTEX_CODEDATA_HEAP_SIZE (0x00800000-0x00001000)
+
+#define SGX_RESERVED_CODE_HEAP_BASE 0x0E800000
+#define SGX_RESERVED_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+#define SGX_KERNEL_CODE_HEAP_BASE 0x0EC00000
+#define SGX_KERNEL_CODE_HEAP_SIZE (0x00080000-0x00001000)
+
+#define SGX_KERNEL_DATA_HEAP_BASE 0x0F000000
+#define SGX_KERNEL_DATA_HEAP_SIZE (0x00400000-0x00001000)
+
+#define SGX_PIXELSHADER_HEAP_BASE 0x0F400000
+#define SGX_PIXELSHADER_HEAP_SIZE (0x00500000-0x00001000)
+
+#define SGX_VERTEXSHADER_HEAP_BASE 0x0FC00000
+#define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000)
+
+#define SGX_CORE_IDENTIFIED
+
+#if !defined(SGX_CORE_IDENTIFIED)
+#error "sgxconfig.h: ERROR: unspecified SGX Core version"
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/sgxcoretypes.h b/drivers/gpu/pvr/sgxcoretypes.h
new file mode 100644
index 00000000000..0eb51461fc9
--- /dev/null
+++ b/drivers/gpu/pvr/sgxcoretypes.h
@@ -0,0 +1,41 @@
+/**********************************************************************
+ *
+ * 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 _SGXCORETYPES_KM_H_
+#define _SGXCORETYPES_KM_H_
+
+enum SGX_CORE_ID_TYPE {
+ SGX_CORE_ID_INVALID = 0,
+ SGX_CORE_ID_530 = 2,
+ SGX_CORE_ID_535 = 3,
+};
+
+struct SGX_CORE_INFO {
+ enum SGX_CORE_ID_TYPE eID;
+ u32 uiRev;
+};
+
+#endif
diff --git a/drivers/gpu/pvr/sgxdefs.h b/drivers/gpu/pvr/sgxdefs.h
new file mode 100644
index 00000000000..1e0cfec503e
--- /dev/null
+++ b/drivers/gpu/pvr/sgxdefs.h
@@ -0,0 +1,38 @@
+/**********************************************************************
+ *
+ * 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 _SGXDEFS_H_
+#define _SGXDEFS_H_
+
+#ifndef SGX530
+#error unsupported SGX revision
+#endif
+
+#include "sgx530defs.h"
+#include "sgxerrata.h"
+#include "sgxfeaturedefs.h"
+
+#endif
diff --git a/drivers/gpu/pvr/sgxerrata.h b/drivers/gpu/pvr/sgxerrata.h
new file mode 100644
index 00000000000..1aeaa9abe85
--- /dev/null
+++ b/drivers/gpu/pvr/sgxerrata.h
@@ -0,0 +1,34 @@
+/**********************************************************************
+ *
+ * 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 _SGXERRATA_KM_H_
+#define _SGXERRATA_KM_H_
+
+#ifndef SGX530
+#error unsupported SGX version
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/sgxfeaturedefs.h b/drivers/gpu/pvr/sgxfeaturedefs.h
new file mode 100644
index 00000000000..b36e6be7227
--- /dev/null
+++ b/drivers/gpu/pvr/sgxfeaturedefs.h
@@ -0,0 +1,40 @@
+/**********************************************************************
+ *
+ * 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 SGX530
+#error unsupported SGX version
+#endif
+
+#define SGX_CORE_FRIENDLY_NAME "SGX530"
+#define SGX_CORE_ID SGX_CORE_ID_530
+#define SGX_FEATURE_ADDRESS_SPACE_SIZE 28
+#define SGX_FEATURE_AUTOCLOCKGATING
+#define SGX_FEATURE_MP_CORE_COUNT 1
+#define SUPPORT_SGX_PRIORITY_SCHEDULING
+
+#include "img_types.h"
+
+#include "sgxcoretypes.h"
diff --git a/drivers/gpu/pvr/sgxinfo.h b/drivers/gpu/pvr/sgxinfo.h
new file mode 100644
index 00000000000..11f599f414a
--- /dev/null
+++ b/drivers/gpu/pvr/sgxinfo.h
@@ -0,0 +1,342 @@
+/**********************************************************************
+ *
+ * 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(__SGXINFO_H__)
+#define __SGXINFO_H__
+
+#include "sgxscript.h"
+
+#include "servicesint.h"
+
+#include "services.h"
+#include "sgxapi_km.h"
+
+#define SGX_MP_CORE_SELECT(x, i) (x)
+
+#define SGX_MAX_DEV_DATA 24
+#define SGX_MAX_INIT_MEM_HANDLES 16
+
+#define SGX_BIF_DIR_LIST_INDEX_EDM 0
+
+struct SGX_BRIDGE_INFO_FOR_SRVINIT {
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+ struct PVRSRV_HEAP_INFO asHeapInfo[PVRSRV_MAX_CLIENT_HEAPS];
+};
+
+struct SGX_BRIDGE_INIT_INFO {
+ void *hKernelCCBMemInfo;
+ void *hKernelCCBCtlMemInfo;
+ void *hKernelCCBEventKickerMemInfo;
+ void *hKernelSGXHostCtlMemInfo;
+ void *hKernelSGXTA3DCtlMemInfo;
+ void *hKernelSGXMiscMemInfo;
+ u32 ui32HostKickAddress;
+ u32 ui32GetMiscInfoAddress;
+ void *hKernelHWPerfCBMemInfo;
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ void *hKernelEDMStatusBufferMemInfo;
+#endif
+
+ u32 ui32EDMTaskReg0;
+ u32 ui32EDMTaskReg1;
+
+ u32 ui32ClkGateStatusReg;
+ u32 ui32ClkGateStatusMask;
+
+ u32 ui32CacheControl;
+
+ u32 asInitDevData[SGX_MAX_DEV_DATA];
+ void *asInitMemHandles[SGX_MAX_INIT_MEM_HANDLES];
+
+ struct SGX_INIT_SCRIPTS sScripts;
+
+};
+
+struct SGXMKIF_COMMAND {
+ u32 ui32ServiceAddress;
+ u32 ui32Data[3];
+};
+
+struct PVRSRV_SGX_KERNEL_CCB {
+ struct SGXMKIF_COMMAND asCommands[256];
+};
+
+struct PVRSRV_SGX_CCB_CTL {
+ u32 ui32WriteOffset;
+ u32 ui32ReadOffset;
+};
+
+#define SGX_AUXCCBFLAGS_SHARED 0x00000001
+
+enum SGXMKIF_COMMAND_TYPE {
+ SGXMKIF_COMMAND_EDM_KICK = 0,
+ SGXMKIF_COMMAND_VIDEO_KICK = 1,
+ SGXMKIF_COMMAND_REQUEST_SGXMISCINFO = 2,
+
+ SGXMKIF_COMMAND_FORCE_I32 = -1,
+
+};
+
+#define PVRSRV_CCBFLAGS_RASTERCMD 0x1
+#define PVRSRV_CCBFLAGS_TRANSFERCMD 0x2
+#define PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD 0x3
+#define PVRSRV_CCBFLAGS_POWERCMD 0x5
+
+#define PVRSRV_POWERCMD_POWEROFF 0x1
+#define PVRSRV_POWERCMD_IDLE 0x2
+
+#define SGX_BIF_INVALIDATE_PTCACHE 0x1
+#define SGX_BIF_INVALIDATE_PDCACHE 0x2
+
+struct SGXMKIF_HWDEVICE_SYNC_LIST {
+ struct IMG_DEV_VIRTADDR sAccessDevAddr;
+ u32 ui32NumSyncObjects;
+
+ struct PVRSRV_DEVICE_SYNC_OBJECT asSyncData[1];
+};
+
+struct SGX_DEVICE_SYNC_LIST {
+ struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList;
+
+ void *hKernelHWSyncListMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO *psHWDeviceSyncListClientMemInfo;
+ struct PVRSRV_CLIENT_MEM_INFO *psAccessResourceClientMemInfo;
+
+ volatile u32 *pui32Lock;
+
+ struct SGX_DEVICE_SYNC_LIST *psNext;
+
+ u32 ui32NumSyncObjects;
+ void *ahSyncHandles[1];
+};
+
+struct SGX_INTERNEL_STATUS_UPDATE {
+ struct CTL_STATUS sCtlStatus;
+ void *hKernelMemInfo;
+ /* pdump specific - required? */
+ u32 ui32LastStatusUpdateDumpVal;
+};
+
+struct SGX_CCB_KICK {
+ enum SGXMKIF_COMMAND_TYPE eCommand;
+ struct SGXMKIF_COMMAND sCommand;
+ void *hCCBKernelMemInfo;
+
+ u32 ui32NumDstSyncObjects;
+ void *hKernelHWSyncListMemInfo;
+ void *sDstSyncHandle;
+
+ u32 ui32NumTAStatusVals;
+ u32 ui32Num3DStatusVals;
+
+ void *ahTAStatusSyncInfo[SGX_MAX_TA_STATUS_VALS];
+ void *ah3DStatusSyncInfo[SGX_MAX_3D_STATUS_VALS];
+
+ IMG_BOOL bFirstKickOrResume;
+#if (defined(NO_HARDWARE) || defined(PDUMP))
+ IMG_BOOL bTerminateOrAbort;
+#endif
+ IMG_BOOL bKickRender;
+
+ u32 ui32CCBOffset;
+
+ u32 ui32NumSrcSyncs;
+ void *ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+
+ IMG_BOOL bTADependency;
+ void *hTA3DSyncInfo;
+
+ void *hTASyncInfo;
+ void *h3DSyncInfo;
+#if defined(PDUMP)
+ u32 ui32CCBDumpWOff;
+#endif
+#if defined(NO_HARDWARE)
+ u32 ui32WriteOpsPendingVal;
+#endif
+};
+
+#define SGX_KERNEL_USE_CODE_BASE_INDEX 15
+
+struct SGXMKIF_HOST_CTL {
+
+ u32 ui32PowerStatus;
+ u32 ui32uKernelDetectedLockups;
+ u32 ui32HostDetectedLockups;
+ u32 ui32HWRecoverySampleRate;
+ u32 ui32ActivePowManSampleRate;
+ u32 ui32InterruptFlags;
+ u32 ui32InterruptClearFlags;
+
+ u32 ui32ResManFlags;
+ struct IMG_DEV_VIRTADDR sResManCleanupData;
+
+ u32 ui32NumActivePowerEvents;
+
+ u32 ui32HWPerfFlags;
+
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+ /* !< See SGXMK_STATUS_BUFFER */
+ struct IMG_DEV_VIRTADDR sEDMStatusBuffer;
+#endif
+
+ /*< to count time wraps in the Timer task */
+ u32 ui32TimeWraps;
+};
+
+struct SGX_CLIENT_INFO {
+ u32 ui32ProcessID;
+ void *pvProcess;
+ struct PVRSRV_MISC_INFO sMiscInfo;
+
+ u32 asDevData[SGX_MAX_DEV_DATA];
+
+};
+
+struct SGX_INTERNAL_DEVINFO {
+ u32 ui32Flags;
+ void *hHostCtlKernelMemInfoHandle;
+ IMG_BOOL bForcePTOff;
+};
+
+#define SGXTQ_MAX_STATUS (SGX_MAX_TRANSFER_STATUS_VALS + 2)
+
+#define SGXMKIF_TQFLAGS_NOSYNCUPDATE 0x00000001
+#define SGXMKIF_TQFLAGS_KEEPPENDING 0x00000002
+#define SGXMKIF_TQFLAGS_TATQ_SYNC 0x00000004
+#define SGXMKIF_TQFLAGS_3DTQ_SYNC 0x00000008
+struct SGXMKIF_CMDTA_SHARED {
+ u32 ui32NumTAStatusVals;
+ u32 ui32Num3DStatusVals;
+
+ u32 ui32TATQSyncWriteOpsPendingVal;
+ struct IMG_DEV_VIRTADDR sTATQSyncWriteOpsCompleteDevVAddr;
+ u32 ui32TATQSyncReadOpsPendingVal;
+ struct IMG_DEV_VIRTADDR sTATQSyncReadOpsCompleteDevVAddr;
+
+ u32 ui323DTQSyncWriteOpsPendingVal;
+ struct IMG_DEV_VIRTADDR s3DTQSyncWriteOpsCompleteDevVAddr;
+ u32 ui323DTQSyncReadOpsPendingVal;
+ struct IMG_DEV_VIRTADDR s3DTQSyncReadOpsCompleteDevVAddr;
+
+ u32 ui32NumSrcSyncs;
+ struct PVRSRV_DEVICE_SYNC_OBJECT asSrcSyncs[SGX_MAX_SRC_SYNCS];
+
+ struct CTL_STATUS sCtlTAStatusInfo[SGX_MAX_TA_STATUS_VALS];
+ /*
+ * Note that the actual size of sCtl3DStatusInfo changes based
+ * on the IOCTL ABI version used.
+ */
+ struct CTL_STATUS sCtl3DStatusInfo[SGX_MAX_3D_STATUS_VALS];
+
+ struct PVRSRV_DEVICE_SYNC_OBJECT sTA3DDependency;
+
+};
+
+struct SGXMKIF_TRANSFERCMD_SHARED {
+
+ u32 ui32SrcReadOpPendingVal;
+ struct IMG_DEV_VIRTADDR sSrcReadOpsCompleteDevAddr;
+
+ u32 ui32SrcWriteOpPendingVal;
+ struct IMG_DEV_VIRTADDR sSrcWriteOpsCompleteDevAddr;
+
+ u32 ui32DstReadOpPendingVal;
+ struct IMG_DEV_VIRTADDR sDstReadOpsCompleteDevAddr;
+
+ u32 ui32DstWriteOpPendingVal;
+ struct IMG_DEV_VIRTADDR sDstWriteOpsCompleteDevAddr;
+
+ u32 ui32TASyncWriteOpsPendingVal;
+ struct IMG_DEV_VIRTADDR sTASyncWriteOpsCompleteDevVAddr;
+ u32 ui32TASyncReadOpsPendingVal;
+ struct IMG_DEV_VIRTADDR sTASyncReadOpsCompleteDevVAddr;
+
+ u32 ui323DSyncWriteOpsPendingVal;
+ struct IMG_DEV_VIRTADDR s3DSyncWriteOpsCompleteDevVAddr;
+ u32 ui323DSyncReadOpsPendingVal;
+ struct IMG_DEV_VIRTADDR s3DSyncReadOpsCompleteDevVAddr;
+
+ u32 ui32NumStatusVals;
+ struct CTL_STATUS sCtlStatusInfo[SGXTQ_MAX_STATUS];
+};
+
+struct PVRSRV_TRANSFER_SGX_KICK {
+ void *hCCBMemInfo;
+ u32 ui32SharedCmdCCBOffset;
+
+ struct IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+
+ void *hTASyncInfo;
+ void *h3DSyncInfo;
+
+ u32 ui32NumSrcSync;
+ void *ahSrcSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ u32 ui32NumDstSync;
+ void *ahDstSyncInfo[SGX_MAX_TRANSFER_SYNC_OPS];
+
+ u32 ui32Flags;
+
+ u32 ui32PDumpFlags;
+#if defined(PDUMP)
+ u32 ui32CCBDumpWOff;
+#endif
+};
+
+#define PVRSRV_SGX_DIFF_NUM_COUNTERS 9
+
+struct PVRSRV_SGXDEV_DIFF_INFO {
+ u32 aui32Counters[PVRSRV_SGX_DIFF_NUM_COUNTERS];
+ u32 ui32Time[2];
+ u32 ui32Marker[2];
+};
+
+#define SGXMKIF_HWPERF_CB_SIZE 0x100
+
+struct SGXMKIF_HWPERF_CB_ENTRY {
+ u32 ui32FrameNo;
+ u32 ui32Type;
+ u32 ui32Ordinal;
+ u32 ui32TimeWraps;
+ u32 ui32Time;
+ u32 ui32Counters[PVRSRV_SGX_HWPERF_NUM_COUNTERS];
+};
+
+struct SGXMKIF_HWPERF_CB {
+ u32 ui32Woff;
+ u32 ui32Roff;
+ u32 ui32OrdinalGRAPHICS;
+ u32 ui32OrdinalMK_EXECUTION;
+ struct SGXMKIF_HWPERF_CB_ENTRY psHWPerfCBData[SGXMKIF_HWPERF_CB_SIZE];
+};
+
+struct PVRSRV_SGX_MISCINFO_INFO {
+ u32 ui32MiscInfoFlags;
+ struct PVRSRV_SGX_MISCINFO_FEATURES sSGXFeatures;
+};
+
+#endif
diff --git a/drivers/gpu/pvr/sgxinfokm.h b/drivers/gpu/pvr/sgxinfokm.h
new file mode 100644
index 00000000000..6db6bb394e6
--- /dev/null
+++ b/drivers/gpu/pvr/sgxinfokm.h
@@ -0,0 +1,270 @@
+/**********************************************************************
+ *
+ * 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 __SGXINFOKM_H__
+#define __SGXINFOKM_H__
+
+#include <linux/workqueue.h>
+#include "sgxdefs.h"
+#include "device.h"
+#include "sysconfig.h"
+#include "sgxscript.h"
+#include "sgxinfo.h"
+
+
+#define SGX_HOSTPORT_PRESENT 0x00000001UL
+
+#define PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE (1UL << 2)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE (1UL << 3)
+#define PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE (1UL << 4)
+#define PVRSRV_USSE_EDM_POWMAN_NO_WORK (1UL << 5)
+
+#define PVRSRV_USSE_EDM_INTERRUPT_HWR (1UL << 0)
+#define PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER (1UL << 1)
+
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_RT_REQUEST 0x01UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_RC_REQUEST 0x02UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_TC_REQUEST 0x04UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_2DC_REQUEST 0x08UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_SHAREDPBDESC 0x10UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPD 0x20UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPT 0x40UL
+#define PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE 0x80UL
+
+#define PVRSRV_USSE_MISCINFO_READY 0x1UL
+
+struct PVRSRV_SGX_CCB_INFO;
+
+struct PVRSRV_SGXDEV_INFO {
+ enum PVRSRV_DEVICE_TYPE eDeviceType;
+ enum PVRSRV_DEVICE_CLASS eDeviceClass;
+
+ u8 ui8VersionMajor;
+ u8 ui8VersionMinor;
+ u32 ui32CoreConfig;
+ u32 ui32CoreFlags;
+
+ void __iomem *pvRegsBaseKM;
+
+ void *hRegMapping;
+
+ struct IMG_SYS_PHYADDR sRegsPhysBase;
+
+ u32 ui32RegSize;
+
+ u32 ui32CoreClockSpeed;
+ u32 ui32uKernelTimerClock;
+
+ void *psStubPBDescListKM;
+
+ struct IMG_DEV_PHYADDR sKernelPDDevPAddr;
+
+ void *pvDeviceMemoryHeap;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelCCBMemInfo;
+ struct PVRSRV_SGX_KERNEL_CCB *psKernelCCB;
+ struct PVRSRV_SGX_CCB_INFO *psKernelCCBInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelCCBCtlMemInfo;
+ struct PVRSRV_SGX_CCB_CTL *psKernelCCBCtl;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelCCBEventKickerMemInfo;
+ u32 *pui32KernelCCBEventKicker;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo;
+ u32 ui32HostKickAddress;
+ u32 ui32GetMiscInfoAddress;
+ u32 ui32KickTACounter;
+ u32 ui32KickTARenderCounter;
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelHWPerfCBMemInfo;
+ struct PVRSRV_SGXDEV_DIFF_INFO sDiffInfo;
+ u32 ui32HWGroupRequested;
+ u32 ui32HWReset;
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+ /*!< Meminfo for EDM status buffer */
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelEDMStatusBufferMemInfo;
+#endif
+
+ u32 ui32ClientRefCount;
+
+ u32 ui32CacheControl;
+
+ void *pvMMUContextList;
+
+ IMG_BOOL bForcePTOff;
+
+ u32 ui32EDMTaskReg0;
+ u32 ui32EDMTaskReg1;
+
+ u32 ui32ClkGateStatusReg;
+ u32 ui32ClkGateStatusMask;
+ struct SGX_INIT_SCRIPTS sScripts;
+
+ void *hBIFResetPDOSMemHandle;
+ struct IMG_DEV_PHYADDR sBIFResetPDDevPAddr;
+ struct IMG_DEV_PHYADDR sBIFResetPTDevPAddr;
+ struct IMG_DEV_PHYADDR sBIFResetPageDevPAddr;
+ u32 *pui32BIFResetPD;
+ u32 *pui32BIFResetPT;
+
+ void *hTimer;
+ u32 ui32TimeStamp;
+ u32 ui32NumResets;
+
+ unsigned long long last_idle;
+ unsigned long long burst_start;
+ int burst_size;
+ int burst_cnt;
+ int power_down_delay;
+
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl;
+
+ struct PVRSRV_KERNEL_MEM_INFO *psKernelSGXTA3DCtlMemInfo;
+
+ u32 ui32Flags;
+
+#if defined(PDUMP)
+ struct PVRSRV_SGX_PDUMP_CONTEXT sPDContext;
+#endif
+
+
+ u32 asSGXDevData[SGX_MAX_DEV_DATA];
+
+};
+
+struct SGX_TIMING_INFORMATION {
+ u32 ui32CoreClockSpeed;
+ u32 ui32HWRecoveryFreq;
+ u32 ui32ActivePowManLatencyms;
+ u32 ui32uKernelFreq;
+};
+
+struct SGX_DEVICE_MAP {
+ u32 ui32Flags;
+
+ struct IMG_SYS_PHYADDR sRegsSysPBase;
+ struct IMG_CPU_PHYADDR sRegsCpuPBase;
+ void __iomem *pvRegsCpuVBase;
+ u32 ui32RegsSize;
+
+ struct IMG_SYS_PHYADDR sLocalMemSysPBase;
+ struct IMG_DEV_PHYADDR sLocalMemDevPBase;
+ struct IMG_CPU_PHYADDR sLocalMemCpuPBase;
+ u32 ui32LocalMemSize;
+
+ u32 ui32IRQ;
+};
+
+struct PVRSRV_STUB_PBDESC;
+struct PVRSRV_STUB_PBDESC {
+ u32 ui32RefCount;
+ u32 ui32TotalPBSize;
+ struct PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO **ppsSubKernelMemInfos;
+ u32 ui32SubKernelMemInfosCount;
+ void *hDevCookie;
+ struct PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo;
+ struct PVRSRV_STUB_PBDESC *psNext;
+};
+
+struct PVRSRV_SGX_CCB_INFO {
+ struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
+ struct SGXMKIF_COMMAND *psCommands;
+ u32 *pui32WriteOffset;
+ volatile u32 *pui32ReadOffset;
+#if defined(PDUMP)
+ u32 ui32CCBDumpWOff;
+#endif
+};
+
+struct timer_work_data {
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct delayed_work work;
+ struct workqueue_struct *work_queue;
+ unsigned int interval;
+ bool armed;
+};
+
+enum PVRSRV_ERROR SGXRegisterDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+enum PVRSRV_ERROR SGXOSTimerEnable(struct timer_work_data *data);
+enum PVRSRV_ERROR SGXOSTimerCancel(struct timer_work_data *data);
+struct timer_work_data *
+SGXOSTimerInit(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+void SGXOSTimerDeInit(struct timer_work_data *data);
+
+void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+void SGXReset(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32PDUMPFlags);
+
+enum PVRSRV_ERROR SGXInitialise(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery);
+enum PVRSRV_ERROR SGXDeinitialise(void *hDevCookie);
+
+void sgx_mark_new_command(struct PVRSRV_DEVICE_NODE *node);
+void sgx_mark_power_down(struct PVRSRV_DEVICE_NODE *node);
+
+void SGXStartTimer(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bStartOSTimer);
+
+enum PVRSRV_ERROR SGXPrePowerStateExt(void *hDevHandle,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE eCurrentPowerState);
+
+enum PVRSRV_ERROR SGXPostPowerStateExt(void *hDevHandle,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE eCurrentPowerState);
+
+enum PVRSRV_ERROR SGXPreClockSpeedChange(void *hDevHandle,
+ IMG_BOOL bIdleDevice,
+ enum PVR_POWER_STATE
+ eCurrentPowerState);
+
+enum PVRSRV_ERROR SGXPostClockSpeedChange(void *hDevHandle,
+ IMG_BOOL bIdleDevice,
+ enum PVR_POWER_STATE
+ eCurrentPowerState);
+
+enum PVRSRV_ERROR SGXDevInitCompatCheck(struct PVRSRV_DEVICE_NODE
+ *psDeviceNode);
+
+void SysGetSGXTimingInformation(struct SGX_TIMING_INFORMATION *psSGXTimingInfo);
+
+#if defined(NO_HARDWARE)
+static inline void NoHardwareGenerateEvent(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ u32 ui32StatusRegister,
+ u32 ui32StatusValue,
+ u32 ui32StatusMask)
+{
+ u32 ui32RegVal;
+
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister);
+
+ ui32RegVal &= ~ui32StatusMask;
+ ui32RegVal |= (ui32StatusValue & ui32StatusMask);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32StatusRegister, ui32RegVal);
+}
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/sgxinit.c b/drivers/gpu/pvr/sgxinit.c
new file mode 100644
index 00000000000..be7fa0f2c00
--- /dev/null
+++ b/drivers/gpu/pvr/sgxinit.c
@@ -0,0 +1,1663 @@
+/**********************************************************************
+ *
+ * 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 <linux/workqueue.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+#include "sysconfig.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "resman.h"
+
+#include "pdump_km.h"
+#include "ra.h"
+#include "mmu.h"
+#include "handle.h"
+#include "perproc.h"
+
+#include "sgxutils.h"
+#include "pvrversion.h"
+#include "sgx_options.h"
+
+static IMG_BOOL SGX_ISRHandler(void *pvData);
+
+static u32 gui32EventStatusServicesByISR;
+
+static enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+static void SGXCommandComplete(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ BUG_ON(in_irq());
+
+ SGXScheduleProcessQueuesKM(psDeviceNode);
+}
+
+static u32 DeinitDevInfo(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ if (psDevInfo->psKernelCCBInfo != NULL)
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGX_CCB_INFO),
+ psDevInfo->psKernelCCBInfo, NULL);
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR InitDevInfo(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ enum PVRSRV_ERROR eError;
+
+ struct PVRSRV_SGX_CCB_INFO *psKernelCCBInfo = NULL;
+
+ PVR_UNREFERENCED_PARAMETER(psPerProc);
+ psDevInfo->sScripts = psInitInfo->sScripts;
+
+ psDevInfo->psKernelCCBMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBMemInfo;
+ psDevInfo->psKernelCCB =
+ (struct PVRSRV_SGX_KERNEL_CCB *)psDevInfo->psKernelCCBMemInfo->
+ pvLinAddrKM;
+
+ psDevInfo->psKernelCCBCtlMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelCCBCtlMemInfo;
+ psDevInfo->psKernelCCBCtl =
+ (struct PVRSRV_SGX_CCB_CTL *)psDevInfo->psKernelCCBCtlMemInfo->
+ pvLinAddrKM;
+
+ psDevInfo->psKernelCCBEventKickerMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)
+ psInitInfo->hKernelCCBEventKickerMemInfo;
+ psDevInfo->pui32KernelCCBEventKicker =
+ (u32 *)psDevInfo->psKernelCCBEventKickerMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXHostCtlMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
+ hKernelSGXHostCtlMemInfo;
+ psDevInfo->psSGXHostCtl = (struct SGXMKIF_HOST_CTL __force __iomem *)
+ psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+
+ psDevInfo->psKernelSGXTA3DCtlMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
+ hKernelSGXTA3DCtlMemInfo;
+
+ psDevInfo->psKernelSGXMiscMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelSGXMiscMemInfo;
+
+ psDevInfo->psKernelHWPerfCBMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelHWPerfCBMemInfo;
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+ psDevInfo->psKernelEDMStatusBufferMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psInitInfo->
+ hKernelEDMStatusBufferMemInfo;
+#endif
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGX_CCB_INFO),
+ (void **)&psKernelCCBInfo, NULL);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "InitDevInfo: Failed to alloc memory");
+ goto failed_allockernelccb;
+ }
+
+ OSMemSet(psKernelCCBInfo, 0, sizeof(struct PVRSRV_SGX_CCB_INFO));
+ psKernelCCBInfo->psCCBMemInfo = psDevInfo->psKernelCCBMemInfo;
+ psKernelCCBInfo->psCCBCtlMemInfo = psDevInfo->psKernelCCBCtlMemInfo;
+ psKernelCCBInfo->psCommands = psDevInfo->psKernelCCB->asCommands;
+ psKernelCCBInfo->pui32WriteOffset =
+ &psDevInfo->psKernelCCBCtl->ui32WriteOffset;
+ psKernelCCBInfo->pui32ReadOffset =
+ &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
+ psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
+
+ psDevInfo->ui32HostKickAddress = psInitInfo->ui32HostKickAddress;
+
+ psDevInfo->ui32GetMiscInfoAddress = psInitInfo->ui32GetMiscInfoAddress;
+
+ psDevInfo->bForcePTOff = IMG_FALSE;
+
+ psDevInfo->ui32CacheControl = psInitInfo->ui32CacheControl;
+
+ psDevInfo->ui32EDMTaskReg0 = psInitInfo->ui32EDMTaskReg0;
+ psDevInfo->ui32EDMTaskReg1 = psInitInfo->ui32EDMTaskReg1;
+ psDevInfo->ui32ClkGateStatusReg = psInitInfo->ui32ClkGateStatusReg;
+ psDevInfo->ui32ClkGateStatusMask = psInitInfo->ui32ClkGateStatusMask;
+
+ OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData,
+ sizeof(psDevInfo->asSGXDevData));
+
+ return PVRSRV_OK;
+
+failed_allockernelccb:
+ DeinitDevInfo(psDevInfo);
+
+ return eError;
+}
+
+static enum PVRSRV_ERROR SGXRunScript(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ union SGX_INIT_COMMAND *psScript,
+ u32 ui32NumInitCommands)
+{
+ u32 ui32PC;
+ union SGX_INIT_COMMAND *psComm;
+
+ for (ui32PC = 0, psComm = psScript;
+ ui32PC < ui32NumInitCommands; ui32PC++, psComm++) {
+ switch (psComm->eOp) {
+ case SGX_INIT_OP_WRITE_HW_REG:
+ {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ psComm->sWriteHWReg.ui32Offset,
+ psComm->sWriteHWReg.ui32Value);
+ PDUMPREG(psComm->sWriteHWReg.ui32Offset,
+ psComm->sWriteHWReg.ui32Value);
+ break;
+ }
+#if defined(PDUMP)
+ case SGX_INIT_OP_PDUMP_HW_REG:
+ {
+ PDUMPREG(psComm->sPDumpHWReg.ui32Offset,
+ psComm->sPDumpHWReg.ui32Value);
+ break;
+ }
+#endif
+ case SGX_INIT_OP_HALT:
+ {
+ return PVRSRV_OK;
+ }
+ case SGX_INIT_OP_ILLEGAL:
+
+ default:
+ {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXRunScript: PC %d: Illegal command: %d",
+ ui32PC, psComm->eOp);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+enum PVRSRV_ERROR SGXInitialise(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bHardwareRecovery)
+{
+ enum PVRSRV_ERROR eError;
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX initialisation script part 1\n");
+ eError =
+ SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1,
+ SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXInitialise: SGXRunScript (part 1) failed (%d)",
+ eError);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "End of SGX initialisation script part 1\n");
+
+ SGXReset(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
+
+
+
+ *psDevInfo->pui32KernelCCBEventKicker = 0;
+#if defined(PDUMP)
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ sizeof(*psDevInfo->pui32KernelCCBEventKicker),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+#endif
+
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX initialisation script part 2\n");
+ eError =
+ SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2,
+ SGX_MAX_INIT_COMMANDS);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXInitialise: SGXRunScript (part 2) failed (%d)",
+ eError);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "End of SGX initialisation script part 2\n");
+
+ SGXStartTimer(psDevInfo, (IMG_BOOL)!bHardwareRecovery);
+
+ if (bHardwareRecovery) {
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+
+ if (PollForValueKM(&psSGXHostCtl->ui32InterruptClearFlags, 0,
+ PVRSRV_USSE_EDM_INTERRUPT_HWR,
+ MAX_HW_TIME_US / WAIT_TRY_COUNT, 1000) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXInitialise: "
+ "Wait for uKernel HW Recovery failed");
+ PVR_DBG_BREAK;
+ return PVRSRV_ERROR_RETRY;
+ }
+ }
+
+ PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset ==
+ psDevInfo->psKernelCCBCtl->ui32WriteOffset);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXDeinitialise(void *hDevCookie)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
+ hDevCookie;
+ enum PVRSRV_ERROR eError;
+
+ if (psDevInfo->pvRegsBaseKM == NULL)
+ return PVRSRV_OK;
+
+ eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asDeinitCommands,
+ SGX_MAX_DEINIT_COMMANDS);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXDeinitialise: SGXRunScript failed (%d)", eError);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ void *hKernelDevMemContext;
+ struct IMG_DEV_PHYADDR sPDDevPAddr;
+ u32 i;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = (struct PVRSRV_DEVICE_NODE *)
+ pvDeviceNode;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap =
+ psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+ enum PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("SGX Initialisation Part 1");
+
+ PDUMPCOMMENT("SGX Core Version Information: %s",
+ SGX_CORE_FRIENDLY_NAME);
+ PDUMPCOMMENT("SGX Core Revision Information: multi rev support");
+
+ if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGXDEV_INFO),
+ (void **)&psDevInfo, NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevInitSGXPart1 : Failed to alloc memory for DevInfo");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDevInfo, 0, sizeof(struct PVRSRV_SGXDEV_INFO));
+
+ psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
+ psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
+
+ psDeviceNode->pvDevice = (void *) psDevInfo;
+
+ psDevInfo->pvDeviceMemoryHeap = (void *) psDeviceMemoryHeap;
+
+ hKernelDevMemContext = BM_CreateContext(psDeviceNode, &sPDDevPAddr,
+ NULL, NULL);
+
+ psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
+
+ for (i = 0; i < psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++) {
+ void *hDevMemHeap;
+
+ switch (psDeviceMemoryHeap[i].DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ hDevMemHeap =
+ BM_CreateHeap(hKernelDevMemContext,
+ &psDeviceMemoryHeap[i]);
+
+ psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
+ break;
+ }
+ }
+ }
+
+ eError = MMU_BIFResetPDAlloc(psDevInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevInitSGX : Failed to alloc memory for BIF reset");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXGetInfoForSrvinitKM(void *hDevHandle,
+ struct SGX_BRIDGE_INFO_FOR_SRVINIT *psInitInfo)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ enum PVRSRV_ERROR eError;
+
+ PDUMPCOMMENT("SGXGetInfoForSrvinit");
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ psInitInfo->sPDDevPAddr = psDevInfo->sKernelPDDevPAddr;
+
+ eError =
+ PVRSRVGetDeviceMemHeapsKM(hDevHandle, &psInitInfo->asHeapInfo[0]);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXGetInfoForSrvinit: "
+ "PVRSRVGetDeviceMemHeapsKM failed (%d)",
+ eError);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR DevInitSGXPart2KM(struct PVRSRV_PER_PROCESS_DATA *psPerProc,
+ void *hDevHandle,
+ struct SGX_BRIDGE_INIT_INFO *psInitInfo)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ enum PVRSRV_ERROR eError;
+ struct SGX_DEVICE_MAP *psSGXDeviceMap;
+ enum PVR_POWER_STATE eDefaultPowerState;
+ u32 l;
+
+ PDUMPCOMMENT("SGX Initialisation Part 2");
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
+ "Failed to load EDM program");
+ goto failed_init_dev_info;
+ }
+
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (void **) &psSGXDeviceMap);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
+ "Failed to get device memory map!");
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ if (psSGXDeviceMap->pvRegsCpuVBase) {
+ psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
+ } else {
+ psDevInfo->pvRegsBaseKM =
+ OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
+ psSGXDeviceMap->ui32RegsSize,
+ PVRSRV_HAP_KERNEL_ONLY | PVRSRV_HAP_UNCACHED,
+ NULL);
+ if (!psDevInfo->pvRegsBaseKM) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevInitSGXPart2KM: Failed to map in regs\n");
+ return PVRSRV_ERROR_BAD_MAPPING;
+ }
+ }
+ psDevInfo->ui32RegSize = psSGXDeviceMap->ui32RegsSize;
+ psDevInfo->sRegsPhysBase = psSGXDeviceMap->sRegsSysPBase;
+
+ psDeviceNode->pvISRData = psDeviceNode;
+
+ PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
+
+ pvr_dev_lock();
+ l = readl(&psDevInfo->psSGXHostCtl->ui32PowerStatus);
+ l |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
+ writel(l, &psDevInfo->psSGXHostCtl->ui32PowerStatus);
+ pvr_dev_unlock();
+ eDefaultPowerState = PVRSRV_POWER_STATE_D3;
+
+ eError = PVRSRVRegisterPowerDevice(psDeviceNode->sDevId.ui32DeviceIndex,
+ SGXPrePowerStateExt,
+ SGXPostPowerStateExt,
+ SGXPreClockSpeedChange,
+ SGXPostClockSpeedChange,
+ (void *) psDeviceNode,
+ PVRSRV_POWER_STATE_D3,
+ eDefaultPowerState);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM: "
+ "failed to register device with power manager");
+ return eError;
+ }
+
+ OSMemSet(psDevInfo->psKernelCCB, 0,
+ sizeof(struct PVRSRV_SGX_KERNEL_CCB));
+ OSMemSet(psDevInfo->psKernelCCBCtl, 0,
+ sizeof(struct PVRSRV_SGX_CCB_CTL));
+ OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0,
+ sizeof(*psDevInfo->pui32KernelCCBEventKicker));
+ PDUMPCOMMENT("Initialise Kernel CCB");
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBMemInfo, 0,
+ sizeof(struct PVRSRV_SGX_KERNEL_CCB), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Control");
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBCtlMemInfo, 0,
+ sizeof(struct PVRSRV_SGX_CCB_CTL), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBCtlMemInfo));
+ PDUMPCOMMENT("Initialise Kernel CCB Event Kicker");
+ PDUMPMEM(NULL, psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ sizeof(*psDevInfo->pui32KernelCCBEventKicker),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
+
+ psDevInfo->hTimer = SGXOSTimerInit(psDeviceNode);
+ if (!psDevInfo->hTimer)
+ PVR_DPF(PVR_DBG_ERROR, "DevInitSGXPart2KM : "
+ "Failed to initialize HW recovery timer");
+
+ return PVRSRV_OK;
+
+failed_init_dev_info:
+ return eError;
+}
+
+static enum PVRSRV_ERROR DevDeInitSGX(void *pvDeviceNode)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode =
+ (struct PVRSRV_DEVICE_NODE *)pvDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ enum PVRSRV_ERROR eError;
+ u32 ui32Heap;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ struct SGX_DEVICE_MAP *psSGXDeviceMap;
+
+ if (!psDevInfo) {
+ PVR_DPF(PVR_DBG_ERROR, "DevDeInitSGX: Null DevInfo");
+ return PVRSRV_OK;
+ }
+ if (psDevInfo->hTimer) {
+ SGXOSTimerCancel(psDevInfo->hTimer);
+ SGXOSTimerDeInit(psDevInfo->hTimer);
+ psDevInfo->hTimer = NULL;
+ }
+
+ MMU_BIFResetPDFree(psDevInfo);
+
+ DeinitDevInfo(psDevInfo);
+
+
+ psDeviceMemoryHeap =
+ (struct DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
+ for (ui32Heap = 0;
+ ui32Heap < psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ ui32Heap++) {
+ switch (psDeviceMemoryHeap[ui32Heap].DevMemHeapType) {
+ case DEVICE_MEMORY_HEAP_KERNEL:
+ case DEVICE_MEMORY_HEAP_SHARED:
+ case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
+ {
+ if (psDeviceMemoryHeap[ui32Heap].hDevMemHeap !=
+ NULL)
+ BM_DestroyHeap(psDeviceMemoryHeap
+ [ui32Heap].hDevMemHeap);
+ break;
+ }
+ }
+ }
+
+ if (!pvr_put_ctx(psDeviceNode->sDevMemoryInfo.pBMKernelContext))
+ pr_err("%s: kernel context still in use, can't free it",
+ __func__);
+
+ eError = PVRSRVRemovePowerDevice(
+ ((struct PVRSRV_DEVICE_NODE *)pvDeviceNode)->
+ sDevId.ui32DeviceIndex);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ eError = SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
+ (void **)&psSGXDeviceMap);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DevDeInitSGX: Failed to get device memory map!");
+ return eError;
+ }
+
+ if (!psSGXDeviceMap->pvRegsCpuVBase)
+ if (psDevInfo->pvRegsBaseKM != NULL)
+ OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32RegSize,
+ PVRSRV_HAP_KERNEL_ONLY |
+ PVRSRV_HAP_UNCACHED,
+ NULL);
+
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
+
+ psDeviceNode->pvDevice = NULL;
+
+ if (psDeviceMemoryHeap != NULL)
+ OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+ sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
+ psDeviceNode->sDevMemoryInfo.ui32HeapCount,
+ psDeviceMemoryHeap, NULL);
+
+ return PVRSRV_OK;
+}
+
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+
+#define SGXMK_TRACE_BUFFER_SIZE 512
+
+static void dump_edm(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ u32 *trace_buffer =
+ psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
+ u32 last_code, write_offset;
+ int i;
+
+ last_code = *trace_buffer;
+ trace_buffer++;
+ write_offset = *trace_buffer;
+
+ pr_err("Last SGX microkernel status code: 0x%x\n", last_code);
+
+ trace_buffer++;
+ /* Dump the status values */
+
+ for (i = 0; i < SGXMK_TRACE_BUFFER_SIZE; i++) {
+ u32 *buf;
+ buf = trace_buffer + (((write_offset + i) %
+ SGXMK_TRACE_BUFFER_SIZE) * 4);
+ pr_err("(MKT%u) %8.8X %8.8X %8.8X %8.8X\n", i,
+ buf[2], buf[3], buf[1], buf[0]);
+ }
+}
+#else
+static void dump_edm(struct PVRSRV_SGXDEV_INFO *psDevInfo) {}
+#endif
+
+static void dump_process_info(struct PVRSRV_DEVICE_NODE *dev)
+{
+ struct PVRSRV_SGXDEV_INFO *dev_info = dev->pvDevice;
+ u32 page_dir = readl(dev_info->pvRegsBaseKM +
+ EUR_CR_BIF_DIR_LIST_BASE0);
+ struct BM_CONTEXT *bm_ctx;
+ struct RESMAN_CONTEXT *res_ctx = NULL;
+
+ bm_ctx = bm_find_context(dev->sDevMemoryInfo.pBMContext, page_dir);
+ if (bm_ctx)
+ res_ctx = pvr_get_resman_ctx(bm_ctx);
+
+ if (res_ctx) {
+ struct task_struct *tsk;
+ struct PVRSRV_PER_PROCESS_DATA *proc;
+ int pid;
+
+ proc = pvr_get_proc_by_ctx(res_ctx);
+ pid = proc->ui32PID;
+ rcu_read_lock();
+ tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
+ pr_err("PID = %d, process name = %s\n", pid, tsk->comm);
+ rcu_read_unlock();
+ }
+}
+
+static void dump_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+{
+ pr_err("EVENT_STATUS = 0x%08X\n"
+ "EVENT_STATUS2 = 0x%08X\n"
+ "BIF_CTRL = 0x%08X\n"
+ "BIF_INT_STAT = 0x%08X\n"
+ "BIF_MEM_REQ_STAT = 0x%08X\n"
+ "BIF_FAULT = 0x%08X\n"
+ "CLKGATECTL = 0x%08X\n",
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_EVENT_STATUS2),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_CTRL),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_INT_STAT),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_BIF_FAULT),
+ readl(psDevInfo->pvRegsBaseKM + EUR_CR_CLKGATECTL));
+}
+
+/* Should be called with pvr_lock held */
+void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+ u32 l;
+ int max_retries = 10;
+
+ BUG_ON(!pvr_is_locked());
+
+ l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
+ l |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
+ writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
+
+ pr_err("%s: SGX Hardware Recovery triggered\n", __func__);
+
+ dump_process_info(psDeviceNode);
+ dump_sgx_registers(psDevInfo);
+ dump_edm(psDevInfo);
+
+ PDUMPSUSPEND();
+
+ do {
+ eError = SGXInitialise(psDevInfo, IMG_TRUE);
+ if (eError != PVRSRV_ERROR_RETRY)
+ break;
+ } while (max_retries--);
+
+ if (eError != PVRSRV_OK) {
+ pr_err("%s: recovery failed (%d). Disabling the driver",
+ __func__, eError);
+ pvr_disable();
+
+ PDUMPRESUME();
+
+ return;
+ }
+
+ PDUMPRESUME();
+
+ SGXScheduleProcessQueues(psDeviceNode);
+
+ PVRSRVProcessQueues(IMG_TRUE);
+}
+
+static unsigned long sgx_reset_forced;
+
+static void SGXOSTimer(struct work_struct *work)
+{
+ struct timer_work_data *data = container_of(work,
+ struct timer_work_data,
+ work.work);
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = data->psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ static u32 ui32EDMTasks;
+ static u32 ui32LockupCounter;
+ static u32 ui32NumResets;
+ u32 ui32CurrentEDMTasks;
+ IMG_BOOL bLockup = IMG_FALSE;
+ IMG_BOOL bPoweredDown;
+
+ pvr_lock();
+
+ if (!data->armed || pvr_is_disabled()) {
+ pvr_unlock();
+ return;
+ }
+
+ psDevInfo->ui32TimeStamp++;
+
+#if defined(NO_HARDWARE)
+ bPoweredDown = IMG_TRUE;
+#else
+ bPoweredDown = (IMG_BOOL) !SGXIsDevicePowered(psDeviceNode);
+#endif
+
+ if (bPoweredDown) {
+ ui32LockupCounter = 0;
+ } else {
+ pvr_dev_lock();
+ ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32EDMTaskReg0);
+ if (psDevInfo->ui32EDMTaskReg1 != 0)
+ ui32CurrentEDMTasks ^=
+ OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ psDevInfo->ui32EDMTaskReg1);
+ if ((ui32CurrentEDMTasks == ui32EDMTasks) &&
+ (psDevInfo->ui32NumResets == ui32NumResets)) {
+ ui32LockupCounter++;
+ if (ui32LockupCounter == 3) {
+ ui32LockupCounter = 0;
+ PVR_DPF(PVR_DBG_ERROR, "SGXOSTimer() "
+ "detected SGX lockup (0x%x tasks)",
+ ui32EDMTasks);
+
+ bLockup = IMG_TRUE;
+ }
+ } else {
+ ui32LockupCounter = 0;
+ ui32EDMTasks = ui32CurrentEDMTasks;
+ ui32NumResets = psDevInfo->ui32NumResets;
+ }
+ pvr_dev_unlock();
+ }
+
+ bLockup |= cmpxchg(&sgx_reset_forced, 1, 0);
+
+ if (bLockup) {
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+ u32 l;
+
+ pvr_dev_lock();
+ l = readl(&psSGXHostCtl->ui32HostDetectedLockups);
+ l++;
+ writel(l, &psSGXHostCtl->ui32HostDetectedLockups);
+
+ HWRecoveryResetSGX(psDeviceNode);
+ pvr_dev_unlock();
+ }
+
+ queue_delayed_work(data->work_queue, &data->work,
+ msecs_to_jiffies(data->interval));
+
+ pvr_unlock();
+}
+
+struct timer_work_data *
+SGXOSTimerInit(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct timer_work_data *data;
+
+ data = kzalloc(sizeof(struct timer_work_data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ data->work_queue = create_workqueue("SGXOSTimer");
+ if (!data->work_queue) {
+ kfree(data);
+ return NULL;
+ }
+
+ data->interval = 150;
+ data->psDeviceNode = psDeviceNode;
+ INIT_DELAYED_WORK(&data->work, SGXOSTimer);
+
+ return data;
+}
+
+void SGXOSTimerDeInit(struct timer_work_data *data)
+{
+ data->armed = false;
+ destroy_workqueue(data->work_queue);
+ kfree(data);
+}
+
+enum PVRSRV_ERROR SGXOSTimerEnable(struct timer_work_data *data)
+{
+ if (!data)
+ return PVRSRV_ERROR_GENERIC;
+
+ if (queue_delayed_work(data->work_queue, &data->work,
+ msecs_to_jiffies(data->interval))) {
+ data->armed = true;
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+enum PVRSRV_ERROR SGXOSTimerCancel(struct timer_work_data *data)
+{
+ if (!data)
+ return PVRSRV_ERROR_GENERIC;
+
+ data->armed = false;
+ cancel_delayed_work(&data->work);
+
+ return PVRSRV_OK;
+}
+
+int sgx_force_reset(void)
+{
+ return !cmpxchg(&sgx_reset_forced, 0, 1);
+}
+
+static IMG_BOOL SGX_ISRHandler(void *pvData)
+{
+ IMG_BOOL bInterruptProcessed = IMG_FALSE;
+
+ {
+ u32 ui32EventStatus, ui32EventEnable;
+ u32 ui32EventClear = 0;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ if (pvData == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGX_ISRHandler: Invalid params\n");
+ return bInterruptProcessed;
+ }
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)pvData;
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ ui32EventStatus =
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ EUR_CR_EVENT_HOST_ENABLE);
+
+ gui32EventStatusServicesByISR = ui32EventStatus;
+
+ ui32EventStatus &= ui32EventEnable;
+
+ if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
+ ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_SW_EVENT_MASK;
+
+ if (ui32EventClear) {
+ bInterruptProcessed = IMG_TRUE;
+
+ ui32EventClear |=
+ EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
+ }
+ }
+
+ return bInterruptProcessed;
+}
+
+static void SGX_MISRHandler(void *pvData)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode =
+ (struct PVRSRV_DEVICE_NODE *)pvData;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+ u32 l1, l2;
+ int dev_idx;
+ enum PVRSRV_ERROR err;
+
+ dev_idx = psDeviceNode->sDevId.ui32DeviceIndex;
+
+ pvr_dev_lock();
+
+ err = PVRSRVSetDevicePowerStateKM(dev_idx, PVRSRV_POWER_STATE_D0);
+ BUG_ON(err != PVRSRV_OK);
+
+ l1 = readl(&psSGXHostCtl->ui32InterruptFlags);
+ l2 = readl(&psSGXHostCtl->ui32InterruptClearFlags);
+
+ if ((l1 & PVRSRV_USSE_EDM_INTERRUPT_HWR) &&
+ !(l2 & PVRSRV_USSE_EDM_INTERRUPT_HWR))
+ HWRecoveryResetSGX(psDeviceNode);
+
+ if (psDeviceNode->bReProcessDeviceCommandComplete)
+ SGXScheduleProcessQueues(psDeviceNode);
+
+ SGXTestActivePowerEvent(psDeviceNode);
+
+ pvr_dev_unlock();
+}
+
+enum PVRSRV_ERROR SGXRegisterDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ struct DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+
+ psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
+ psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
+
+ psDeviceNode->pfnInitDevice = DevInitSGXPart1;
+ psDeviceNode->pfnDeInitDevice = DevDeInitSGX;
+
+ psDeviceNode->pfnInitDeviceCompatCheck = SGXDevInitCompatCheck;
+
+ psDeviceNode->pfnMMUInitialise = MMU_Initialise;
+ psDeviceNode->pfnMMUFinalise = MMU_Finalise;
+ psDeviceNode->pfnMMUInsertHeap = MMU_InsertHeap;
+ psDeviceNode->pfnMMUCreate = MMU_Create;
+ psDeviceNode->pfnMMUDelete = MMU_Delete;
+ psDeviceNode->pfnMMUAlloc = MMU_Alloc;
+ psDeviceNode->pfnMMUFree = MMU_Free;
+ psDeviceNode->pfnMMUMapPages = MMU_MapPages;
+ psDeviceNode->pfnMMUMapShadow = MMU_MapShadow;
+ psDeviceNode->pfnMMUUnmapPages = MMU_UnmapPages;
+ psDeviceNode->pfnMMUMapScatter = MMU_MapScatter;
+ psDeviceNode->pfnMMUGetPhysPageAddr = MMU_GetPhysPageAddr;
+ psDeviceNode->pfnMMUGetPDDevPAddr = MMU_GetPDDevPAddr;
+
+ psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
+ psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
+
+ psDeviceNode->pfnDeviceCommandComplete = SGXCommandComplete;
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+
+ psDevMemoryInfo->ui32AddressSpaceSizeLog2 =
+ SGX_FEATURE_ADDRESS_SPACE_SIZE;
+
+ psDevMemoryInfo->ui32Flags = 0;
+ psDevMemoryInfo->ui32HeapCount = SGX_MAX_HEAP_ID;
+ psDevMemoryInfo->ui32SyncHeapID = SGX_SYNCINFO_HEAP_ID;
+
+ psDevMemoryInfo->ui32MappingHeapID = SGX_GENERAL_HEAP_ID;
+
+ if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
+ psDevMemoryInfo->ui32HeapCount,
+ (void **) &psDevMemoryInfo->psDeviceMemoryHeap,
+ NULL) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXRegisterDevice : "
+ "Failed to alloc memory for "
+ "struct DEVICE_MEMORY_HEAP_INFO");
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psDevMemoryInfo->psDeviceMemoryHeap, 0,
+ sizeof(struct DEVICE_MEMORY_HEAP_INFO) *
+ psDevMemoryInfo->ui32HeapCount);
+
+ psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
+
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_GENERAL_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32HeapSize =
+ SGX_GENERAL_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszName = "General";
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].pszBSName = "General BS";
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap[SGX_GENERAL_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_TADATA_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32HeapSize =
+ SGX_TADATA_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszName = "TA Data";
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].pszBSName = "TA Data BS";
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap[SGX_TADATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_KERNEL_CODE_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32HeapSize =
+ SGX_KERNEL_CODE_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszName = "Kernel Code";
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].pszBSName =
+ "Kernel Code BS";
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap[SGX_KERNEL_CODE_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_KERNEL_DATA_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32HeapSize =
+ SGX_KERNEL_DATA_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszName = "KernelData";
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].pszBSName = "KernelData BS";
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap[SGX_KERNEL_DATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_PIXELSHADER_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32HeapSize =
+ SGX_PIXELSHADER_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszName = "PixelShaderUSSE";
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].pszBSName =
+ "PixelShaderUSSE BS";
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap[SGX_PIXELSHADER_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_VERTEXSHADER_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32HeapSize =
+ SGX_VERTEXSHADER_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszName =
+ "VertexShaderUSSE";
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].pszBSName =
+ "VertexShaderUSSE BS";
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap[SGX_VERTEXSHADER_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32HeapSize =
+ SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszName =
+ "PDSPixelCodeData";
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].pszBSName =
+ "PDSPixelCodeData BS";
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap[SGX_PDSPIXEL_CODEDATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].sDevVAddrBase.
+ uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32HeapSize =
+ SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszName =
+ "PDSVertexCodeData";
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].pszBSName =
+ "PDSVertexCodeData BS";
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap[SGX_PDSVERTEX_CODEDATA_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_SYNCINFO_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32HeapSize =
+ SGX_SYNCINFO_HEAP_SIZE;
+
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_MULTI_PROCESS;
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszName = "CacheCoherent";
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].pszBSName = "CacheCoherent BS";
+
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
+
+ psDeviceMemoryHeap[SGX_SYNCINFO_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapID =
+ HEAP_ID(PVRSRV_DEVICE_TYPE_SGX, SGX_3DPARAMETERS_HEAP_ID);
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].sDevVAddrBase.uiAddr =
+ SGX_3DPARAMETERS_HEAP_BASE;
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32HeapSize =
+ SGX_3DPARAMETERS_HEAP_SIZE;
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszName = "3DParameters";
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].pszBSName =
+ "3DParameters BS";
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32Attribs =
+ PVRSRV_HAP_WRITECOMBINE | PVRSRV_MEM_RAM_BACKED_ALLOCATION |
+ PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].DevMemHeapType =
+ DEVICE_MEMORY_HEAP_PERCONTEXT;
+
+ psDeviceMemoryHeap[SGX_3DPARAMETERS_HEAP_ID].ui32DataPageSize =
+ SGX_MMU_PAGE_SIZE;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXGetClientInfoKM(void *hDevCookie,
+ struct SGX_CLIENT_INFO *psClientInfo)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)
+ ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psDevInfo->ui32ClientRefCount++;
+#ifdef PDUMP
+ if (psDevInfo->ui32ClientRefCount == 1)
+ psDevInfo->psKernelCCBInfo->ui32CCBDumpWOff = 0;
+#endif
+ psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
+
+ OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData,
+ sizeof(psClientInfo->asDevData));
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXDevInitCompatCheck(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ enum PVRSRV_ERROR eError;
+#if !defined(NO_HARDWARE)
+ u32 ui32BuildOptions, ui32BuildOptionsMismatch;
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+#endif
+
+ if (psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXDevInitCompatCheck: Device not of type SGX");
+ eError = PVRSRV_ERROR_INVALID_PARAMS;
+ goto exit;
+ }
+ psDevInfo = psDeviceNode->pvDevice;
+ psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
+#if !defined(NO_HARDWARE)
+
+ eError = SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXDevInitCompatCheck: "
+ "Unable to validate device DDK version");
+ goto exit;
+ }
+ psSGXFeatures =
+ &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->pvLinAddrKM))->
+ sSGXFeatures;
+ if ((psSGXFeatures->ui32DDKVersion !=
+ ((PVRVERSION_MAJ << 16) | (PVRVERSION_MIN << 8) |
+ PVRVERSION_BRANCH)) ||
+ (psSGXFeatures->ui32DDKBuild != PVRVERSION_BUILD)) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXDevInitCompatCheck: "
+ "Incompatible driver DDK revision (%ld)"
+ "/device DDK revision (%ld).",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
+ eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
+ goto exit;
+ } else {
+ PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
+ "driver DDK (%ld) and device DDK (%ld) match",
+ PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild);
+ }
+
+ ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
+ if (ui32BuildOptions != (SGX_BUILD_OPTIONS)) {
+ ui32BuildOptionsMismatch =
+ ui32BuildOptions ^ (SGX_BUILD_OPTIONS);
+ if (((SGX_BUILD_OPTIONS) & ui32BuildOptionsMismatch) != 0)
+ PVR_DPF(PVR_DBG_ERROR, "SGXInit: "
+ "Mismatch in driver and microkernel build "
+ "options; extra options present in driver: "
+ "(0x%lx)",
+ (SGX_BUILD_OPTIONS) &
+ ui32BuildOptionsMismatch);
+
+ if ((ui32BuildOptions & ui32BuildOptionsMismatch) != 0)
+ PVR_DPF(PVR_DBG_ERROR, "SGXInit: "
+ "Mismatch in driver and microkernel build "
+ "options; extra options present in "
+ "microkernel: (0x%lx)",
+ ui32BuildOptions & ui32BuildOptionsMismatch);
+ eError = PVRSRV_ERROR_BUILD_MISMATCH;
+ goto exit;
+ } else {
+ PVR_DPF(PVR_DBG_WARNING, "(Success) SGXInit: "
+ "Driver and microkernel build options match.");
+ }
+
+#endif
+ eError = PVRSRV_OK;
+exit:
+ return eError;
+}
+
+static
+enum PVRSRV_ERROR SGXGetBuildInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ enum PVRSRV_ERROR eError;
+ struct SGXMKIF_COMMAND sCommandData;
+ struct PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psDevInfo->psKernelSGXMiscMemInfo;
+
+ if (!psMemInfo->pvLinAddrKM) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXGetMiscInfoKM: Invalid address.");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
+ psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
+ psSGXFeatures = &psSGXMiscInfoInt->sSGXFeatures;
+
+ OSMemSet(psMemInfo->pvLinAddrKM, 0,
+ sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
+
+ sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+
+ OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
+
+ mb();
+
+ eError = SGXScheduleCCBCommandKM(psDeviceNode,
+ SGXMKIF_COMMAND_REQUEST_SGXMISCINFO,
+ &sCommandData, KERNEL_ID, 0);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXGetMiscInfoKM: SGXScheduleCCBCommandKM failed.");
+ return eError;
+ }
+
+#if !defined(NO_HARDWARE)
+ {
+ IMG_BOOL bTimeout = IMG_TRUE;
+
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if ((psSGXMiscInfoInt->
+ ui32MiscInfoFlags & PVRSRV_USSE_MISCINFO_READY) !=
+ 0) {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ if (bTimeout)
+ return PVRSRV_ERROR_TIMEOUT;
+ }
+#endif
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXGetMiscInfoKM(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct SGX_MISC_INFO *psMiscInfo,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ switch (psMiscInfo->eRequest) {
+ case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
+ {
+ psMiscInfo->uData.ui32SGXClockSpeed =
+ psDevInfo->ui32CoreClockSpeed;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SGXREV:
+ {
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psDevInfo->psKernelSGXMiscMemInfo;
+
+ SGXGetBuildInfoKM(psDevInfo, psDeviceNode);
+ psSGXFeatures =
+ &((struct PVRSRV_SGX_MISCINFO_INFO *)(psMemInfo->
+ pvLinAddrKM))->sSGXFeatures;
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
+ "Core 0x%lx, sw ID 0x%lx, "
+ "sw Rev 0x%lx\n",
+ psSGXFeatures->ui32CoreRev,
+ psSGXFeatures->ui32CoreIdSW,
+ psSGXFeatures->ui32CoreRevSW);
+ PVR_DPF(PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: "
+ "DDK version 0x%lx, DDK build 0x%lx\n",
+ psSGXFeatures->ui32DDKVersion,
+ psSGXFeatures->ui32DDKBuild);
+
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_DRIVER_SGXREV:
+ {
+ struct PVRSRV_KERNEL_MEM_INFO *psMemInfo =
+ psDevInfo->psKernelSGXMiscMemInfo;
+ struct PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+
+ psSGXFeatures = &((struct PVRSRV_SGX_MISCINFO_INFO *)(
+ psMemInfo->pvLinAddrKM))->sSGXFeatures;
+
+ OSMemSet(psMemInfo->pvLinAddrKM, 0,
+ sizeof(struct PVRSRV_SGX_MISCINFO_INFO));
+
+ psSGXFeatures->ui32DDKVersion =
+ (PVRVERSION_MAJ << 16) |
+ (PVRVERSION_MIN << 8) | PVRVERSION_BRANCH;
+ psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
+
+ psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
+ return PVRSRV_OK;
+ }
+
+ case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
+ {
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ unsigned ui32MatchingFlags;
+
+ if ((psMiscInfo->uData.ui32NewHWPerfStatus &
+ ~(PVRSRV_SGX_HWPERF_GRAPHICS_ON |
+ PVRSRV_SGX_HWPERF_MK_EXECUTION_ON)) != 0) {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ pvr_dev_lock();
+ ui32MatchingFlags = readl(&psDevInfo->
+ psSGXHostCtl->ui32HWPerfFlags);
+ ui32MatchingFlags &=
+ psMiscInfo->uData.ui32NewHWPerfStatus;
+ if ((ui32MatchingFlags & PVRSRV_SGX_HWPERF_GRAPHICS_ON)
+ == 0UL) {
+ psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffff;
+ }
+ if ((ui32MatchingFlags &
+ PVRSRV_SGX_HWPERF_MK_EXECUTION_ON) == 0UL) {
+ psHWPerfCB->ui32OrdinalMK_EXECUTION =
+ 0xffffffffUL;
+ }
+
+
+ writel(psMiscInfo->uData.ui32NewHWPerfStatus,
+ &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ pvr_dev_unlock();
+#if defined(PDUMP)
+ PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
+ "SGX ukernel HWPerf status %u\n",
+ readl(&psDevInfo->psSGXHostCtl->
+ ui32HWPerfFlags));
+ PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL,
+ ui32HWPerfFlags),
+ sizeof(psDevInfo->psSGXHostCtl->
+ ui32HWPerfFlags),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->
+ psKernelSGXHostCtlMemInfo));
+#endif
+
+ return PVRSRV_OK;
+ }
+ case SGX_MISC_INFO_REQUEST_HWPERF_CB_ON:
+ {
+
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ u32 l;
+
+ psHWPerfCB->ui32OrdinalGRAPHICS = 0xffffffffUL;
+
+ pvr_dev_lock();;
+ l = readl(&psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ l |= PVRSRV_SGX_HWPERF_GRAPHICS_ON;
+ writel(l, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ pvr_dev_unlock();
+
+ return PVRSRV_OK;
+ }
+ case SGX_MISC_INFO_REQUEST_HWPERF_CB_OFF:
+ {
+ pvr_dev_lock();
+ writel(0, &psDevInfo->psSGXHostCtl->ui32HWPerfFlags);
+ pvr_dev_unlock();
+
+ return PVRSRV_OK;
+ }
+ case SGX_MISC_INFO_REQUEST_HWPERF_RETRIEVE_CB:
+ {
+ struct SGX_MISC_INFO_HWPERF_RETRIEVE_CB *psRetrieve =
+ &psMiscInfo->uData.sRetrieveCB;
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ unsigned i;
+
+ for (i = 0;
+ psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff
+ && i < psRetrieve->ui32ArraySize; i++) {
+ struct SGXMKIF_HWPERF_CB_ENTRY *psData =
+ &psHWPerfCB->psHWPerfCBData[psHWPerfCB->
+ ui32Roff];
+
+ psRetrieve->psHWPerfData[i].ui32FrameNo =
+ psData->ui32FrameNo;
+ psRetrieve->psHWPerfData[i].ui32Type =
+ (psData->ui32Type &
+ PVRSRV_SGX_HWPERF_TYPE_OP_MASK);
+ psRetrieve->psHWPerfData[i].ui32StartTime =
+ psData->ui32Time;
+ psRetrieve->psHWPerfData[i].ui32StartTimeWraps =
+ psData->ui32TimeWraps;
+ psRetrieve->psHWPerfData[i].ui32EndTime =
+ psData->ui32Time;
+ psRetrieve->psHWPerfData[i].ui32EndTimeWraps =
+ psData->ui32TimeWraps;
+ psRetrieve->psHWPerfData[i].ui32ClockSpeed =
+ psDevInfo->ui32CoreClockSpeed;
+ psRetrieve->psHWPerfData[i].ui32TimeMax =
+ psDevInfo->ui32uKernelTimerClock;
+ psHWPerfCB->ui32Roff =
+ (psHWPerfCB->ui32Roff + 1) &
+ (SGXMKIF_HWPERF_CB_SIZE - 1);
+ }
+ psRetrieve->ui32DataCount = i;
+ psRetrieve->ui32Time = OSClockus();
+ return PVRSRV_OK;
+ }
+ default:
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+}
+
+enum PVRSRV_ERROR SGXReadDiffCountersKM(void *hDevHandle, u32 ui32Reg,
+ u32 *pui32Old, IMG_BOOL bNew, u32 ui32New,
+ u32 ui32NewReset, u32 ui32CountersReg,
+ u32 *pui32Time, IMG_BOOL *pbActive,
+ struct PVRSRV_SGXDEV_DIFF_INFO *psDiffs)
+{
+ struct SYS_DATA *psSysData;
+ struct PVRSRV_POWER_DEV *psPowerDevice;
+ IMG_BOOL bPowered = IMG_FALSE;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ if (bNew)
+ psDevInfo->ui32HWGroupRequested = ui32New;
+ psDevInfo->ui32HWReset |= ui32NewReset;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return PVRSRV_ERROR_GENERIC;
+
+ psPowerDevice = psSysData->psPowerDeviceList;
+ while (psPowerDevice) {
+ if (psPowerDevice->ui32DeviceIndex ==
+ psDeviceNode->sDevId.ui32DeviceIndex) {
+ bPowered =
+ (IMG_BOOL)(psPowerDevice->eCurrentPowerState ==
+ PVRSRV_POWER_STATE_D0);
+ break;
+ }
+
+ psPowerDevice = psPowerDevice->psNext;
+ }
+
+ *pbActive = bPowered;
+
+ pvr_dev_lock();
+
+ {
+ struct PVRSRV_SGXDEV_DIFF_INFO sNew,
+ *psPrev = &psDevInfo->sDiffInfo;
+ u32 i;
+
+ sNew.ui32Time[0] = OSClockus();
+ *pui32Time = sNew.ui32Time[0];
+ if (sNew.ui32Time[0] != psPrev->ui32Time[0] && bPowered) {
+
+ *pui32Old =
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32Reg);
+
+ for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
+ sNew.aui32Counters[i] =
+ OSReadHWReg(psDevInfo->pvRegsBaseKM,
+ ui32CountersReg + (i * 4));
+ }
+
+ if (psDevInfo->ui32HWGroupRequested != *pui32Old) {
+ if (psDevInfo->ui32HWReset != 0) {
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ ui32Reg,
+ psDevInfo->
+ ui32HWGroupRequested |
+ psDevInfo->ui32HWReset);
+ psDevInfo->ui32HWReset = 0;
+ }
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Reg,
+ psDevInfo->ui32HWGroupRequested);
+ }
+
+ sNew.ui32Marker[0] = psDevInfo->ui32KickTACounter;
+ sNew.ui32Marker[1] = psDevInfo->ui32KickTARenderCounter;
+
+ sNew.ui32Time[1] = readl(
+ &psDevInfo->psSGXHostCtl->ui32TimeWraps);
+
+ for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i) {
+ psDiffs->aui32Counters[i] =
+ sNew.aui32Counters[i] -
+ psPrev->aui32Counters[i];
+ }
+
+ psDiffs->ui32Marker[0] =
+ sNew.ui32Marker[0] - psPrev->ui32Marker[0];
+ psDiffs->ui32Marker[1] =
+ sNew.ui32Marker[1] - psPrev->ui32Marker[1];
+
+ psDiffs->ui32Time[0] =
+ sNew.ui32Time[0] - psPrev->ui32Time[0];
+ psDiffs->ui32Time[1] =
+ sNew.ui32Time[1] - psPrev->ui32Time[1];
+
+ *psPrev = sNew;
+ } else {
+ for (i = 0; i < PVRSRV_SGX_DIFF_NUM_COUNTERS; ++i)
+ psDiffs->aui32Counters[i] = 0;
+
+ psDiffs->ui32Marker[0] = 0;
+ psDiffs->ui32Marker[1] = 0;
+
+ psDiffs->ui32Time[0] = 0;
+ psDiffs->ui32Time[1] = 0;
+ }
+ }
+
+ SGXTestActivePowerEvent(psDeviceNode);
+
+ pvr_dev_unlock();
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXReadHWPerfCBKM(void *hDevHandle, u32 ui32ArraySize,
+ struct PVRSRV_SGX_HWPERF_CB_ENTRY *psClientHWPerfEntry,
+ u32 *pui32DataCount, u32 *pui32ClockSpeed,
+ u32 *pui32HostTimeStamp)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct SGXMKIF_HWPERF_CB *psHWPerfCB =
+ psDevInfo->psKernelHWPerfCBMemInfo->pvLinAddrKM;
+ unsigned i;
+
+ for (i = 0;
+ psHWPerfCB->ui32Woff != psHWPerfCB->ui32Roff && i < ui32ArraySize;
+ i++) {
+ struct SGXMKIF_HWPERF_CB_ENTRY *psMKPerfEntry =
+ &psHWPerfCB->psHWPerfCBData[psHWPerfCB->ui32Roff];
+
+ psClientHWPerfEntry[i].ui32FrameNo = psMKPerfEntry->ui32FrameNo;
+ psClientHWPerfEntry[i].ui32Type = psMKPerfEntry->ui32Type;
+ psClientHWPerfEntry[i].ui32Ordinal = psMKPerfEntry->ui32Ordinal;
+ psClientHWPerfEntry[i].ui32Clocksx16 =
+ SGXConvertTimeStamp(psDevInfo, psMKPerfEntry->ui32TimeWraps,
+ psMKPerfEntry->ui32Time);
+ OSMemCopy(&psClientHWPerfEntry[i].ui32Counters[0],
+ &psMKPerfEntry->ui32Counters[0],
+ sizeof(psMKPerfEntry->ui32Counters));
+
+ psHWPerfCB->ui32Roff =
+ (psHWPerfCB->ui32Roff + 1) & (SGXMKIF_HWPERF_CB_SIZE - 1);
+ }
+
+ *pui32DataCount = i;
+ *pui32ClockSpeed = psDevInfo->ui32CoreClockSpeed;
+ *pui32HostTimeStamp = OSClockus();
+
+ return eError;
+}
diff --git a/drivers/gpu/pvr/sgxkick.c b/drivers/gpu/pvr/sgxkick.c
new file mode 100644
index 00000000000..045de0fc764
--- /dev/null
+++ b/drivers/gpu/pvr/sgxkick.c
@@ -0,0 +1,521 @@
+/**********************************************************************
+ *
+ * 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 "sgxinfo.h"
+#include "sgxinfokm.h"
+#if defined(PDUMP)
+#include "sgxapi_km.h"
+#include "pdump_km.h"
+#endif
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+enum PVRSRV_ERROR SGXDoKickKM(void *hDevHandle, struct SGX_CCB_KICK *psCCBKick,
+ int max_3dstat_vals)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->hCCBKernelMemInfo;
+ struct SGXMKIF_CMDTA_SHARED *psTACmd;
+ u32 i;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo;
+
+ psDeviceNode = (struct PVRSRV_DEVICE_NODE *)hDevHandle;
+ psDevInfo = (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+
+ if (psCCBKick->bKickRender)
+ ++psDevInfo->ui32KickTARenderCounter;
+ ++psDevInfo->ui32KickTACounter;
+
+ if (!CCB_OFFSET_IS_VALID
+ (struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick,
+ ui32CCBOffset)) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXDoKickKM: Invalid CCB offset");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ psTACmd =
+ CCB_DATA_FROM_OFFSET(struct SGXMKIF_CMDTA_SHARED, psCCBMemInfo,
+ psCCBKick, ui32CCBOffset);
+
+ if (psCCBKick->hTA3DSyncInfo) {
+ struct PVRSRV_DEVICE_SYNC_OBJECT *ta3d_dep;
+
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+ ta3d_dep = &psTACmd->sTA3DDependency;
+ /*
+ * Ugly hack to account for the two possible sizes of
+ * struct SGXMKIF_CMDTA_SHARED which is based on the
+ * corresponding IOCTL ABI version used.
+ */
+ if (max_3dstat_vals != SGX_MAX_3D_STATUS_VALS)
+ ta3d_dep = (struct PVRSRV_DEVICE_SYNC_OBJECT *)
+ ((u8 *)ta3d_dep - sizeof(struct CTL_STATUS) *
+ (SGX_MAX_3D_STATUS_VALS - max_3dstat_vals));
+
+ ta3d_dep->sWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ ta3d_dep->ui32WriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if (psCCBKick->bTADependency)
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ if (psCCBKick->hTASyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psCCBKick->hTASyncInfo;
+
+ psTACmd->sTATQSyncReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->sTATQSyncWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui32TATQSyncReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui32TATQSyncWriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psCCBKick->h3DSyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psCCBKick->h3DSyncInfo;
+
+ psTACmd->s3DTQSyncReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ psTACmd->s3DTQSyncWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psTACmd->ui323DTQSyncReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+ psTACmd->ui323DTQSyncWriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
+ if (psCCBKick->ui32NumTAStatusVals != 0) {
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psCCBKick->ahTAStatusSyncInfo[i];
+
+ psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psTACmd->sCtlTAStatusInfo[i].ui32StatusValue =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+ }
+
+ psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
+ if (psCCBKick->ui32Num3DStatusVals != 0) {
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ah3DStatusSyncInfo[i];
+
+ psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psTACmd->sCtl3DStatusInfo[i].ui32StatusValue =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+ }
+
+ psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
+ for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ahSrcKernelSyncInfo[i];
+
+ psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ }
+
+ if (psCCBKick->bFirstKickOrResume &&
+ psCCBKick->ui32NumDstSyncObjects > 0) {
+ struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
+ hKernelHWSyncListMemInfo;
+ struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
+ psHWDstSyncListMemInfo->pvLinAddrKM;
+ u32 ui32NumDstSyncs = psCCBKick->ui32NumDstSyncObjects;
+
+ PVR_ASSERT(((struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
+ hKernelHWSyncListMemInfo)->ui32AllocSize >=
+ (sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST) +
+ (sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT) *
+ ui32NumDstSyncs)));
+
+ psHWDeviceSyncList->ui32NumSyncObjects = ui32NumDstSyncs;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()) {
+ PDUMPCOMMENT("HWDeviceSyncList for TACmd\r\n");
+ PDUMPMEM(NULL,
+ psHWDstSyncListMemInfo, 0,
+ sizeof(struct SGXMKIF_HWDEVICE_SYNC_LIST),
+ 0, MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+#endif
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ sDstSyncHandle;
+ i = 0;
+ if (psSyncInfo) {
+ psHWDeviceSyncList->asSyncData[i].
+ sWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+ psHWDeviceSyncList->asSyncData[i].
+ sReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+
+ psHWDeviceSyncList->asSyncData[i].
+ ui32ReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psHWDeviceSyncList->asSyncData[i].
+ ui32WriteOpsPendingVal =
+ psSyncInfo->psSyncData->
+ ui32WriteOpsPending++;
+
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()) {
+ u32 ui32ModifiedValue;
+ u32 ui32SyncOffset = offsetof(
+ struct SGXMKIF_HWDEVICE_SYNC_LIST,
+ asSyncData) + (i *
+ sizeof(
+ struct PVRSRV_DEVICE_SYNC_OBJECT));
+ u32 ui32WOpsOffset = ui32SyncOffset +
+ offsetof(
+ struct PVRSRV_DEVICE_SYNC_OBJECT,
+ ui32WriteOpsPendingVal);
+ u32 ui32ROpsOffset = ui32SyncOffset +
+ offsetof(
+ struct PVRSRV_DEVICE_SYNC_OBJECT,
+ ui32ReadOpsPendingVal);
+
+ PDUMPCOMMENT("HWDeviceSyncObject for RT: "
+ "%i\r\n", i);
+
+ PDUMPMEM(NULL, psHWDstSyncListMemInfo,
+ ui32SyncOffset, sizeof(
+ struct PVRSRV_DEVICE_SYNC_OBJECT),
+ 0, MAKEUNIQUETAG(
+ psHWDstSyncListMemInfo));
+
+ if ((psSyncInfo->psSyncData->
+ ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal == 0)) {
+
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n",
+ i);
+ PDUMPMEM(&psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(struct
+ PVRSRV_SYNC_DATA,
+ ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->
+ ui32ReadOpsComplete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->
+ psSyncDataMemInfoKM));
+
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->
+ ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(struct PVRSRV_SYNC_DATA,
+ ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->
+ ui32WriteOpsComplete),
+ 0, MAKEUNIQUETAG(psSyncInfo->
+ psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+
+ ui32ModifiedValue = psSyncInfo->psSyncData->
+ ui32LastOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify RT %d WOpPendingVal "
+ "in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psHWDstSyncListMemInfo, ui32WOpsOffset,
+ sizeof(u32), 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ PDUMPCOMMENT("Modify RT %d ROpsPendingVal "
+ "in HWDevSyncList\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal,
+ psHWDstSyncListMemInfo,
+ ui32ROpsOffset, sizeof(u32), 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+ }
+#endif
+ } else {
+ psHWDeviceSyncList->asSyncData[i].
+ sWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psHWDeviceSyncList->asSyncData[i].
+ sReadOpsCompleteDevVAddr.uiAddr = 0;
+
+ psHWDeviceSyncList->asSyncData[i].
+ ui32ReadOpsPendingVal = 0;
+ psHWDeviceSyncList->asSyncData[i].
+ ui32WriteOpsPendingVal = 0;
+ }
+ }
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM()) {
+ PDUMPCOMMENT("Shared part of TA command\r\n");
+
+ PDUMPMEM(psTACmd, psCCBMemInfo, psCCBKick->ui32CCBDumpWOff,
+ sizeof(struct SGXMKIF_CMDTA_SHARED), 0,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
+ u32 ui32ModifiedValue;
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ahSrcKernelSyncInfo[i];
+
+ if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
+ (psSyncInfo->psSyncData->ui32LastReadOpDumpVal ==
+ 0)) {
+ PDUMPCOMMENT("Init RT ROpsComplete\r\n", i);
+ PDUMPMEM(&psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(struct PVRSRV_SYNC_DATA,
+ ui32ReadOpsComplete),
+ sizeof(psSyncInfo->psSyncData->
+ ui32ReadOpsComplete), 0,
+ MAKEUNIQUETAG(psSyncInfo->
+ psSyncDataMemInfoKM));
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->
+ ui32LastOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(struct PVRSRV_SYNC_DATA,
+ ui32WriteOpsComplete),
+ sizeof(psSyncInfo->psSyncData->
+ ui32WriteOpsComplete), 0,
+ MAKEUNIQUETAG(psSyncInfo->
+ psSyncDataMemInfoKM));
+ }
+
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ ui32ModifiedValue =
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal - 1;
+
+ PDUMPCOMMENT("Modify SrcSync %d ROpsPendingVal\r\n", i);
+
+ PDUMPMEM(&ui32ModifiedValue,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_CMDTA_SHARED,
+ asSrcSyncs) +
+ (i *
+ sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
+ offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
+ ui32ReadOpsPendingVal), sizeof(u32),
+ 0, MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Modify SrcSync %d WOpPendingVal\r\n", i);
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_CMDTA_SHARED,
+ asSrcSyncs) +
+ (i *
+ sizeof(struct PVRSRV_DEVICE_SYNC_OBJECT)) +
+ offsetof(struct PVRSRV_DEVICE_SYNC_OBJECT,
+ ui32WriteOpsPendingVal), sizeof(u32),
+ 0, MAKEUNIQUETAG(psCCBMemInfo));
+
+ }
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ahTAStatusSyncInfo[i];
+ PDUMPCOMMENT("Modify TA status value in TA cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_CMDTA_SHARED,
+ sCtlTAStatusInfo[i].ui32StatusValue),
+ sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psCCBKick->ah3DStatusSyncInfo[i];
+
+ PDUMPCOMMENT("Modify 3D status value in TA cmd\r\n");
+
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psCCBKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_CMDTA_SHARED,
+ sCtl3DStatusInfo[i].ui32StatusValue),
+ sizeof(u32), 0, MAKEUNIQUETAG(psCCBMemInfo));
+ }
+ }
+#endif
+
+ /* to aid in determining the next power down delay */
+ sgx_mark_new_command(psDeviceNode);
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, psCCBKick->eCommand,
+ &psCCBKick->sCommand, KERNEL_ID, 0);
+ if (eError == PVRSRV_ERROR_RETRY) {
+ if (psCCBKick->bFirstKickOrResume &&
+ psCCBKick->ui32NumDstSyncObjects > 0) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psCCBKick->sDstSyncHandle;
+ if (psSyncInfo) {
+ psSyncInfo->psSyncData->ui32WriteOpsPending--;
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM())
+ psSyncInfo->psSyncData->
+ ui32LastOpDumpVal--;
+#endif
+ }
+ }
+
+ for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ahSrcKernelSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsPending--;
+ }
+
+ return eError;
+ } else if (PVRSRV_OK != eError) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXDoKickKM: SGXScheduleCCBCommandKM failed.");
+ return eError;
+ }
+
+#if defined(NO_HARDWARE)
+
+ if (psCCBKick->hTA3DSyncInfo) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
+
+ if (psCCBKick->bTADependency) {
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+
+ if (psCCBKick->hTASyncInfo != NULL) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ if (psCCBKick->h3DSyncInfo != NULL) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ahTAStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete =
+ psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
+ }
+
+ for (i = 0; i < psCCBKick->ui32NumSrcSyncs; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ahSrcKernelSyncInfo[i];
+
+ psSyncInfo->psSyncData->ui32ReadOpsComplete =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ }
+
+ if (psCCBKick->bTerminateOrAbort) {
+ if (psCCBKick->ui32NumDstSyncObjects > 0) {
+ struct PVRSRV_KERNEL_MEM_INFO *psHWDstSyncListMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psCCBKick->
+ hKernelHWSyncListMemInfo;
+ struct SGXMKIF_HWDEVICE_SYNC_LIST *psHWDeviceSyncList =
+ psHWDstSyncListMemInfo->pvLinAddrKM;
+
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ sDstSyncHandle;
+ if (psSyncInfo)
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psHWDeviceSyncList->asSyncData[0].
+ ui32WriteOpsPendingVal + 1;
+ }
+
+ for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->
+ ah3DStatusSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete =
+ psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
+ }
+ }
+#endif
+
+ return eError;
+}
diff --git a/drivers/gpu/pvr/sgxmmu.h b/drivers/gpu/pvr/sgxmmu.h
new file mode 100644
index 00000000000..d633e299e67
--- /dev/null
+++ b/drivers/gpu/pvr/sgxmmu.h
@@ -0,0 +1,57 @@
+/**********************************************************************
+ *
+ * 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(__SGXMMU_KM_H__)
+#define __SGXMMU_KM_H__
+
+#define SGX_MMU_PAGE_SHIFT 12
+#define SGX_MMU_PAGE_SIZE (1UL << SGX_MMU_PAGE_SHIFT)
+#define SGX_MMU_PAGE_MASK (SGX_MMU_PAGE_SIZE - 1UL)
+
+#define SGX_MMU_PD_SHIFT 10
+#define SGX_MMU_PD_SIZE (1UL << SGX_MMU_PD_SHIFT)
+#define SGX_MMU_PD_MASK 0xFFC00000UL
+
+#define SGX_MMU_PDE_ADDR_MASK 0xFFFFF000UL
+#define SGX_MMU_PDE_VALID 0x00000001UL
+#define SGX_MMU_PDE_PAGE_SIZE_4K 0x00000000UL
+#define SGX_MMU_PDE_WRITEONLY 0x00000002UL
+#define SGX_MMU_PDE_READONLY 0x00000004UL
+#define SGX_MMU_PDE_CACHECONSISTENT 0x00000008UL
+#define SGX_MMU_PDE_EDMPROTECT 0x00000010UL
+
+#define SGX_MMU_PT_SHIFT 10
+#define SGX_MMU_PT_SIZE (1UL << SGX_MMU_PT_SHIFT)
+#define SGX_MMU_PT_MASK 0x003FF000UL
+
+#define SGX_MMU_PTE_ADDR_MASK 0xFFFFF000UL
+#define SGX_MMU_PTE_VALID 0x00000001UL
+#define SGX_MMU_PTE_WRITEONLY 0x00000002UL
+#define SGX_MMU_PTE_READONLY 0x00000004UL
+#define SGX_MMU_PTE_CACHECONSISTENT 0x00000008UL
+#define SGX_MMU_PTE_EDMPROTECT 0x00000010UL
+
+#endif
diff --git a/drivers/gpu/pvr/sgxpower.c b/drivers/gpu/pvr/sgxpower.c
new file mode 100644
index 00000000000..899613ff245
--- /dev/null
+++ b/drivers/gpu/pvr/sgxpower.c
@@ -0,0 +1,488 @@
+/**********************************************************************
+ *
+ * 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 <linux/io.h>
+#include <linux/sched.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sgxapi_km.h"
+#include "sgxinfokm.h"
+#include "sgxutils.h"
+#include "pdump_km.h"
+
+#define MS_TO_NS(x) ((x) * 1000000ULL)
+#define SGX_CMD_BURST_THRESHOLD_NS MS_TO_NS(3)
+#define SGX_CMD_BURST_MAX_SIZE 4
+#define SGX_POWER_DOWN_DELAY_LONG_MS 4
+#define SGX_POWER_DOWN_DELAY_SHORT_MS 0
+
+enum PVR_DEVICE_POWER_STATE {
+
+ PVR_DEVICE_POWER_STATE_ON = 0,
+ PVR_DEVICE_POWER_STATE_IDLE = 1,
+ PVR_DEVICE_POWER_STATE_OFF = 2,
+
+ PVR_DEVICE_POWER_STATE_FORCE_I32 = 0x7fffffff
+};
+
+static enum PVR_DEVICE_POWER_STATE MapDevicePowerState(enum PVR_POWER_STATE
+ ePowerState)
+{
+ enum PVR_DEVICE_POWER_STATE eDevicePowerState;
+
+ switch (ePowerState) {
+ case PVRSRV_POWER_STATE_D0:
+ {
+ eDevicePowerState = PVR_DEVICE_POWER_STATE_ON;
+ break;
+ }
+ case PVRSRV_POWER_STATE_D3:
+ {
+ eDevicePowerState = PVR_DEVICE_POWER_STATE_OFF;
+ break;
+ }
+ default:
+ {
+ PVR_DPF(PVR_DBG_ERROR,
+ "MapDevicePowerState: Invalid state: %ld",
+ ePowerState);
+ eDevicePowerState = PVR_DEVICE_POWER_STATE_FORCE_I32;
+ PVR_DBG_BREAK;
+ }
+ }
+
+ return eDevicePowerState;
+}
+
+static void sgx_set_pwrdown_delay(struct PVRSRV_DEVICE_NODE *node,
+ unsigned ukernel_freq, int msec)
+{
+ struct PVRSRV_SGXDEV_INFO *dev_info = node->pvDevice;
+ unsigned delay;
+
+ delay = ukernel_freq * msec / 1000 + 1;
+ if (dev_info->power_down_delay != delay) {
+ writel(delay,
+ &dev_info->psSGXHostCtl->ui32ActivePowManSampleRate);
+ dev_info->power_down_delay = delay;
+ }
+}
+
+static int sgx_calc_power_down_delay(struct PVRSRV_DEVICE_NODE *node)
+{
+ struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
+
+ /*
+ * Set the power down delay to short if the command to be executed is
+ * the last one in the burst, except if the burst size is at the
+ * maximum.
+ */
+ if (info->burst_size < SGX_CMD_BURST_MAX_SIZE &&
+ info->burst_cnt == info->burst_size)
+ return SGX_POWER_DOWN_DELAY_SHORT_MS;
+ else
+ return SGX_POWER_DOWN_DELAY_LONG_MS;
+
+}
+
+void sgx_mark_new_command(struct PVRSRV_DEVICE_NODE *node)
+{
+ struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
+ struct SGX_TIMING_INFORMATION tinfo = { 0 };
+ unsigned long long cmd_start;
+ bool new_burst = false;
+
+ cmd_start = cpu_clock(smp_processor_id());
+
+ if (unlikely(info->last_idle == info->burst_start)) {
+ /*
+ * This is the initial case, when we haven't yet any commands
+ * issued.
+ */
+ new_burst = true;
+ } else {
+ /*
+ * If the last idle occurred after the current burst started
+ * and the time since the idle is greater than the threshold
+ * allowed for delays within a burst then this is a new burst.
+ */
+ if (time_after64(info->last_idle, info->burst_start) &&
+ cmd_start - info->last_idle > SGX_CMD_BURST_THRESHOLD_NS)
+ new_burst = true;
+ }
+
+ if (new_burst) {
+ info->burst_start = cmd_start;
+ /*
+ * We predict the length of this new burst to be that of the
+ * previous burst.
+ */
+ info->burst_size = info->burst_cnt;
+ info->burst_cnt = 0;
+ } else if (info->burst_cnt < SGX_CMD_BURST_MAX_SIZE) {
+ info->burst_cnt++;
+ }
+
+ SysGetSGXTimingInformation(&tinfo);
+ sgx_set_pwrdown_delay(node, tinfo.ui32uKernelFreq,
+ sgx_calc_power_down_delay(node));
+}
+
+void sgx_mark_power_down(struct PVRSRV_DEVICE_NODE *node)
+{
+ struct PVRSRV_SGXDEV_INFO *info = node->pvDevice;
+
+ info->last_idle = cpu_clock(smp_processor_id());
+ /*
+ * After the last command completes power down happens in a delayed
+ * manner. The current value of this delay is in power_down_delay.
+ * To get the command complete time - which is the actual idle start
+ * time - we have to deduct the amount of delay from the current time.
+ */
+ info->last_idle -= MS_TO_NS(info->power_down_delay);
+}
+
+static void SGXGetTimingInfo(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct SGX_TIMING_INFORMATION sSGXTimingInfo = { 0 };
+ struct timer_work_data *data = psDevInfo->hTimer;
+
+ SysGetSGXTimingInformation(&sSGXTimingInfo);
+
+ if (data) {
+ BUG_ON(data->armed);
+ /*
+ * The magic calculation below sets the hardware lock-up
+ * detection and recovery timer interval to ~150msecs.
+ * The interval length will be scaled based on the SGX
+ * functional clock frequency. The higher the frequency
+ * the shorter the interval and vice versa.
+ */
+ data->interval = 150 * SYS_SGX_PDS_TIMER_FREQ /
+ sSGXTimingInfo.ui32uKernelFreq;
+ }
+
+ writel(sSGXTimingInfo.ui32uKernelFreq /
+ sSGXTimingInfo.ui32HWRecoveryFreq,
+ &psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate);
+
+ psDevInfo->ui32CoreClockSpeed = sSGXTimingInfo.ui32CoreClockSpeed;
+ psDevInfo->ui32uKernelTimerClock =
+ sSGXTimingInfo.ui32CoreClockSpeed /
+ sSGXTimingInfo.ui32uKernelFreq;
+
+ sgx_set_pwrdown_delay(psDeviceNode, sSGXTimingInfo.ui32uKernelFreq,
+ sgx_calc_power_down_delay(psDeviceNode));
+}
+
+void SGXStartTimer(struct PVRSRV_SGXDEV_INFO *psDevInfo, IMG_BOOL bStartOSTimer)
+{
+ u32 ui32RegVal;
+
+ ui32RegVal =
+ EUR_CR_EVENT_TIMER_ENABLE_MASK | psDevInfo->ui32uKernelTimerClock;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_TIMER, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_EVENT_TIMER, ui32RegVal,
+ PDUMP_FLAGS_CONTINUOUS);
+
+ if (bStartOSTimer) {
+ enum PVRSRV_ERROR eError;
+
+ eError = SGXOSTimerEnable(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK)
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXStartTimer : Failed to enable host timer");
+ }
+}
+
+static void SGXPollForClockGating(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ u32 ui32Register,
+ u32 ui32RegisterValue, char *pszComment)
+{
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+ PVR_UNREFERENCED_PARAMETER(ui32Register);
+ PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
+ PVR_UNREFERENCED_PARAMETER(pszComment);
+
+#if !defined(NO_HARDWARE)
+ if (psDevInfo != NULL)
+ if (PollForValueKM
+ ((u32 __iomem *)psDevInfo->pvRegsBaseKM +
+ (ui32Register >> 2), 0,
+ ui32RegisterValue, MAX_HW_TIME_US / WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK)
+ PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: %s failed.",
+ pszComment);
+
+#endif
+
+ PDUMPCOMMENT(pszComment);
+ PDUMPREGPOL(ui32Register, 0, ui32RegisterValue);
+}
+
+static enum PVRSRV_ERROR SGXPrePowerState(void *hDevHandle,
+ enum PVR_DEVICE_POWER_STATE eNewPowerState,
+ enum PVR_DEVICE_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eNewPowerState != PVR_DEVICE_POWER_STATE_ON)) {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ u32 ui32PowerCmd, ui32CompleteStatus;
+ struct SGXMKIF_COMMAND sCommand = { 0 };
+
+ eError = SGXOSTimerCancel(psDevInfo->hTimer);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXPrePowerState: Failed to disable timer");
+ return eError;
+ }
+
+ if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
+ ui32CompleteStatus =
+ PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
+ PDUMPCOMMENT("SGX power off request");
+ } else {
+
+ ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
+ ui32CompleteStatus =
+ PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
+ PDUMPCOMMENT("SGX idle request");
+ }
+
+ sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_POWERCMD;
+ sCommand.ui32Data[1] = ui32PowerCmd;
+
+ eError =
+ SGXScheduleCCBCommand(psDevInfo, SGXMKIF_COMMAND_EDM_KICK,
+ &sCommand, KERNEL_ID, 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: "
+ "Failed to submit power down command");
+ return eError;
+ }
+
+#if !defined(NO_HARDWARE)
+ if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
+ ui32CompleteStatus,
+ ui32CompleteStatus,
+ MAX_HW_TIME_US / WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: "
+ "Wait for SGX ukernel power transition failed.");
+ PVR_DBG_BREAK;
+ }
+#endif
+
+#if defined(PDUMP)
+ PDUMPCOMMENT
+ ("TA/3D CCB Control - Wait for power event on uKernel.");
+ PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL, ui32PowerStatus),
+ ui32CompleteStatus, ui32CompleteStatus,
+ PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE,
+ MAKEUNIQUETAG(psDevInfo->
+ psKernelSGXHostCtlMemInfo));
+#endif
+
+ SGXPollForClockGating(psDevInfo,
+ psDevInfo->ui32ClkGateStatusReg,
+ psDevInfo->ui32ClkGateStatusMask,
+ "Wait for SGX clock gating");
+
+ if (eNewPowerState == PVR_DEVICE_POWER_STATE_OFF) {
+ eError = SGXDeinitialise(psDevInfo);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXPrePowerState: "
+ "SGXDeinitialise failed: %lu",
+ eError);
+ return eError;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+static enum PVRSRV_ERROR SGXPostPowerState(void *hDevHandle,
+ enum PVR_DEVICE_POWER_STATE eNewPowerState,
+ enum PVR_DEVICE_POWER_STATE eCurrentPowerState)
+{
+ if ((eNewPowerState != eCurrentPowerState) &&
+ (eCurrentPowerState != PVR_DEVICE_POWER_STATE_ON)) {
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+
+ writel(0, &psSGXHostCtl->ui32PowerStatus);
+ PDUMPCOMMENT("TA/3D CCB Control - Reset power status");
+#if defined(PDUMP)
+ PDUMPMEM(NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL, ui32PowerStatus),
+ sizeof(u32), PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+#endif
+
+ if (eCurrentPowerState == PVR_DEVICE_POWER_STATE_OFF) {
+
+ SGXGetTimingInfo(psDeviceNode);
+
+ eError = SGXInitialise(psDevInfo, IMG_FALSE);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXPostPowerState: SGXInitialise failed");
+ return eError;
+ }
+ } else {
+
+ struct SGXMKIF_COMMAND sCommand = { 0 };
+
+ SGXStartTimer(psDevInfo, IMG_TRUE);
+
+ sCommand.ui32Data[0] =
+ PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
+ eError =
+ SGXScheduleCCBCommand(psDevInfo,
+ SGXMKIF_COMMAND_EDM_KICK,
+ &sCommand, ISR_ID, 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXPostPowerState failed to schedule CCB command: %lu",
+ eError);
+ return PVRSRV_ERROR_GENERIC;
+ }
+ }
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXPrePowerStateExt(void *hDevHandle,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE eCurrentPowerState)
+{
+ enum PVR_DEVICE_POWER_STATE eNewDevicePowerState =
+ MapDevicePowerState(eNewPowerState);
+ enum PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
+ MapDevicePowerState(eCurrentPowerState);
+
+ return SGXPrePowerState(hDevHandle, eNewDevicePowerState,
+ eCurrentDevicePowerState);
+}
+
+enum PVRSRV_ERROR SGXPostPowerStateExt(void *hDevHandle,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE eCurrentPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ enum PVR_DEVICE_POWER_STATE eNewDevicePowerState =
+ MapDevicePowerState(eNewPowerState);
+ enum PVR_DEVICE_POWER_STATE eCurrentDevicePowerState =
+ MapDevicePowerState(eCurrentPowerState);
+
+ eError =
+ SGXPostPowerState(hDevHandle, eNewDevicePowerState,
+ eCurrentDevicePowerState);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "SGXPostPowerState : SGX Power Transition from %d to %d OK",
+ eCurrentPowerState, eNewPowerState);
+
+ return eError;
+}
+
+enum PVRSRV_ERROR SGXPreClockSpeedChange(void *hDevHandle, IMG_BOOL bIdleDevice,
+ enum PVR_POWER_STATE eCurrentPowerState)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ if (eCurrentPowerState == PVRSRV_POWER_STATE_D0)
+ if (bIdleDevice) {
+ PDUMPSUSPEND();
+ eError =
+ SGXPrePowerState(hDevHandle,
+ PVR_DEVICE_POWER_STATE_IDLE,
+ PVR_DEVICE_POWER_STATE_ON);
+ if (eError != PVRSRV_OK) {
+ PDUMPRESUME();
+ return eError;
+ }
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "SGXPreClockSpeedChange: SGX clock speed was %luHz",
+ psDevInfo->ui32CoreClockSpeed);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXPostClockSpeedChange(void *hDevHandle,
+ IMG_BOOL bIdleDevice,
+ enum PVR_POWER_STATE eCurrentPowerState)
+{
+ struct PVRSRV_DEVICE_NODE *psDeviceNode = hDevHandle;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ u32 ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
+
+ PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
+
+ if (eCurrentPowerState == PVRSRV_POWER_STATE_D0) {
+ SGXGetTimingInfo(psDeviceNode);
+ if (bIdleDevice) {
+ enum PVRSRV_ERROR eError;
+ eError =
+ SGXPostPowerState(hDevHandle,
+ PVR_DEVICE_POWER_STATE_ON,
+ PVR_DEVICE_POWER_STATE_IDLE);
+ PDUMPRESUME();
+ if (eError != PVRSRV_OK)
+ return eError;
+ } else {
+ SGXStartTimer(psDevInfo, IMG_TRUE);
+ }
+
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE, "SGXPostClockSpeedChange: "
+ "SGX clock speed changed from %luHz to %luHz",
+ ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed);
+
+ return PVRSRV_OK;
+}
diff --git a/drivers/gpu/pvr/sgxreset.c b/drivers/gpu/pvr/sgxreset.c
new file mode 100644
index 00000000000..ad76a01fe31
--- /dev/null
+++ b/drivers/gpu/pvr/sgxreset.c
@@ -0,0 +1,223 @@
+/**********************************************************************
+ *
+ * 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 "sgxdefs.h"
+#include "sgxmmu.h"
+#include "services_headers.h"
+#include "sgxinfokm.h"
+#include "sgxconfig.h"
+
+#include "pdump_km.h"
+
+static void SGXResetSoftReset(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bResetBIF, u32 ui32PDUMPFlags,
+ IMG_BOOL bPDump)
+{
+ u32 ui32SoftResetRegVal =
+ EUR_CR_SOFT_RESET_DPM_RESET_MASK |
+ EUR_CR_SOFT_RESET_TA_RESET_MASK |
+ EUR_CR_SOFT_RESET_USE_RESET_MASK |
+ EUR_CR_SOFT_RESET_ISP_RESET_MASK | EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+
+#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
+#endif
+
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ if (bResetBIF)
+ ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_BIF_RESET_MASK;
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET,
+ ui32SoftResetRegVal);
+ if (bPDump)
+ PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32SoftResetRegVal,
+ ui32PDUMPFlags);
+}
+
+static void SGXResetSleep(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ u32 ui32PDUMPFlags, IMG_BOOL bPDump)
+{
+#if !defined(PDUMP)
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ OSWaitus(1000 * 1000000 / psDevInfo->ui32CoreClockSpeed);
+ if (bPDump) {
+ PDUMPIDLWITHFLAGS(30, ui32PDUMPFlags);
+#if defined(PDUMP)
+ PDumpRegRead(EUR_CR_SOFT_RESET, ui32PDUMPFlags);
+#endif
+ }
+
+}
+
+static void SGXResetInvalDC(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ u32 ui32PDUMPFlags, IMG_BOOL bPDump)
+{
+ u32 ui32RegVal;
+
+ ui32RegVal = EUR_CR_BIF_CTRL_INVALDC_MASK;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
+ if (bPDump)
+ PDUMPREGWITHFLAGS(EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, bPDump);
+
+ if (PollForValueKM(
+ (u32 __iomem *)((u8 __iomem *)psDevInfo->pvRegsBaseKM +
+ EUR_CR_BIF_MEM_REQ_STAT),
+ 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+ MAX_HW_TIME_US / WAIT_TRY_COUNT, WAIT_TRY_COUNT) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "Wait for DC invalidate failed.");
+ PVR_DBG_BREAK;
+ }
+
+ if (bPDump)
+ PDUMPREGPOLWITHFLAGS(EUR_CR_BIF_MEM_REQ_STAT, 0,
+ EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
+ ui32PDUMPFlags);
+}
+
+void SGXReset(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32PDUMPFlags)
+{
+ u32 ui32RegVal;
+
+ const u32 ui32BifFaultMask = EUR_CR_BIF_INT_STAT_FAULT_MASK;
+
+
+#ifndef PDUMP
+ PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
+#endif
+
+ psDevInfo->ui32NumResets++;
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags,
+ "Start of SGX reset sequence\r\n");
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+
+ ui32RegVal = psDevInfo->sBIFResetPDDevPAddr.uiAddr;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
+ ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ for (;;) {
+ u32 ui32BifIntStat =
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ struct IMG_DEV_VIRTADDR sBifFault;
+ u32 ui32PDIndex, ui32PTIndex;
+
+ if ((ui32BifIntStat & ui32BifFaultMask) == 0)
+ break;
+
+ sBifFault.uiAddr =
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ PVR_DPF(PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x",
+ ui32BifIntStat, sBifFault.uiAddr);
+ ui32PDIndex =
+ sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
+ ui32PTIndex =
+ (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+
+ SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags,
+ IMG_FALSE);
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] =
+ psDevInfo->sBIFResetPTDevPAddr.uiAddr |
+ SGX_MMU_PDE_PAGE_SIZE_4K | SGX_MMU_PDE_VALID;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] =
+ psDevInfo->sBIFResetPageDevPAddr.uiAddr | SGX_MMU_PTE_VALID;
+
+ ui32RegVal =
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR,
+ ui32RegVal);
+ ui32RegVal =
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2,
+ ui32RegVal);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags,
+ IMG_FALSE);
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
+
+ psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
+ psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
+ }
+
+ {
+ u32 ui32EDMDirListReg;
+
+#if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
+ ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
+#else
+
+ ui32EDMDirListReg =
+ EUR_CR_BIF_DIR_LIST_BASE1 +
+ 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
+#endif
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32EDMDirListReg,
+ psDevInfo->sKernelPDDevPAddr.uiAddr);
+ PDUMPPDREGWITHFLAGS(ui32EDMDirListReg,
+ psDevInfo->sKernelPDDevPAddr.uiAddr,
+ ui32PDUMPFlags, PDUMP_PD_UNIQUETAG);
+ }
+
+ SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PVR_DPF(PVR_DBG_MESSAGE, "Soft Reset of SGX");
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ ui32RegVal = 0;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
+ PDUMPREGWITHFLAGS(EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
+
+ SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
+
+ PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
+}
diff --git a/drivers/gpu/pvr/sgxscript.h b/drivers/gpu/pvr/sgxscript.h
new file mode 100644
index 00000000000..2bbb0ba03ed
--- /dev/null
+++ b/drivers/gpu/pvr/sgxscript.h
@@ -0,0 +1,65 @@
+/**********************************************************************
+ *
+ * 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 __SGXSCRIPT_H__
+#define __SGXSCRIPT_H__
+
+
+#define SGX_MAX_INIT_COMMANDS 64
+#define SGX_MAX_DEINIT_COMMANDS 16
+
+enum SGX_INIT_OPERATION {
+ SGX_INIT_OP_ILLEGAL = 0,
+ SGX_INIT_OP_WRITE_HW_REG,
+#if defined(PDUMP)
+ SGX_INIT_OP_PDUMP_HW_REG,
+#endif
+ SGX_INIT_OP_HALT
+};
+
+union SGX_INIT_COMMAND {
+ enum SGX_INIT_OPERATION eOp;
+ struct {
+ enum SGX_INIT_OPERATION eOp;
+ u32 ui32Offset;
+ u32 ui32Value;
+ } sWriteHWReg;
+#if defined(PDUMP)
+ struct {
+ enum SGX_INIT_OPERATION eOp;
+ u32 ui32Offset;
+ u32 ui32Value;
+ } sPDumpHWReg;
+#endif
+};
+
+struct SGX_INIT_SCRIPTS {
+ union SGX_INIT_COMMAND asInitCommandsPart1[SGX_MAX_INIT_COMMANDS];
+ union SGX_INIT_COMMAND asInitCommandsPart2[SGX_MAX_INIT_COMMANDS];
+ union SGX_INIT_COMMAND asDeinitCommands[SGX_MAX_DEINIT_COMMANDS];
+};
+
+#endif
diff --git a/drivers/gpu/pvr/sgxtransfer.c b/drivers/gpu/pvr/sgxtransfer.c
new file mode 100644
index 00000000000..410b97ed629
--- /dev/null
+++ b/drivers/gpu/pvr/sgxtransfer.c
@@ -0,0 +1,293 @@
+/**********************************************************************
+ *
+ * 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 "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+enum PVRSRV_ERROR SGXSubmitTransferKM(void *hDevHandle,
+ struct PVRSRV_TRANSFER_SGX_KICK *psKick)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ struct SGXMKIF_COMMAND sCommand = { 0 };
+ struct SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ enum PVRSRV_ERROR eError;
+
+ if (!CCB_OFFSET_IS_VALID
+ (struct SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick,
+ ui32SharedCmdCCBOffset)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXSubmitTransferKM: Invalid CCB offset");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSharedTransferCmd =
+ CCB_DATA_FROM_OFFSET(struct SGXMKIF_TRANSFERCMD_SHARED,
+ psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ if (psKick->hTASyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->hTASyncInfo;
+
+ psSharedTransferCmd->ui32TASyncWriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui32TASyncReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ } else {
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+ if (psKick->h3DSyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->h3DSyncInfo;
+
+ psSharedTransferCmd->ui323DSyncWriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui323DSyncReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ } else {
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) {
+ if (psKick->ui32NumSrcSync > 0) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->ahSrcSyncInfo[0];
+
+ psSharedTransferCmd->ui32SrcWriteOpPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->ui32SrcReadOpPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sSrcWriteOpsCompleteDevAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sSrcReadOpsCompleteDevAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+ if (psKick->ui32NumDstSync > 0) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->ahDstSyncInfo[0];
+ psSharedTransferCmd->ui32DstWriteOpPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->ui32DstReadOpPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psSharedTransferCmd->sDstWriteOpsCompleteDevAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sDstReadOpsCompleteDevAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+ if (psKick->ui32NumSrcSync > 0) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ }
+ if (psKick->ui32NumDstSync > 0) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+ }
+
+ if (psKick->ui32NumDstSync > 1 || psKick->ui32NumSrcSync > 1) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "Transfer command doesn't support "
+ "more than 1 sync object per src/dst\ndst: %d, src: %d",
+ psKick->ui32NumDstSync, psKick->ui32NumSrcSync);
+ }
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM() ||
+ ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) {
+ PDUMPCOMMENT("Shared part of transfer command\r\n");
+ PDUMPMEM(psSharedTransferCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(struct SGXMKIF_TRANSFERCMD_SHARED),
+ psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo));
+
+ if ((psKick->ui32NumSrcSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo = psKick->ahSrcSyncInfo[0];
+
+ PDUMPCOMMENT
+ ("Hack src surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32SrcWriteOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT
+ ("Hack src surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32SrcReadOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+ if ((psKick->ui32NumDstSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo = psKick->ahDstSyncInfo[0];
+
+ PDUMPCOMMENT
+ ("Hack dest surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32DstWriteOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT
+ ("Hack dest surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32DstReadOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ if ((psKick->ui32NumSrcSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ }
+
+ if ((psKick->ui32NumDstSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+#endif
+
+ sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_TRANSFERCMD;
+ sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+ /* To aid in determining the next power down delay */
+ sgx_mark_new_command(hDevHandle);
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_COMMAND_EDM_KICK,
+ &sCommand, KERNEL_ID,
+ psKick->ui32PDumpFlags);
+
+#if defined(NO_HARDWARE)
+ if (!(psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE)) {
+ u32 i;
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ for (i = 0; i < psKick->ui32NumDstSync; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahDstSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ }
+
+ if (psKick->hTASyncInfo != NULL) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+#endif
+
+ return eError;
+}
+
diff --git a/drivers/gpu/pvr/sgxutils.c b/drivers/gpu/pvr/sgxutils.c
new file mode 100644
index 00000000000..b92d5023958
--- /dev/null
+++ b/drivers/gpu/pvr/sgxutils.c
@@ -0,0 +1,749 @@
+/**********************************************************************
+ *
+ * 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 "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxapi_km.h"
+#include "sgxinfo.h"
+#include "sgxinfokm.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge_km.h"
+#include "sgx_bridge_km.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+#include <linux/tty.h>
+#include <linux/io.h>
+
+static void SGXPostActivePowerEvent(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ psDevInfo->psSGXHostCtl;
+ u32 l;
+
+ /* To aid in calculating the next power down delay */
+ sgx_mark_power_down(psDeviceNode);
+
+ l = readl(&psSGXHostCtl->ui32NumActivePowerEvents);
+ l++;
+ writel(l, &psSGXHostCtl->ui32NumActivePowerEvents);
+
+ l = readl(&psSGXHostCtl->ui32PowerStatus);
+ if (l & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE)
+ SGXScheduleProcessQueues(psDeviceNode);
+}
+
+void SGXTestActivePowerEvent(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl = psDevInfo->psSGXHostCtl;
+ u32 l;
+
+ l = readl(&psSGXHostCtl->ui32InterruptFlags);
+ if (!(l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER))
+ return;
+
+ l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
+ if (l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER)
+ return;
+
+ /* Microkernel is idle and is requesting to be powered down. */
+ l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
+ l |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+ writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
+
+ PDUMPSUSPEND();
+
+ eError = PVRSRVSetDevicePowerStateKM(
+ psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_POWER_STATE_D3);
+ if (eError == PVRSRV_OK)
+ SGXPostActivePowerEvent(psDeviceNode);
+
+ PDUMPRESUME();
+
+ if (eError != PVRSRV_OK)
+ PVR_DPF(PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%lu",
+ eError);
+}
+
+static inline struct SGXMKIF_COMMAND *SGXAcquireKernelCCBSlot(
+ struct PVRSRV_SGX_CCB_INFO *psCCB)
+{
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ if (((*psCCB->pui32WriteOffset + 1) & 255) !=
+ *psCCB->pui32ReadOffset) {
+ return &psCCB->psCommands[*psCCB->pui32WriteOffset];
+ }
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ return NULL;
+}
+
+enum PVRSRV_ERROR SGXScheduleCCBCommand(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ enum SGXMKIF_COMMAND_TYPE eCommandType,
+ struct SGXMKIF_COMMAND *psCommandData,
+ u32 ui32CallerID, u32 ui32PDumpFlags)
+{
+ struct PVRSRV_SGX_CCB_INFO *psKernelCCB;
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+ struct SGXMKIF_COMMAND *psSGXCommand;
+#if defined(PDUMP)
+ void *pvDumpCommand;
+#else
+ PVR_UNREFERENCED_PARAMETER(ui32CallerID);
+ PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
+#endif
+
+ psKernelCCB = psDevInfo->psKernelCCBInfo;
+
+ psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
+
+ if (!psSGXCommand) {
+ eError = PVRSRV_ERROR_TIMEOUT;
+ goto Exit;
+ }
+
+ psCommandData->ui32Data[2] = psDevInfo->ui32CacheControl;
+
+#if defined(PDUMP)
+
+ psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
+#endif
+
+ psDevInfo->ui32CacheControl = 0;
+
+ *psSGXCommand = *psCommandData;
+
+ switch (eCommandType) {
+ case SGXMKIF_COMMAND_EDM_KICK:
+ psSGXCommand->ui32ServiceAddress =
+ psDevInfo->ui32HostKickAddress;
+ break;
+ case SGXMKIF_COMMAND_REQUEST_SGXMISCINFO:
+ psSGXCommand->ui32ServiceAddress =
+ psDevInfo->ui32GetMiscInfoAddress;
+ break;
+ case SGXMKIF_COMMAND_VIDEO_KICK:
+ default:
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXScheduleCCBCommandKM: Unknown command type: %d",
+ eCommandType);
+ eError = PVRSRV_ERROR_GENERIC;
+ goto Exit;
+ }
+
+#if defined(PDUMP)
+ if (ui32CallerID != ISR_ID) {
+ PDUMPCOMMENTWITHFLAGS(0,
+ "Poll for space in the Kernel CCB\r\n");
+ PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
+ offsetof(struct PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
+ (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff, 0xff,
+ PDUMP_POLL_OPERATOR_NOTEQUAL, IMG_FALSE, IMG_FALSE,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+
+ PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB command\r\n");
+ pvDumpCommand =
+ (void *)((u8 *)psKernelCCB->psCCBMemInfo->
+ pvLinAddrKM +
+ (*psKernelCCB->pui32WriteOffset *
+ sizeof(struct SGXMKIF_COMMAND)));
+
+ PDUMPMEM(pvDumpCommand,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff *
+ sizeof(struct SGXMKIF_COMMAND),
+ sizeof(struct SGXMKIF_COMMAND), ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+ PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
+ psKernelCCB->psCCBMemInfo,
+ psKernelCCB->ui32CCBDumpWOff *
+ sizeof(struct SGXMKIF_COMMAND) +
+ offsetof(struct SGXMKIF_COMMAND, ui32Data[2]),
+ sizeof(u32), ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
+
+ if (PDumpIsCaptureFrameKM() ||
+ ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ psDevInfo->sPDContext.ui32CacheControl = 0;
+ }
+#endif
+ *psKernelCCB->pui32WriteOffset =
+ (*psKernelCCB->pui32WriteOffset + 1) & 255;
+
+#if defined(PDUMP)
+ if (ui32CallerID != ISR_ID) {
+ if (PDumpIsCaptureFrameKM() ||
+ ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
+ psKernelCCB->ui32CCBDumpWOff =
+ (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
+
+ PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB write offset\r\n");
+ PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+ psKernelCCB->psCCBCtlMemInfo,
+ offsetof(struct PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
+ sizeof(u32), ui32PDumpFlags,
+ MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
+ PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB event kicker\r\n");
+ PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
+ psDevInfo->psKernelCCBEventKickerMemInfo, 0,
+ sizeof(u32), ui32PDumpFlags,
+ MAKEUNIQUETAG(psDevInfo->
+ psKernelCCBEventKickerMemInfo));
+ PDUMPCOMMENTWITHFLAGS(0, "Event kick\r\n");
+ PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK, 0);
+ }
+#endif
+ *psDevInfo->pui32KernelCCBEventKicker =
+ (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM,
+ SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
+ EUR_CR_EVENT_KICK_NOW_MASK);
+
+#if defined(NO_HARDWARE)
+
+ *psKernelCCB->pui32ReadOffset =
+ (*psKernelCCB->pui32ReadOffset + 1) & 255;
+#endif
+
+Exit:
+ return eError;
+}
+
+enum PVRSRV_ERROR SGXScheduleCCBCommandKM(
+ struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ enum SGXMKIF_COMMAND_TYPE eCommandType,
+ struct SGXMKIF_COMMAND *psCommandData,
+ u32 ui32CallerID, u32 ui32PDumpFlags)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+
+ PDUMPSUSPEND();
+
+ pvr_dev_lock();
+
+ eError =
+ PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_POWER_STATE_D0);
+
+ PDUMPRESUME();
+
+ if (eError == PVRSRV_OK) {
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
+ } else {
+ PVR_DPF(PVR_DBG_ERROR, "%s: can't power on device (%d)",
+ __func__, eError);
+ pvr_dev_unlock();
+ return eError;
+ }
+
+ eError = SGXScheduleCCBCommand(psDevInfo, eCommandType, psCommandData,
+ ui32CallerID, ui32PDumpFlags);
+
+ if (ui32CallerID != ISR_ID)
+ SGXTestActivePowerEvent(psDeviceNode);
+
+ pvr_dev_unlock();
+
+ return eError;
+}
+
+enum PVRSRV_ERROR SGXScheduleProcessQueues(struct PVRSRV_DEVICE_NODE
+ *psDeviceNode)
+{
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ struct SGXMKIF_HOST_CTL *psHostCtl =
+ psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
+ u32 ui32PowerStatus;
+ struct SGXMKIF_COMMAND sCommand = { 0 };
+
+ ui32PowerStatus = psHostCtl->ui32PowerStatus;
+ if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
+ return PVRSRV_OK;
+
+ eError =
+ PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
+ PVRSRV_POWER_STATE_D0);
+ if (eError != PVRSRV_OK)
+ return eError;
+
+ sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
+ eError = SGXScheduleCCBCommand(psDeviceNode->pvDevice,
+ SGXMKIF_COMMAND_EDM_KICK, &sCommand,
+ ISR_ID, 0);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "%s failed to schedule CCB command: %lu",
+ __func__, eError);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SGXScheduleProcessQueuesKM(struct PVRSRV_DEVICE_NODE
+ *psDeviceNode)
+{
+ enum PVRSRV_ERROR eError;
+
+ pvr_dev_lock();
+ eError = SGXScheduleProcessQueues(psDeviceNode);
+ pvr_dev_unlock();
+
+ return eError;
+}
+
+IMG_BOOL SGXIsDevicePowered(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
+}
+
+enum PVRSRV_ERROR SGXGetInternalDevInfoKM(void *hDevCookie,
+ struct SGX_INTERNAL_DEVINFO
+ *psSGXInternalDevInfo)
+{
+ struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
+ ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
+
+ psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
+ psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
+
+ psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
+ (void *)psDevInfo->psKernelSGXHostCtlMemInfo;
+
+ return PVRSRV_OK;
+}
+
+#if defined(PDUMP) && !defined(EDM_USSE_HWDEBUG)
+#define PDUMP_SGX_CLEANUP
+#endif
+
+void SGXCleanupRequest(struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ u32 ui32ResManRequestFlag)
+{
+ struct PVRSRV_SGXDEV_INFO *psSGXDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ struct PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo =
+ psSGXDevInfo->psKernelSGXHostCtlMemInfo;
+ struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
+ (struct SGXMKIF_HOST_CTL __iomem __force *)
+ psSGXHostCtlMemInfo->pvLinAddrKM;
+#if defined(PDUMP_SGX_CLEANUP)
+ void *hUniqueTag = MAKEUNIQUETAG(psSGXHostCtlMemInfo);
+#endif
+ u32 l;
+
+ pvr_dev_lock();
+ if (readl(&psSGXHostCtl->ui32PowerStatus) &
+ PVRSRV_USSE_EDM_POWMAN_NO_WORK) {
+ ;
+ } else {
+ if (psSGXDevInfo->ui32CacheControl &
+ SGX_BIF_INVALIDATE_PDCACHE) {
+ l = readl(&psSGXHostCtl->ui32ResManFlags);
+ l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPD;
+ writel(l, &psSGXHostCtl->ui32ResManFlags);
+
+ psSGXDevInfo->ui32CacheControl ^=
+ SGX_BIF_INVALIDATE_PDCACHE;
+ }
+ if (psSGXDevInfo->ui32CacheControl &
+ SGX_BIF_INVALIDATE_PTCACHE) {
+ l = readl(&psSGXHostCtl->ui32ResManFlags);
+ l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPT;
+ writel(l, &psSGXHostCtl->ui32ResManFlags);
+
+ psSGXDevInfo->ui32CacheControl ^=
+ SGX_BIF_INVALIDATE_PTCACHE;
+ }
+
+ if (psHWDataDevVAddr == NULL)
+ writel(0, &psSGXHostCtl->sResManCleanupData.uiAddr);
+ else
+ writel(psHWDataDevVAddr->uiAddr,
+ &psSGXHostCtl->sResManCleanupData.uiAddr);
+
+ l = readl(&psSGXHostCtl->ui32ResManFlags);
+ l |= ui32ResManRequestFlag;
+ writel(l, &psSGXHostCtl->ui32ResManFlags);
+
+#if defined(PDUMP_SGX_CLEANUP)
+
+ PDUMPCOMMENTWITHFLAGS(0,
+ "TA/3D CCB Control - Request clean-up event on uKernel...");
+ PDUMPMEM(NULL, psSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL,
+ sResManCleanupData.uiAddr), sizeof(u32), 0,
+ hUniqueTag);
+ PDUMPMEM(&ui32ResManRequestFlag, psSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
+ sizeof(u32), 0, hUniqueTag);
+#else
+ PDUMPCOMMENTWITHFLAGS(0, "Clean-up event on uKernel disabled");
+#endif
+
+ SGXScheduleProcessQueues(psDeviceNode);
+
+#if !defined(NO_HARDWARE)
+ if (PollForValueKM(&psSGXHostCtl->ui32ResManFlags,
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+ MAX_HW_TIME_US / WAIT_TRY_COUNT,
+ WAIT_TRY_COUNT) != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXCleanupRequest: "
+ "Wait for uKernel to clean up failed");
+ PVR_DBG_BREAK;
+ }
+#endif
+
+#if defined(PDUMP_SGX_CLEANUP)
+
+ PDUMPCOMMENTWITHFLAGS(0, "TA/3D CCB Control - "
+ "Wait for clean-up request to complete...");
+ PDUMPMEMPOL(psSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
+ PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE,
+ hUniqueTag);
+#endif
+
+ l = readl(&psSGXHostCtl->ui32ResManFlags);
+ l &= ~ui32ResManRequestFlag;
+ writel(l, &psSGXHostCtl->ui32ResManFlags);
+
+ l = readl(&psSGXHostCtl->ui32ResManFlags);
+ l &= ~PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE;
+ writel(l, &psSGXHostCtl->ui32ResManFlags);
+
+#if defined(PDUMP_SGX_CLEANUP)
+ PDUMPMEM(NULL, psSGXHostCtlMemInfo,
+ offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
+ sizeof(u32), 0, hUniqueTag);
+#endif
+ }
+ pvr_dev_unlock();
+}
+
+struct SGX_HW_RENDER_CONTEXT_CLEANUP {
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
+ void *hBlockAlloc;
+ struct RESMAN_ITEM *psResItem;
+};
+
+static enum PVRSRV_ERROR SGXCleanupHWRenderContextCallback(void *pvParam,
+ u32 ui32Param)
+{
+ struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHWRenderContextDevVAddr,
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_RC_REQUEST);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup, psCleanup->hBlockAlloc);
+
+ return PVRSRV_OK;
+}
+
+struct SGX_HW_TRANSFER_CONTEXT_CLEANUP {
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
+ void *hBlockAlloc;
+ struct RESMAN_ITEM *psResItem;
+};
+
+static enum PVRSRV_ERROR SGXCleanupHWTransferContextCallback(void *pvParam,
+ u32 ui32Param)
+{
+ struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup =
+ (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(ui32Param);
+
+ SGXCleanupRequest(psCleanup->psDeviceNode,
+ &psCleanup->sHWTransferContextDevVAddr,
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_TC_REQUEST);
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup, psCleanup->hBlockAlloc);
+
+ return PVRSRV_OK;
+}
+
+void *SGXRegisterHWRenderContextKM(void *psDeviceNode,
+ struct IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ enum PVRSRV_ERROR eError;
+ void *hBlockAlloc;
+ struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+ struct RESMAN_ITEM *psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
+ (void **) &psCleanup, &hBlockAlloc);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXRegisterHWRenderContextKM: "
+ "Couldn't allocate memory for struct "
+ "SGX_HW_RENDER_CONTEXT_CLEANUP structure");
+ return NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_RENDER_CONTEXT,
+ (void *) psCleanup,
+ 0, &SGXCleanupHWRenderContextCallback);
+
+ if (psResItem == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: "
+ "ResManRegisterRes failed");
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup, psCleanup->hBlockAlloc);
+
+ return NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (void *)psCleanup;
+}
+
+enum PVRSRV_ERROR SGXUnregisterHWRenderContextKM(void *hHWRenderContext)
+{
+ struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWRenderContext != NULL);
+
+ psCleanup = (struct SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
+
+ if (psCleanup == NULL) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXUnregisterHWRenderContextKM: invalid parameter");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ ResManFreeResByPtr(psCleanup->psResItem);
+
+ return PVRSRV_OK;
+}
+
+void *SGXRegisterHWTransferContextKM(void *psDeviceNode,
+ struct IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ enum PVRSRV_ERROR eError;
+ void *hBlockAlloc;
+ struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+ struct RESMAN_ITEM *psResItem;
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ (void **) &psCleanup, &hBlockAlloc);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXRegisterHWTransferContextKM: "
+ "Couldn't allocate memory for struct "
+ "SGX_HW_TRANSFER_CONTEXT_CLEANUP structure");
+ return NULL;
+ }
+
+ psCleanup->hBlockAlloc = hBlockAlloc;
+ psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
+
+ psResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT,
+ psCleanup,
+ 0, &SGXCleanupHWTransferContextCallback);
+
+ if (psResItem == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: "
+ "ResManRegisterRes failed");
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup, psCleanup->hBlockAlloc);
+
+ return NULL;
+ }
+
+ psCleanup->psResItem = psResItem;
+
+ return (void *)psCleanup;
+}
+
+enum PVRSRV_ERROR SGXUnregisterHWTransferContextKM(void *hHWTransferContext)
+{
+ struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
+
+ PVR_ASSERT(hHWTransferContext != NULL);
+
+ psCleanup =
+ (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
+
+ if (psCleanup == NULL) {
+ PVR_DPF(PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: "
+ "invalid parameter");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ ResManFreeResByPtr(psCleanup->psResItem);
+
+ return PVRSRV_OK;
+}
+
+static inline IMG_BOOL SGX2DQuerySyncOpsComplete(
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ u32 ui32ReadOpsPending, u32 ui32WriteOpsPending)
+{
+ struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ return (IMG_BOOL)((psSyncData->ui32ReadOpsComplete >=
+ ui32ReadOpsPending) &&
+ (psSyncData->ui32WriteOpsComplete >=
+ ui32WriteOpsPending));
+}
+
+enum PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(
+ struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
+ IMG_BOOL bWaitForComplete)
+{
+ u32 ui32ReadOpsPending, ui32WriteOpsPending;
+
+ PVR_UNREFERENCED_PARAMETER(psDevInfo);
+
+ PVR_DPF(PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start");
+
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ if (SGX2DQuerySyncOpsComplete
+ (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
+
+ PVR_DPF(PVR_DBG_CALLTRACE,
+ "SGX2DQueryBlitsCompleteKM: No wait. Blits complete.");
+ return PVRSRV_OK;
+ }
+
+ if (!bWaitForComplete) {
+
+ PVR_DPF(PVR_DBG_CALLTRACE,
+ "SGX2DQueryBlitsCompleteKM: No wait. Ops pending.");
+ return PVRSRV_ERROR_CMD_NOT_PROCESSED;
+ }
+
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling.");
+ LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
+ OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
+
+ if (SGX2DQuerySyncOpsComplete
+ (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
+
+ PVR_DPF(PVR_DBG_CALLTRACE,
+ "SGX2DQueryBlitsCompleteKM: "
+ "Wait over. Blits complete.");
+ return PVRSRV_OK;
+ }
+ }
+ END_LOOP_UNTIL_TIMEOUT();
+
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGX2DQueryBlitsCompleteKM: Timed out. Ops pending.");
+
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ {
+ struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
+
+ PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
+ "Syncinfo: %p, Syncdata: %p",
+ psSyncInfo, psSyncData);
+
+ PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
+ "Read ops complete: %d, Read ops pending: %d",
+ psSyncData->ui32ReadOpsComplete,
+ psSyncData->ui32ReadOpsPending);
+ PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
+ "Write ops complete: %d, Write ops pending: %d",
+ psSyncData->ui32WriteOpsComplete,
+ psSyncData->ui32WriteOpsPending);
+
+ }
+#endif
+ return PVRSRV_ERROR_TIMEOUT;
+}
+
+void SGXFlushHWRenderTargetKM(void *psDeviceNode,
+ struct IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
+{
+ PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr);
+
+ SGXCleanupRequest((struct PVRSRV_DEVICE_NODE *)psDeviceNode,
+ &sHWRTDataSetDevVAddr,
+ PVRSRV_USSE_EDM_RESMAN_CLEANUP_RT_REQUEST);
+}
+
+u32 SGXConvertTimeStamp(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32TimeWraps,
+ u32 ui32Time)
+{
+ u64 ui64Clocks;
+ u32 ui32Clocksx16;
+
+ ui64Clocks = ((u64) ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
+ (psDevInfo->ui32uKernelTimerClock -
+ (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
+ ui32Clocksx16 = (u32) (ui64Clocks / 16);
+
+ return ui32Clocksx16;
+}
diff --git a/drivers/gpu/pvr/sgxutils.h b/drivers/gpu/pvr/sgxutils.h
new file mode 100644
index 00000000000..0a9060611e4
--- /dev/null
+++ b/drivers/gpu/pvr/sgxutils.h
@@ -0,0 +1,78 @@
+/**********************************************************************
+ *
+ * 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 "perproc.h"
+
+#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
+ ((sizeof(type) <= (psCCBMemInfo)->ui32AllocSize) && \
+ ((psCCBKick)->offset <= (psCCBMemInfo)->ui32AllocSize - sizeof(type)))
+
+#define CCB_DATA_FROM_OFFSET(type, psCCBMemInfo, psCCBKick, offset) \
+ ((type *)(((char *)(psCCBMemInfo)->pvLinAddrKM) + \
+ (psCCBKick)->offset))
+
+void SGXTestActivePowerEvent(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+enum PVRSRV_ERROR SGXScheduleCCBCommand(
+ struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ enum SGXMKIF_COMMAND_TYPE eCommandType,
+ struct SGXMKIF_COMMAND *psCommandData,
+ u32 ui32CallerID, u32 ui32PDumpFlags);
+enum PVRSRV_ERROR SGXScheduleCCBCommandKM(
+ struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ enum SGXMKIF_COMMAND_TYPE eCommandType,
+ struct SGXMKIF_COMMAND *psCommandData,
+ u32 ui32CallerID, u32 ui32PDumpFlags);
+
+enum PVRSRV_ERROR SGXScheduleProcessQueues(
+ struct PVRSRV_DEVICE_NODE *psDeviceNode);
+enum PVRSRV_ERROR SGXScheduleProcessQueuesKM(
+ struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+IMG_BOOL SGXIsDevicePowered(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+void *SGXRegisterHWRenderContextKM(void *psDeviceNode,
+ struct IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+void *SGXRegisterHWTransferContextKM(void *psDeviceNode,
+ struct IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
+ struct PVRSRV_PER_PROCESS_DATA *psPerProc);
+
+void SGXFlushHWRenderTargetKM(void *psSGXDevInfo,
+ struct IMG_DEV_VIRTADDR psHWRTDataSetDevVAddr);
+
+enum PVRSRV_ERROR SGXUnregisterHWRenderContextKM(void *hHWRenderContext);
+
+enum PVRSRV_ERROR SGXUnregisterHWTransferContextKM(void *hHWTransferContext);
+
+u32 SGXConvertTimeStamp(struct PVRSRV_SGXDEV_INFO *psDevInfo,
+ u32 ui32TimeWraps, u32 ui32Time);
+
+void SGXCleanupRequest(struct PVRSRV_DEVICE_NODE *psDeviceNode,
+ struct IMG_DEV_VIRTADDR *psHWDataDevVAddr,
+ u32 ui32ResManRequestFlag);
+
diff --git a/drivers/gpu/pvr/srvkm.h b/drivers/gpu/pvr/srvkm.h
new file mode 100644
index 00000000000..3dbcd24eabd
--- /dev/null
+++ b/drivers/gpu/pvr/srvkm.h
@@ -0,0 +1,50 @@
+/**********************************************************************
+ *
+ * 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 SRVKM_H
+#define SRVKM_H
+
+enum PVRSRV_ERROR PVRSRVProcessConnect(u32 ui32PID);
+void PVRSRVProcessDisconnect(u32 ui32PID);
+ void PVRSRVSetDCState(u32 ui32State);
+ enum PVRSRV_ERROR PVRSRVSaveRestoreLiveSegments(void *hArena,
+ u8 *pbyBuffer,
+ u32 *puiBufSize,
+ IMG_BOOL bSave);
+
+#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
+{ \
+ u32 uiOffset, uiStart, uiCurrent; \
+ for (uiOffset = 0, uiStart = OSClockus(), uiCurrent = uiStart+1; \
+ (uiCurrent - uiStart + uiOffset) < TIMEOUT; \
+ uiCurrent = OSClockus(), \
+ uiOffset = uiCurrent < uiStart ? \
+ IMG_UINT32_MAX - uiStart : uiOffset, \
+ uiStart = uiCurrent < uiStart ? 0 : uiStart)
+
+#define END_LOOP_UNTIL_TIMEOUT() \
+}
+#endif
diff --git a/drivers/gpu/pvr/syscommon.h b/drivers/gpu/pvr/syscommon.h
new file mode 100644
index 00000000000..c55ac3893e5
--- /dev/null
+++ b/drivers/gpu/pvr/syscommon.h
@@ -0,0 +1,177 @@
+/**********************************************************************
+ *
+ * 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 _SYSCOMMON_H
+#define _SYSCOMMON_H
+
+#include "sysconfig.h"
+#include "sysinfo.h"
+#include "servicesint.h"
+#include "queue.h"
+#include "power.h"
+#include "resman.h"
+#include "ra.h"
+#include "device.h"
+#include "buffer_manager.h"
+
+#include <linux/platform_device.h>
+#include <linux/pvr.h>
+
+#if defined(NO_HARDWARE) && defined(__KERNEL__)
+#include <linux/io.h>
+#endif
+
+struct SYS_DEVICE_ID {
+ u32 uiID;
+ IMG_BOOL bInUse;
+
+};
+
+#define SYS_MAX_LOCAL_DEVMEM_ARENAS 4
+
+struct SYS_DATA {
+ u32 ui32NumDevices;
+ struct SYS_DEVICE_ID sDeviceID[SYS_DEVICE_COUNT];
+ struct PVRSRV_DEVICE_NODE *psDeviceNodeList;
+ struct PVRSRV_POWER_DEV *psPowerDeviceList;
+ enum PVR_POWER_STATE eCurrentPowerState;
+ enum PVR_POWER_STATE eFailedPowerState;
+ u32 ui32CurrentOSPowerState;
+ struct PVRSRV_QUEUE_INFO *psQueueList;
+ struct PVRSRV_KERNEL_SYNC_INFO *psSharedSyncInfoList;
+ void *pvEnvSpecificData;
+ void *pvSysSpecificData;
+ void *pvSOCRegsBase;
+ void *hSOCTimerRegisterOSMemHandle;
+ u32 *pvSOCTimerRegisterKM;
+ void *pvSOCClockGateRegsBase;
+ u32 ui32SOCClockGateRegsSize;
+ IMG_BOOL (**ppfnCmdProcList[SYS_DEVICE_COUNT])(void *, u32, void *);
+
+ struct COMMAND_COMPLETE_DATA **ppsCmdCompleteData[SYS_DEVICE_COUNT];
+
+ struct RA_ARENA *apsLocalDevMemArena[SYS_MAX_LOCAL_DEVMEM_ARENAS];
+
+ char *pszVersionString;
+ struct PVRSRV_EVENTOBJECT *psGlobalEventObject;
+#if defined(PDUMP)
+ IMG_BOOL bPowerUpPDumped;
+#endif
+};
+
+enum PVRSRV_ERROR SysInitialise(struct platform_device *spd);
+enum PVRSRV_ERROR SysFinalise(void);
+
+enum PVRSRV_ERROR SysDeinitialise(struct SYS_DATA *psSysData);
+
+enum PVRSRV_ERROR SysGetDeviceMemoryMap(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void **ppvDeviceMap);
+
+void SysRegisterExternalDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+void SysRemoveExternalDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+u32 SysGetInterruptSource(struct SYS_DATA *psSysData,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode);
+
+void SysClearInterrupts(struct SYS_DATA *psSysData,
+ u32 ui32ClearBits);
+
+enum PVRSRV_ERROR SysResetDevice(u32 ui32DeviceIndex);
+
+enum PVRSRV_ERROR SysSystemPrePowerState(enum PVR_POWER_STATE eNewPowerState);
+enum PVRSRV_ERROR SysSystemPostPowerState(enum PVR_POWER_STATE eNewPowerState);
+enum PVRSRV_ERROR SysDevicePrePowerState(u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE eCurrentPowerState);
+enum PVRSRV_ERROR SysDevicePostPowerState(u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE
+ eCurrentPowerState);
+
+enum PVRSRV_ERROR SysOEMFunction(u32 ui32ID,
+ void *pvIn,
+ u32 ulInSize,
+ void *pvOut, u32 ulOutSize);
+
+struct IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr(
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ struct IMG_CPU_PHYADDR cpu_paddr);
+struct IMG_DEV_PHYADDR SysSysPAddrToDevPAddr(
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ struct IMG_SYS_PHYADDR SysPAddr);
+struct IMG_SYS_PHYADDR SysDevPAddrToSysPAddr(
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ struct IMG_DEV_PHYADDR SysPAddr);
+struct IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(struct IMG_SYS_PHYADDR SysPAddr);
+struct IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr(struct IMG_CPU_PHYADDR cpu_paddr);
+
+extern struct SYS_DATA *gpsSysData;
+
+
+static inline enum PVRSRV_ERROR SysAcquireData(struct SYS_DATA **ppsSysData)
+{
+ *ppsSysData = gpsSysData;
+
+ if (!gpsSysData)
+ return PVRSRV_ERROR_GENERIC;
+
+ return PVRSRV_OK;
+}
+
+static inline enum PVRSRV_ERROR SysInitialiseCommon(struct SYS_DATA *psSysData)
+{
+ enum PVRSRV_ERROR eError;
+ eError = PVRSRVInit(psSysData);
+ return eError;
+}
+
+static inline void SysDeinitialiseCommon(struct SYS_DATA *psSysData)
+{
+ PVRSRVDeInit(psSysData);
+}
+
+#if !(defined(NO_HARDWARE) && defined(__KERNEL__))
+#define SysReadHWReg(p, o) OSReadHWReg(p, o)
+#define SysWriteHWReg(p, o, v) OSWriteHWReg(p, o, v)
+#else
+static inline u32 SysReadHWReg(void *pvLinRegBaseAddr, u32 ui32Offset)
+{
+ return (u32)readl(pvLinRegBaseAddr + ui32Offset);
+}
+
+static inline void SysWriteHWReg(void *pvLinRegBaseAddr, u32 ui32Offset,
+ u32 ui32Value)
+{
+ writel(ui32Value, pvLinRegBaseAddr + ui32Offset);
+}
+#endif
+
+bool sgx_is_530(void);
+u32 sgx_get_rev(void);
+void sgx_ocp_write_reg(u32 reg, u32 val);
+unsigned long sgx_get_max_freq(void);
+
+#endif
diff --git a/drivers/gpu/pvr/sysconfig.c b/drivers/gpu/pvr/sysconfig.c
new file mode 100644
index 00000000000..8ce48e4efb7
--- /dev/null
+++ b/drivers/gpu/pvr/sysconfig.c
@@ -0,0 +1,836 @@
+/**********************************************************************
+ *
+ * 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 <linux/platform_device.h>
+
+#include "services_headers.h"
+#include "kerneldisplay.h"
+#include "oemfuncs.h"
+#include "sgxinfo.h"
+#include "pdump_km.h"
+#include "sgxinfokm.h"
+#include "syslocal.h"
+#include "sysconfig.h"
+#include "syscommon.h"
+#include "img_types.h"
+#include "ocpdefs.h"
+#include "pvr_bridge_km.h"
+
+struct SYS_DATA *gpsSysData;
+static struct SYS_DATA gsSysData;
+
+static struct SYS_SPECIFIC_DATA gsSysSpecificData;
+struct SYS_SPECIFIC_DATA *gpsSysSpecificData;
+
+static u32 gui32SGXDeviceID;
+static struct SGX_DEVICE_MAP gsSGXDeviceMap;
+static struct PVRSRV_DEVICE_NODE *gpsSGXDevNode;
+
+#define DEVICE_SGX_INTERRUPT (1 << 0)
+
+#if defined(NO_HARDWARE)
+static void *gsSGXRegsCPUVAddr;
+#endif
+
+static void __iomem *ocp_base;
+
+static enum PVRSRV_ERROR SysLocateDevices(struct SYS_DATA *psSysData)
+{
+#if defined(NO_HARDWARE)
+ enum PVRSRV_ERROR eError;
+ struct IMG_CPU_PHYADDR sCpuPAddr;
+#endif
+
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+
+ gsSGXDeviceMap.ui32Flags = 0x0;
+
+#if defined(NO_HARDWARE)
+
+ eError = OSBaseAllocContigMemory(SYS_OMAP3430_SGX_REGS_SIZE,
+ &gsSGXRegsCPUVAddr, &sCpuPAddr);
+ if (eError != PVRSRV_OK)
+ return eError;
+ gsSGXDeviceMap.sRegsCpuPBase = sCpuPAddr;
+ gsSGXDeviceMap.sRegsSysPBase =
+ SysCpuPAddrToSysPAddr(gsSGXDeviceMap.sRegsCpuPBase);
+ gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE;
+
+ gsSGXDeviceMap.pvRegsCpuVBase = gsSGXRegsCPUVAddr;
+
+ OSMemSet(gsSGXRegsCPUVAddr, 0, SYS_OMAP3430_SGX_REGS_SIZE);
+
+ gsSGXDeviceMap.ui32IRQ = 0;
+
+#else
+
+ gsSGXDeviceMap.sRegsSysPBase.uiAddr =
+ SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE;
+ gsSGXDeviceMap.sRegsCpuPBase =
+ SysSysPAddrToCpuPAddr(gsSGXDeviceMap.sRegsSysPBase);
+ gsSGXDeviceMap.ui32RegsSize = SYS_OMAP3430_SGX_REGS_SIZE;
+
+ gsSGXDeviceMap.ui32IRQ = SYS_OMAP3430_SGX_IRQ;
+
+#endif
+
+ return PVRSRV_OK;
+}
+
+#ifndef NO_HARDWARE
+u32 sgx_get_rev(void)
+{
+ /*
+ * Ugly solution, used until we have proper per device instances
+ * passed to functions and get rid of most if not all globals.
+ */
+ struct SYS_SPECIFIC_DATA *sysd = gpsSysSpecificData;
+ void __iomem *regs;
+ static u32 rev = -1UL;
+ int err;
+
+ if (rev != -1UL)
+ return rev;
+
+ regs = OSMapPhysToLin(gsSGXDeviceMap.sRegsCpuPBase,
+ SYS_OMAP3430_SGX_REGS_SIZE,
+ PVRSRV_HAP_UNCACHED | PVRSRV_HAP_KERNEL_ONLY,
+ NULL);
+ if (!regs)
+ return 0;
+
+ err = clk_enable(sysd->psSGX_FCK);
+ BUG_ON(err);
+ err = clk_enable(sysd->psSGX_ICK);
+ BUG_ON(err);
+
+ rev = OSReadHWReg(regs, EUR_CR_CORE_REVISION);
+
+ clk_disable(sysd->psSGX_ICK);
+ clk_disable(sysd->psSGX_FCK);
+
+ OSUnMapPhysToLin(regs, SYS_OMAP3430_SGX_REGS_SIZE,
+ PVRSRV_HAP_UNCACHED | PVRSRV_HAP_KERNEL_ONLY, NULL);
+
+ return rev;
+}
+
+unsigned long sgx_get_max_freq(void)
+{
+ struct SYS_SPECIFIC_DATA *sysd = gpsSysSpecificData;
+
+ BUG_ON(!sysd);
+
+ if (sysd->sgx_fck_max)
+ return sysd->sgx_fck_max;
+
+ /*
+ * In case there's no board specific setting for this, return
+ * some revision specific defaults.
+ */
+ if (sgx_is_530()) {
+ switch (sgx_get_rev()) {
+ case EUR_CR_CORE_MAKE_REV(1, 2, 1):
+ return SYS_SGX_MAX_FREQ_530R121;
+ case EUR_CR_CORE_MAKE_REV(1, 2, 5):
+ return SYS_SGX_MAX_FREQ_530R125;
+ }
+ }
+ BUG();
+}
+
+#else
+
+u32 sgx_get_rev(void)
+{
+ return 0;
+}
+
+unsigned long sgx_get_max_freq()
+{
+ return SYS_SGX_MAX_FREQ_NO_HW;
+}
+
+#endif
+
+bool sgx_is_530(void)
+{
+#ifdef SGX530
+ return true;
+#endif
+ return false;
+}
+
+char *SysCreateVersionString(struct IMG_CPU_PHYADDR sRegRegion)
+{
+ static char aszVersionString[100];
+ struct SYS_DATA *psSysData;
+ u32 ui32SGXRevision;
+ s32 i32Count;
+
+ if (SysAcquireData(&psSysData) != PVRSRV_OK)
+ return NULL;
+
+ ui32SGXRevision = sgx_get_rev();
+
+ i32Count = OSSNPrintf(aszVersionString, 100,
+ "SGX revision = %u.%u.%u",
+ (unsigned)((ui32SGXRevision &
+ EUR_CR_CORE_REVISION_MAJOR_MASK)
+ >> EUR_CR_CORE_REVISION_MAJOR_SHIFT),
+ (unsigned)((ui32SGXRevision &
+ EUR_CR_CORE_REVISION_MINOR_MASK)
+ >> EUR_CR_CORE_REVISION_MINOR_SHIFT),
+ (unsigned)((ui32SGXRevision &
+ EUR_CR_CORE_REVISION_MAINTENANCE_MASK)
+ >> EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT)
+ );
+
+ if (i32Count == -1)
+ return NULL;
+
+ return aszVersionString;
+}
+
+static int sgx_ocp_init(void)
+{
+ struct IMG_SYS_PHYADDR sys_pbase;
+ struct IMG_CPU_PHYADDR cpu_pbase;
+
+ sys_pbase.uiAddr = SYS_OMAP3430_OCP_REGS_SYS_PHYS_BASE;
+ cpu_pbase = SysSysPAddrToCpuPAddr(sys_pbase);
+
+ ocp_base = OSMapPhysToLin(cpu_pbase, SYS_OMAP3430_OCP_REGS_SIZE,
+ PVRSRV_HAP_UNCACHED | PVRSRV_HAP_KERNEL_ONLY,
+ NULL);
+
+ if (!ocp_base) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: Failed to map OCP registers",
+ __func__);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void sgx_ocp_cleanup(void)
+{
+ OSUnMapPhysToLin(ocp_base, SYS_OMAP3430_OCP_REGS_SIZE,
+ PVRSRV_HAP_UNCACHED | PVRSRV_HAP_KERNEL_ONLY, NULL);
+}
+
+void sgx_ocp_write_reg(u32 reg, u32 val)
+{
+ BUG_ON(!ocp_base);
+
+ /* OCP offsets are based at EUR_CR_OCP_REVISION */
+ reg -= EUR_CR_OCP_REVISION;
+ OSWriteHWReg(ocp_base, reg, val);
+}
+
+enum PVRSRV_ERROR SysInitialise(struct platform_device *pdev)
+{
+ u32 i;
+ enum PVRSRV_ERROR eError;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ struct IMG_CPU_PHYADDR TimerRegPhysBase;
+ struct sgx_platform_data *spd;
+
+ gpsSysData = &gsSysData;
+
+ gpsSysSpecificData = &gsSysSpecificData;
+
+ gpsSysData->pvSysSpecificData = gpsSysSpecificData;
+
+ spd = pdev->dev.platform_data;
+ if (spd)
+ gpsSysSpecificData->sgx_fck_max = spd->fclock_max;
+
+ eError = OSInitEnvData(&gpsSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to setup env structure");
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_ENVDATA);
+
+ gpsSysData->ui32NumDevices = SYS_DEVICE_COUNT;
+
+ for (i = 0; i < SYS_DEVICE_COUNT; i++) {
+ gpsSysData->sDeviceID[i].uiID = i;
+ gpsSysData->sDeviceID[i].bInUse = IMG_FALSE;
+ }
+
+ gpsSysData->psDeviceNodeList = NULL;
+ gpsSysData->psQueueList = NULL;
+
+ eError = SysInitialiseCommon(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed in SysInitialiseCommon");
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+
+ TimerRegPhysBase.uiAddr =
+ SYS_OMAP3430_GP11TIMER_PHYS_BASE + SYS_OMAP3430_GPTIMER_REGS;
+ gpsSysData->pvSOCTimerRegisterKM = NULL;
+ gpsSysData->hSOCTimerRegisterOSMemHandle = NULL;
+ OSReservePhys(TimerRegPhysBase, 4,
+ PVRSRV_HAP_MULTI_PROCESS | PVRSRV_HAP_UNCACHED,
+ (void **)&gpsSysData->pvSOCTimerRegisterKM,
+ &gpsSysData->hSOCTimerRegisterOSMemHandle);
+
+ gpsSysSpecificData->ui32SrcClockDiv = 3;
+
+ eError = SysLocateDevices(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to locate devices");
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV);
+
+ if (sgx_ocp_init() < 0) {
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ eError = PVRSRVRegisterDevice(gpsSysData, SGXRegisterDevice,
+ DEVICE_SGX_INTERRUPT, &gui32SGXDeviceID);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to register device!");
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_REGDEV);
+
+ psDeviceNode = gpsSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ switch (psDeviceNode->sDevId.eDeviceType) {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ {
+ struct DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ struct DEVICE_MEMORY_HEAP_INFO
+ *psDeviceMemoryHeap;
+
+ psDeviceNode->psLocalDevMemArena = NULL;
+
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap =
+ psDevMemoryInfo->psDeviceMemoryHeap;
+
+ for (i = 0; i < psDevMemoryInfo->ui32HeapCount;
+ i++)
+ psDeviceMemoryHeap[i].ui32Attribs |=
+ PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG;
+
+ gpsSGXDevNode = psDeviceNode;
+ gsSysSpecificData.psSGXDevNode = psDeviceNode;
+
+ break;
+ }
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "SysInitialise: "
+ "Failed to find SGX device node!");
+ return PVRSRV_ERROR_INIT_FAILURE;
+ }
+
+ psDeviceNode = psDeviceNode->psNext;
+ }
+
+ PDUMPINIT();
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT);
+
+ eError = InitSystemClocks(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to init system clocks (%d)",
+ eError);
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+
+ eError = EnableSystemClocks(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to Enable system clocks (%d)",
+ eError);
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+
+ eError = OSInitPerf(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to init DVFS (%d)", eError);
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_PERF);
+
+ eError = EnableSGXClocks(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to Enable SGX clocks (%d)",
+ eError);
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+
+ eError = PVRSRVInitialiseDevice(gui32SGXDeviceID);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to initialise device!");
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_INITDEV);
+
+ gpsSysData->pszVersionString =
+ SysCreateVersionString(gsSGXDeviceMap.sRegsCpuPBase);
+ if (!gpsSysData->pszVersionString)
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysFinalise: Failed to create a system version string");
+ else
+ PVR_DPF(PVR_DBG_WARNING, "SysFinalise: Version string: %s",
+ gpsSysData->pszVersionString);
+
+ DisableSGXClocks(gpsSysData);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SysFinalise(void)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ eError = EnableSGXClocks(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysInitialise: Failed to Enable SGX clocks (%d)",
+ eError);
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+
+
+ eError = OSInstallMISR(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SysFinalise: Failed to install MISR");
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_MISR);
+
+ eError =
+ OSInstallDeviceLISR(gpsSysData, gsSGXDeviceMap.ui32IRQ, "SGX ISR",
+ gpsSGXDevNode);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SysFinalise: Failed to install ISR");
+ SysDeinitialise(gpsSysData);
+ gpsSysData = NULL;
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_LISR);
+
+ DisableSGXClocks(gpsSysData);
+
+ gpsSysSpecificData->bSGXInitComplete = IMG_TRUE;
+
+ return eError;
+}
+
+enum PVRSRV_ERROR SysDeinitialise(struct SYS_DATA *psSysData)
+{
+ enum PVRSRV_ERROR eError;
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR)) {
+ eError = OSUninstallDeviceLISR(psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SysDeinitialise: "
+ "OSUninstallDeviceLISR failed");
+ return eError;
+ }
+ }
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_MISR)) {
+ eError = OSUninstallMISR(psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SysDeinitialise: "
+ "OSUninstallMISR failed");
+ return eError;
+ }
+ }
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_INITDEV)) {
+ PVR_ASSERT(SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS));
+
+ eError = EnableSGXClocks(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysDeinitialise: EnableSGXClocks failed");
+ return eError;
+ }
+
+ eError = PVRSRVDeinitialiseDevice(gui32SGXDeviceID);
+
+ DisableSGXClocks(gpsSysData);
+
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR, "SysDeinitialise: "
+ "failed to de-init the device");
+ return eError;
+ }
+ }
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS))
+ DisableSystemClocks(gpsSysData);
+
+ CleanupSystemClocks(gpsSysData);
+
+ if (SYS_SPECIFIC_DATA_TEST(gpsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_PERF)) {
+ eError = OSCleanupPerf(psSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysDeinitialise: OSCleanupDvfs failed");
+ return eError;
+ }
+ }
+
+ sgx_ocp_cleanup();
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_ENVDATA)) {
+ eError = OSDeInitEnvData(gpsSysData->pvEnvSpecificData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysDeinitialise: failed to de-init env structure");
+ return eError;
+ }
+ }
+
+ if (gpsSysData->pvSOCTimerRegisterKM)
+ OSUnReservePhys(gpsSysData->pvSOCTimerRegisterKM, 4,
+ PVRSRV_HAP_MULTI_PROCESS | PVRSRV_HAP_UNCACHED,
+ gpsSysData->hSOCTimerRegisterOSMemHandle);
+
+ SysDeinitialiseCommon(gpsSysData);
+
+#if defined(NO_HARDWARE)
+ if (SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV))
+
+ OSBaseFreeContigMemory(SYS_OMAP3430_SGX_REGS_SIZE,
+ gsSGXRegsCPUVAddr,
+ gsSGXDeviceMap.sRegsCpuPBase);
+#endif
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (gpsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT))
+ PDUMPDEINIT();
+
+ gpsSysSpecificData->ui32SysSpecificData = 0;
+ gpsSysSpecificData->bSGXInitComplete = IMG_FALSE;
+
+ gpsSysData = NULL;
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SysGetDeviceMemoryMap(enum PVRSRV_DEVICE_TYPE eDeviceType,
+ void **ppvDeviceMap)
+{
+ switch (eDeviceType) {
+ case PVRSRV_DEVICE_TYPE_SGX:
+ *ppvDeviceMap = (void *) &gsSGXDeviceMap;
+ break;
+ default:
+ PVR_DPF(PVR_DBG_ERROR, "SysGetDeviceMemoryMap: "
+ "unsupported device type");
+ }
+ return PVRSRV_OK;
+}
+
+struct IMG_DEV_PHYADDR SysCpuPAddrToDevPAddr(
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ struct IMG_CPU_PHYADDR CpuPAddr)
+{
+ struct IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+ DevPAddr.uiAddr = CpuPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+struct IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(struct IMG_SYS_PHYADDR sys_paddr)
+{
+ struct IMG_CPU_PHYADDR cpu_paddr;
+
+ cpu_paddr.uiAddr = sys_paddr.uiAddr;
+ return cpu_paddr;
+}
+
+struct IMG_SYS_PHYADDR SysCpuPAddrToSysPAddr(struct IMG_CPU_PHYADDR cpu_paddr)
+{
+ struct IMG_SYS_PHYADDR sys_paddr;
+
+ sys_paddr.uiAddr = cpu_paddr.uiAddr;
+ return sys_paddr;
+}
+
+struct IMG_DEV_PHYADDR SysSysPAddrToDevPAddr(
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ struct IMG_SYS_PHYADDR SysPAddr)
+{
+ struct IMG_DEV_PHYADDR DevPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+ DevPAddr.uiAddr = SysPAddr.uiAddr;
+
+ return DevPAddr;
+}
+
+struct IMG_SYS_PHYADDR SysDevPAddrToSysPAddr(
+ enum PVRSRV_DEVICE_TYPE eDeviceType,
+ struct IMG_DEV_PHYADDR DevPAddr)
+{
+ struct IMG_SYS_PHYADDR SysPAddr;
+
+ PVR_UNREFERENCED_PARAMETER(eDeviceType);
+
+ SysPAddr.uiAddr = DevPAddr.uiAddr;
+
+ return SysPAddr;
+}
+
+void SysRegisterExternalDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+void SysRemoveExternalDevice(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+}
+
+u32 SysGetInterruptSource(struct SYS_DATA *psSysData,
+ struct PVRSRV_DEVICE_NODE *psDeviceNode)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+#if defined(NO_HARDWARE)
+
+ return 0xFFFFFFFF;
+#else
+
+ return psDeviceNode->ui32SOCInterruptBit;
+#endif
+}
+
+void SysClearInterrupts(struct SYS_DATA *psSysData, u32 ui32ClearBits)
+{
+ PVR_UNREFERENCED_PARAMETER(psSysData);
+ PVR_UNREFERENCED_PARAMETER(ui32ClearBits);
+
+ OSReadHWReg(((struct PVRSRV_SGXDEV_INFO *)gpsSGXDevNode->pvDevice)->
+ pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR);
+}
+
+enum PVRSRV_ERROR SysSystemPrePowerState(enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (eNewPowerState == PVRSRV_POWER_STATE_D3) {
+ PVR_TRACE("SysSystemPrePowerState: Entering state D3");
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_LISR)) {
+ eError = OSUninstallDeviceLISR(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysSystemPrePowerState: "
+ "OSUninstallDeviceLISR failed "
+ "(%d)",
+ eError);
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_LISR);
+ }
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (&gsSysSpecificData, SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS)) {
+ DisableSystemClocks(gpsSysData);
+
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+ }
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR SysSystemPostPowerState(enum PVR_POWER_STATE eNewPowerState)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ if (eNewPowerState == PVRSRV_POWER_STATE_D0) {
+ PVR_TRACE("SysSystemPostPowerState: Entering state D0");
+
+ if (SYS_SPECIFIC_DATA_TEST
+ (&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS)) {
+ eError = EnableSystemClocks(gpsSysData);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysSystemPostPowerState: "
+ "EnableSystemClocks failed (%d)",
+ eError);
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS);
+ }
+ if (SYS_SPECIFIC_DATA_TEST
+ (&gsSysSpecificData, SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR)) {
+ eError =
+ OSInstallDeviceLISR(gpsSysData,
+ gsSGXDeviceMap.ui32IRQ,
+ "SGX ISR", gpsSGXDevNode);
+ if (eError != PVRSRV_OK) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SysSystemPostPowerState: "
+ "OSInstallDeviceLISR failed "
+ "to install ISR (%d)",
+ eError);
+ return eError;
+ }
+ SYS_SPECIFIC_DATA_SET(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_ENABLE_LISR);
+ SYS_SPECIFIC_DATA_CLEAR(&gsSysSpecificData,
+ SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR);
+ }
+ }
+ return eError;
+}
+
+enum PVRSRV_ERROR SysDevicePrePowerState(u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE eCurrentPowerState)
+{
+ PVR_UNREFERENCED_PARAMETER(eCurrentPowerState);
+
+ if (ui32DeviceIndex != gui32SGXDeviceID)
+ return PVRSRV_OK;
+ if (eNewPowerState == PVRSRV_POWER_STATE_D3) {
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "SysDevicePrePowerState: SGX Entering state D3");
+ DisableSGXClocks(gpsSysData);
+ }
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR SysDevicePostPowerState(u32 ui32DeviceIndex,
+ enum PVR_POWER_STATE eNewPowerState,
+ enum PVR_POWER_STATE eCurrentPowerState)
+{
+ enum PVRSRV_ERROR eError = PVRSRV_OK;
+
+ PVR_UNREFERENCED_PARAMETER(eNewPowerState);
+
+ if (ui32DeviceIndex != gui32SGXDeviceID)
+ return eError;
+ if (eCurrentPowerState == PVRSRV_POWER_STATE_D3) {
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "SysDevicePostPowerState: SGX Leaving state D3");
+ eError = EnableSGXClocks(gpsSysData);
+ }
+
+ return eError;
+}
+
+enum PVRSRV_ERROR SysOEMFunction(u32 ui32ID, void *pvIn, u32 ulInSize,
+ void *pvOut, u32 ulOutSize)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32ID);
+ PVR_UNREFERENCED_PARAMETER(pvIn);
+ PVR_UNREFERENCED_PARAMETER(ulInSize);
+ PVR_UNREFERENCED_PARAMETER(pvOut);
+ PVR_UNREFERENCED_PARAMETER(ulOutSize);
+
+ if ((ui32ID == OEM_GET_EXT_FUNCS) &&
+ (ulOutSize == sizeof(struct PVRSRV_DC_OEM_JTABLE))) {
+
+ struct PVRSRV_DC_OEM_JTABLE *psOEMJTable =
+ (struct PVRSRV_DC_OEM_JTABLE *)pvOut;
+ psOEMJTable->pfnOEMBridgeDispatch = &PVRSRV_BridgeDispatchKM;
+ return PVRSRV_OK;
+ }
+
+ return PVRSRV_ERROR_INVALID_PARAMS;
+}
diff --git a/drivers/gpu/pvr/sysconfig.h b/drivers/gpu/pvr/sysconfig.h
new file mode 100644
index 00000000000..3ae1c6d00f7
--- /dev/null
+++ b/drivers/gpu/pvr/sysconfig.h
@@ -0,0 +1,53 @@
+/**********************************************************************
+ *
+ * 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(__SOCCONFIG_H__)
+#define __SOCCONFIG_H__
+
+#include "syscommon.h"
+
+#define VS_PRODUCT_NAME "OMAP3430"
+
+#define SYS_SGX_MAX_FREQ_NO_HW 200000000
+#define SYS_SGX_MAX_FREQ_530R121 110000000
+#define SYS_SGX_MAX_FREQ_530R125 200000000
+
+#define SYS_SGX_HWRECOVERY_TIMEOUT_FREQ 100
+#define SYS_SGX_PDS_TIMER_FREQ 1000
+#define SYS_SGX_ACTIVE_POWER_LATENCY_MS 1
+
+#define SYS_OMAP3430_SGX_REGS_SYS_PHYS_BASE 0x50000000
+#define SYS_OMAP3430_SGX_REGS_SIZE 0x4000
+
+#define SYS_OMAP3430_SGX_IRQ 21
+
+#define SYS_OMAP3430_GP11TIMER_PHYS_BASE 0x48088000
+#define SYS_OMAP3430_GPTIMER_ENABLE 0x24
+#define SYS_OMAP3430_GPTIMER_REGS 0x28
+#define SYS_OMAP3430_GPTIMER_TSICR 0x40
+#define SYS_OMAP3430_GPTIMER_SIZE 1024
+
+#endif
diff --git a/drivers/gpu/pvr/sysinfo.h b/drivers/gpu/pvr/sysinfo.h
new file mode 100644
index 00000000000..2af219da763
--- /dev/null
+++ b/drivers/gpu/pvr/sysinfo.h
@@ -0,0 +1,94 @@
+/**********************************************************************
+ *
+ * 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(__SYSINFO_H__)
+#define __SYSINFO_H__
+
+#define MAX_HW_TIME_US 500000
+#define WAIT_TRY_COUNT 10000
+
+enum SYS_DEVICE_TYPE {
+ SYS_DEVICE_SGX = 0,
+ SYS_DEVICE_FORCE_I16 = 0x7fff
+};
+
+#define SYS_DEVICE_COUNT 3
+
+#define PRM_REG32(offset) (offset)
+#define CM_REG32(offset) (offset)
+
+#define CM_FCLKEN_SGX CM_REG32(0xB00)
+#define CM_FCLKEN_SGX_EN_3D 0x00000002
+
+#define CM_ICLKEN_SGX CM_REG32(0xB10)
+#define CM_ICLKEN_SGX_EN_SGX 0x00000001
+
+#define CM_IDLEST_SGX CM_REG32(0xB20)
+#define CM_IDLEST_SGX_ST_SGX 0x00000001
+
+#define CM_CLKSEL_SGX CM_REG32(0xB40)
+#define CM_CLKSEL_SGX_MASK 0x0000000f
+#define CM_CLKSEL_SGX_L3DIV3 0x00000000
+#define CM_CLKSEL_SGX_L3DIV4 0x00000001
+#define CM_CLKSEL_SGX_L3DIV6 0x00000002
+#define CM_CLKSEL_SGX_96M 0x00000003
+
+#define CM_SLEEPDEP_SGX CM_REG32(0xB44)
+#define CM_CLKSTCTRL_SGX CM_REG32(0xB48)
+#define CM_CLKSTCTRL_SGX_AUTOSTATE 0x00008001
+
+#define CM_CLKSTST_SGX CM_REG32(0xB4C)
+#define CM_CLKSTST_SGX_STATUS_VALID 0x00000001
+
+#define RM_RSTST_SGX PRM_REG32(0xB58)
+#define RM_RSTST_SGX_RST_MASK 0x0000000F
+#define RM_RSTST_SGX_COREDOMAINWKUP_RST 0x00000008
+#define RM_RSTST_SGX_DOMAINWKUP_RST 0x00000004
+#define RM_RSTST_SGX_GLOBALWARM_RST 0x00000002
+#define RM_RSTST_SGX_GLOBALCOLD_RST 0x00000001
+
+#define PM_WKDEP_SGXi PRM_REG32(0xBC8)
+#define PM_WKDEP_SGX_EN_WAKEUP 0x00000010
+#define PM_WKDEP_SGX_EN_MPU 0x00000002
+#define PM_WKDEP_SGX_EN_CORE 0x00000001
+
+#define PM_PWSTCTRL_SGX PRM_REG32(0xBE0)
+#define PM_PWSTCTRL_SGX_POWERSTATE_MASK 0x00000003
+#define PM_PWSTCTRL_SGX_OFF 0x00000000
+#define PM_PWSTCTRL_SGX_RETENTION 0x00000001
+#define PM_PWSTCTRL_SGX_ON 0x00000003
+
+#define PM_PWSTST_SGX PRM_REG32(0xBE4)
+#define PM_PWSTST_SGX_INTRANSITION 0x00100000
+#define PM_PWSTST_SGX_CLKACTIVITY 0x00080000
+#define PM_PWSTST_SGX_POWERSTATE_MASK 0x00000003
+#define PM_PWSTST_SGX_OFF 0x00000003
+#define PM_PWSTST_SGX_RETENTION 0x00000001
+#define PM_PWSTST_SGX_ON 0x00000000
+
+#define PM_PREPWSTST_SGX PRM_REG32(0xBE8)
+
+#endif
diff --git a/drivers/gpu/pvr/syslocal.h b/drivers/gpu/pvr/syslocal.h
new file mode 100644
index 00000000000..0cda586c114
--- /dev/null
+++ b/drivers/gpu/pvr/syslocal.h
@@ -0,0 +1,100 @@
+/**********************************************************************
+ *
+ * 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(__SYSLOCAL_H__)
+#define __SYSLOCAL_H__
+
+#include <linux/version.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+#include <linux/semaphore.h>
+#include <linux/resource.h>
+
+char *SysCreateVersionString(struct IMG_CPU_PHYADDR sRegRegion);
+
+enum PVRSRV_ERROR InitSystemClocks(struct SYS_DATA *psSysData);
+void CleanupSystemClocks(struct SYS_DATA *psSysData);
+void DisableSystemClocks(struct SYS_DATA *psSysData);
+enum PVRSRV_ERROR EnableSystemClocks(struct SYS_DATA *psSysData);
+
+void DisableSGXClocks(struct SYS_DATA *psSysData);
+enum PVRSRV_ERROR EnableSGXClocks(struct SYS_DATA *psSysData);
+
+#define SYS_SPECIFIC_DATA_ENABLE_SYSCLOCKS 0x00000001
+#define SYS_SPECIFIC_DATA_ENABLE_LISR 0x00000002
+#define SYS_SPECIFIC_DATA_ENABLE_MISR 0x00000004
+#define SYS_SPECIFIC_DATA_ENABLE_ENVDATA 0x00000008
+#define SYS_SPECIFIC_DATA_ENABLE_LOCDEV 0x00000010
+#define SYS_SPECIFIC_DATA_ENABLE_REGDEV 0x00000020
+#define SYS_SPECIFIC_DATA_ENABLE_PDUMPINIT 0x00000040
+#define SYS_SPECIFIC_DATA_ENABLE_INITDEV 0x00000080
+#define SYS_SPECIFIC_DATA_ENABLE_LOCATEDEV 0x00000100
+
+#define SYS_SPECIFIC_DATA_PM_UNINSTALL_LISR 0x00000200
+#define SYS_SPECIFIC_DATA_PM_DISABLE_SYSCLOCKS 0x00000400
+#define SYS_SPECIFIC_DATA_ENABLE_PERF 0x00000800
+
+#define SYS_SPECIFIC_DATA_SET(psSysSpecData, flag) \
+ ((void)((psSysSpecData)->ui32SysSpecificData |= (flag)))
+
+#define SYS_SPECIFIC_DATA_CLEAR(psSysSpecData, flag) \
+ ((void)((psSysSpecData)->ui32SysSpecificData &= ~(flag)))
+
+#define SYS_SPECIFIC_DATA_TEST(psSysSpecData, flag) \
+ (((psSysSpecData)->ui32SysSpecificData & (flag)) != 0)
+
+struct SYS_SPECIFIC_DATA {
+ u32 ui32SysSpecificData;
+ struct PVRSRV_DEVICE_NODE *psSGXDevNode;
+ IMG_BOOL bSGXInitComplete;
+ u32 ui32SrcClockDiv;
+ IMG_BOOL bConstraintNotificationsEnabled;
+ atomic_t sSGXClocksEnabled;
+ spinlock_t sPowerLock;
+ atomic_t sPowerLockCPU;
+ spinlock_t sNotifyLock;
+ atomic_t sNotifyLockCPU;
+ IMG_BOOL bCallVDD2PostFunc;
+
+ struct clk *psCORE_CK;
+ struct clk *psSGX_FCK;
+ struct clk *psSGX_ICK;
+ struct clk *psMPU_CK;
+#if defined(CONFIG_PVR_DEBUG_EXTRA) || defined(TIMING)
+ struct clk *psGPT11_FCK;
+ struct clk *psGPT11_ICK;
+ void __iomem *gpt_base;
+#endif
+ struct constraint_handle *pVdd2Handle;
+
+ unsigned long sgx_fck_max;
+};
+
+extern struct SYS_SPECIFIC_DATA *gpsSysSpecificData;
+
+#endif
diff --git a/drivers/gpu/pvr/sysutils.c b/drivers/gpu/pvr/sysutils.c
new file mode 100644
index 00000000000..96870f3bca1
--- /dev/null
+++ b/drivers/gpu/pvr/sysutils.c
@@ -0,0 +1,731 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <plat/omap-pm.h>
+#include <linux/bug.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "sysinfo.h"
+#include "sgxapi_km.h"
+#include "sysconfig.h"
+#include "sgxinfokm.h"
+#include "syslocal.h"
+#include "env_data.h"
+#include "ocpdefs.h"
+#include "pvr_bridge_km.h"
+
+#define HZ_TO_MHZ(m) ((m) / 1000000)
+
+static inline unsigned long scale_by_rate(unsigned long val,
+ unsigned long rate1,
+ unsigned long rate2)
+{
+ if (rate1 >= rate2)
+ return val * (rate1 / rate2);
+
+ return val / (rate2 / rate1);
+}
+
+static inline unsigned long scale_prop_to_SGX_clock(unsigned long val,
+ unsigned long rate)
+{
+ return scale_by_rate(val, rate, sgx_get_max_freq());
+}
+
+void SysGetSGXTimingInformation(struct SGX_TIMING_INFORMATION *psTimingInfo)
+{
+ unsigned long rate;
+
+#if defined(NO_HARDWARE)
+ rate = SYS_SGX_MAX_FREQ_NO_HW;
+#else
+ rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
+ PVR_ASSERT(rate != 0);
+#endif
+ psTimingInfo->ui32CoreClockSpeed = rate;
+ psTimingInfo->ui32HWRecoveryFreq =
+ scale_prop_to_SGX_clock(SYS_SGX_HWRECOVERY_TIMEOUT_FREQ, rate);
+ psTimingInfo->ui32uKernelFreq =
+ scale_prop_to_SGX_clock(SYS_SGX_PDS_TIMER_FREQ, rate);
+ psTimingInfo->ui32ActivePowManLatencyms =
+ SYS_SGX_ACTIVE_POWER_LATENCY_MS;
+}
+
+static int vdd2_post_func(struct notifier_block *n, unsigned long event,
+ void *ptr)
+{
+ PVR_UNREFERENCED_PARAMETER(n);
+ PVR_UNREFERENCED_PARAMETER(event);
+ PVR_UNREFERENCED_PARAMETER(ptr);
+
+ if (atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0 &&
+ gpsSysSpecificData->bSGXInitComplete) {
+#if defined(CONFIG_PVR_DEBUG_EXTRA)
+ unsigned long rate;
+
+ rate = clk_get_rate(gpsSysSpecificData->psSGX_FCK);
+
+ PVR_ASSERT(rate != 0);
+
+ PVR_TRACE("%s: SGX clock rate: %dMHz", __func__,
+ HZ_TO_MHZ(rate));
+#endif
+ PVRSRVDevicePostClockSpeedChange(gpsSysSpecificData->
+ psSGXDevNode->sDevId.
+ ui32DeviceIndex, IMG_TRUE,
+ NULL);
+ }
+ return 0;
+}
+
+static int vdd2_pre_func(struct notifier_block *n, unsigned long event,
+ void *ptr)
+{
+ PVR_UNREFERENCED_PARAMETER(n);
+ PVR_UNREFERENCED_PARAMETER(event);
+ PVR_UNREFERENCED_PARAMETER(ptr);
+
+ if (atomic_read(&gpsSysSpecificData->sSGXClocksEnabled) != 0 &&
+ gpsSysSpecificData->bSGXInitComplete) {
+ BUG_ON(gpsSysData->eCurrentPowerState > PVRSRV_POWER_STATE_D1);
+ PVRSRVDevicePreClockSpeedChange(gpsSysSpecificData->
+ psSGXDevNode->sDevId.
+ ui32DeviceIndex, IMG_TRUE,
+ NULL);
+ }
+
+ return 0;
+}
+
+static int vdd2_pre_post_func(struct notifier_block *n, unsigned long event,
+ void *ptr)
+{
+ PVR_UNREFERENCED_PARAMETER(n);
+
+ if (CPUFREQ_PRECHANGE == event) {
+ pvr_dev_lock();
+ PVR_TRACE("vdd2_pre_post_func: CPUFREQ_PRECHANGE event");
+ vdd2_pre_func(n, event, ptr);
+ } else if (CPUFREQ_POSTCHANGE == event) {
+ PVR_TRACE("vdd2_pre_post_func: CPUFREQ_POSTCHANGE event");
+ vdd2_post_func(n, event, ptr);
+ pvr_dev_unlock();
+ } else {
+ printk(KERN_ERR "vdd2_pre_post_func: unexpected event (%lu)\n",
+ event);
+ PVR_DPF(PVR_DBG_ERROR,
+ "vdd2_pre_post_func: unexpected event (%lu)", event);
+ }
+ PVR_TRACE("vdd2_pre_post_func end.");
+ return 0;
+}
+
+static struct notifier_block vdd2_pre_post = {
+ vdd2_pre_post_func,
+ NULL
+};
+
+static void RegisterConstraintNotifications(struct SYS_SPECIFIC_DATA
+ *psSysSpecData)
+{
+ PVR_TRACE("Registering constraint notifications");
+
+ cpufreq_register_notifier(&vdd2_pre_post, CPUFREQ_TRANSITION_NOTIFIER);
+
+ PVR_TRACE("VDD2 constraint notifications registered");
+}
+
+static void UnRegisterConstraintNotifications(struct SYS_SPECIFIC_DATA
+ *psSysSpecData)
+{
+ PVR_TRACE("Unregistering constraint notifications");
+
+ cpufreq_unregister_notifier(&vdd2_pre_post, CPUFREQ_TRANSITION_NOTIFIER);
+}
+
+static struct device sgx_dev;
+static int sgx_clock_enabled;
+
+/* return value: current sgx load
+ * 0 - not busy
+ * 100 - busy
+ */
+static unsigned int sgx_current_load(void)
+{
+ enum PVRSRV_ERROR eError;
+ struct SYS_DATA *psSysData;
+ struct SYS_SPECIFIC_DATA *psSysSpecData;
+ struct PVRSRV_DEVICE_NODE *psDeviceNode;
+ static unsigned int kicks_prev;
+ static long time_prev;
+
+ eError = SysAcquireData(&psSysData);
+ if (eError != PVRSRV_OK)
+ return 0;
+ psSysSpecData =
+ (struct SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+ if (!psSysSpecData ||
+ atomic_read(&psSysSpecData->sSGXClocksEnabled) == 0)
+ return 0;
+ psDeviceNode = psSysData->psDeviceNodeList;
+ while (psDeviceNode) {
+ if ((psDeviceNode->sDevId.eDeviceType ==
+ PVRSRV_DEVICE_TYPE_SGX) &&
+ psDeviceNode->pvDevice) {
+ struct PVRSRV_SGXDEV_INFO *psDevInfo =
+ (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
+ unsigned int kicks = psDevInfo->ui32KickTACounter;
+ unsigned int load;
+ long time_elapsed;
+
+ time_elapsed = jiffies - time_prev;
+ if (likely(time_elapsed))
+ load =
+ 1000 * (kicks - kicks_prev) / time_elapsed;
+ else
+ load = 0;
+ kicks_prev = kicks;
+ time_prev += time_elapsed;
+ /*
+ * if the period between calls to this function was
+ * too long, then load stats are invalid
+ */
+ if (time_elapsed > 5 * HZ)
+ return 0;
+ /*pr_err("SGX load %u\n", load); */
+
+ /*
+ * 'load' shows how many times sgx was kicked
+ * per 1000 jiffies
+ * 150 is arbitrarily chosen threshold.
+ * If the number of kicks is below threshold
+ * then sgx is doing
+ * some small jobs and we can keep the clock freq low.
+ */
+ if (load < 150)
+ return 0;
+ else
+ return 100;
+ }
+ psDeviceNode = psDeviceNode->psNext;
+ }
+ return 0;
+}
+
+static void sgx_lock_perf(struct work_struct *work)
+{
+ int vdd1, vdd2;
+ static int bHigh;
+ int high;
+ unsigned int load;
+ struct delayed_work *d_work =
+ container_of(work, struct delayed_work, work);
+ struct ENV_DATA *psEnvData =
+ container_of(d_work, struct ENV_DATA, sPerfWork);
+
+ pvr_lock();
+
+ if (pvr_is_disabled()) {
+ pvr_unlock();
+ return;
+ }
+
+ load = sgx_current_load();
+
+ pvr_unlock();
+
+ if (load) {
+ vdd1 = 500000000;
+ vdd2 = 400000;
+ high = 1;
+ } else {
+ vdd1 = 0;
+ vdd2 = 0;
+ high = 0;
+ }
+ if (high != bHigh) {
+ omap_pm_set_min_bus_tput(&sgx_dev, OCP_INITIATOR_AGENT, vdd2);
+ bHigh = high;
+ }
+
+ if (sgx_clock_enabled || load)
+ queue_delayed_work(psEnvData->psPerfWorkqueue,
+ &psEnvData->sPerfWork, HZ / 5);
+}
+
+static void sgx_need_perf(struct SYS_DATA *psSysData, int ena)
+{
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ sgx_clock_enabled = ena;
+ cancel_delayed_work(&psEnvData->sPerfWork);
+ queue_delayed_work(psEnvData->psPerfWorkqueue, &psEnvData->sPerfWork,
+ 0);
+}
+
+enum PVRSRV_ERROR OSInitPerf(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (psEnvData->psPerfWorkqueue) {
+ PVR_DPF(PVR_DBG_ERROR, "OSInitPerf: already inited");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE("Initing DVFS %x", pvSysData);
+
+ psEnvData->psPerfWorkqueue = create_singlethread_workqueue("sgx_perf");
+ INIT_DELAYED_WORK(&psEnvData->sPerfWork, sgx_lock_perf);
+
+ return PVRSRV_OK;
+}
+
+enum PVRSRV_ERROR OSCleanupPerf(void *pvSysData)
+{
+ struct SYS_DATA *psSysData = (struct SYS_DATA *)pvSysData;
+ struct ENV_DATA *psEnvData =
+ (struct ENV_DATA *)psSysData->pvEnvSpecificData;
+
+ if (!psEnvData->psPerfWorkqueue) {
+ PVR_DPF(PVR_DBG_ERROR, "OSCleanupPerf: not inited");
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ PVR_TRACE("Cleaning up DVFS");
+
+ sgx_clock_enabled = 0;
+ flush_workqueue(psEnvData->psPerfWorkqueue);
+ destroy_workqueue(psEnvData->psPerfWorkqueue);
+
+ return PVRSRV_OK;
+}
+
+static inline void setup_int_bypass(void)
+{
+ if (cpu_is_omap3630())
+ sgx_ocp_write_reg(EUR_CR_OCP_DEBUG_CONFIG,
+ EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_MASK);
+}
+
+#ifndef NO_HARDWARE
+
+static enum PVRSRV_ERROR sgx_force_enable_clocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData =
+ (struct SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+ int res;
+
+ res = clk_enable(psSysSpecData->psSGX_FCK);
+ if (res < 0) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: "
+ "Couldn't enable SGX functional clock (%d)",
+ __func__, res);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ res = clk_enable(psSysSpecData->psSGX_ICK);
+ if (res < 0) {
+ PVR_DPF(PVR_DBG_ERROR, "%s: "
+ "Couldn't enable SGX interface clock (%d)",
+ __func__, res);
+
+ clk_disable(psSysSpecData->psSGX_FCK);
+ return PVRSRV_ERROR_GENERIC;
+ }
+
+ setup_int_bypass();
+
+ return PVRSRV_OK;
+}
+
+static void sgx_force_disable_clocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData =
+ (struct SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+
+ if (psSysSpecData->psSGX_ICK)
+ clk_disable(psSysSpecData->psSGX_ICK);
+
+ if (psSysSpecData->psSGX_FCK)
+ clk_disable(psSysSpecData->psSGX_FCK);
+}
+
+#else /* NO_HARDWARE */
+
+static enum PVRSRV_ERROR sgx_force_enable_clocks(struct SYS_DATA *psSYsData)
+{
+ return PVRSRV_OK;
+}
+
+static void sgx_force_disable_clocks(struct SYS_DATA *psSYsData)
+{
+}
+
+#endif /* NO_HARDWARE */
+
+static bool force_clocks_on(void)
+{
+#ifdef CONFIG_PVR_FORCE_CLOCKS_ON
+ return true;
+#else
+ return false;
+#endif
+}
+
+enum PVRSRV_ERROR EnableSGXClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData =
+ (struct SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+ enum PVRSRV_ERROR res = PVRSRV_OK;
+
+ if (atomic_xchg(&psSysSpecData->sSGXClocksEnabled, 1))
+ return PVRSRV_OK;
+
+ /*
+ * In case of force clocks on we have already enabled the clocks
+ * at init time.
+ */
+ if (!force_clocks_on())
+ res = sgx_force_enable_clocks(psSysData);
+
+ if (res == PVRSRV_OK) {
+ BUG_ON(!atomic_read(&psSysSpecData->sSGXClocksEnabled));
+ sgx_need_perf(psSysData, 1);
+ } else {
+ atomic_set(&psSysSpecData->sSGXClocksEnabled, 0);
+ }
+
+ return res;
+}
+
+void DisableSGXClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData =
+ (struct SYS_SPECIFIC_DATA *)psSysData->pvSysSpecificData;
+
+ if (!atomic_xchg(&psSysSpecData->sSGXClocksEnabled, 0))
+ return;
+
+ if (!force_clocks_on())
+ sgx_force_disable_clocks(psSysData);
+
+ BUG_ON(atomic_read(&psSysSpecData->sSGXClocksEnabled));
+
+ sgx_need_perf(psSysData, 0);
+}
+
+static enum PVRSRV_ERROR InitSgxClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+ struct clk *psCLK;
+ struct clk *core_ck = NULL;
+ unsigned long rate;
+ int r;
+
+ psCLK = clk_get(NULL, "sgx_fck");
+ if (IS_ERR(psCLK))
+ goto err0;
+ psSysSpecData->psSGX_FCK = psCLK;
+
+ psCLK = clk_get(NULL, "sgx_ick");
+ if (IS_ERR(psCLK))
+ goto err1;
+ psSysSpecData->psSGX_ICK = psCLK;
+
+ core_ck = clk_get(NULL, "core_ck");
+ if (IS_ERR(core_ck))
+ goto err2;
+ if (clk_set_parent(psSysSpecData->psSGX_FCK, core_ck) < 0) {
+ clk_put(core_ck);
+ goto err2;
+ }
+ clk_put(core_ck);
+
+ /* +1 to account for rounding errors */
+ rate = clk_round_rate(psSysSpecData->psSGX_FCK, sgx_get_max_freq() + 1);
+ r = clk_set_rate(psSysSpecData->psSGX_FCK, rate);
+ if (r < 0) {
+ unsigned long current_rate;
+
+ current_rate = clk_get_rate(psSysSpecData->psSGX_FCK);
+ pr_warning("error %d when setting SGX fclk to %lu Hz, "
+ "falling back to %lu Hz\n", r, rate, current_rate);
+ } else {
+ pr_info("SGX clock rate %lu MHz\n", rate / 1000000);
+ };
+
+ RegisterConstraintNotifications(psSysSpecData);
+ return PVRSRV_OK;
+
+err2:
+ clk_put(psSysSpecData->psSGX_ICK);
+err1:
+ clk_put(psSysSpecData->psSGX_FCK);
+err0:
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: couldn't init clocks fck %p ick %p core %p", __func__,
+ psSysSpecData->psSGX_FCK, psSysSpecData->psSGX_ICK, core_ck);
+ psSysSpecData->psSGX_FCK = NULL;
+ psSysSpecData->psSGX_ICK = NULL;
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+static void CleanupSgxClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+ UnRegisterConstraintNotifications(psSysSpecData);
+
+ if (psSysSpecData->psSGX_ICK) {
+ clk_put(psSysSpecData->psSGX_ICK);
+ psSysSpecData->psSGX_ICK = NULL;
+ }
+
+ if (psSysSpecData->psSGX_FCK) {
+ clk_put(psSysSpecData->psSGX_FCK);
+ psSysSpecData->psSGX_FCK = NULL;
+ }
+}
+
+#if defined(CONFIG_PVR_DEBUG_EXTRA) || defined(TIMING)
+static inline u32 gpt_read_reg(struct SYS_DATA *psSysData, u32 reg)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ return __raw_readl(psSysSpecData->gpt_base + reg);
+}
+
+static inline void gpt_write_reg(struct SYS_DATA *psSysData, u32 reg, u32 val)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ __raw_writel(val, psSysSpecData->gpt_base + reg);
+}
+
+static enum PVRSRV_ERROR InitDebugClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+ struct clk *psCLK;
+ struct clk *sys_ck = NULL;
+ u32 rate;
+
+ psCLK = clk_get(NULL, "mpu_ck");
+ if (IS_ERR(psCLK))
+ goto err0;
+ psSysSpecData->psMPU_CK = psCLK;
+
+ psCLK = clk_get(NULL, "gpt11_fck");
+ if (IS_ERR(psCLK))
+ goto err1;
+ psSysSpecData->psGPT11_FCK = psCLK;
+
+ psCLK = clk_get(NULL, "gpt11_ick");
+ if (IS_ERR(psCLK))
+ goto err2;
+ psSysSpecData->psGPT11_ICK = psCLK;
+
+ sys_ck = clk_get(NULL, "sys_ck");
+ if (IS_ERR(sys_ck))
+ goto err3;
+ if (clk_get_parent(psSysSpecData->psGPT11_FCK) != sys_ck)
+ if (clk_set_parent(psSysSpecData->psGPT11_FCK, sys_ck) < 0) {
+ clk_put(sys_ck);
+ goto err3;
+ }
+ clk_put(sys_ck);
+
+ PVR_TRACE("GPTIMER11 clock is %dMHz",
+ HZ_TO_MHZ(clk_get_rate(psSysSpecData->psGPT11_FCK)));
+
+ psSysSpecData->gpt_base = ioremap(SYS_OMAP3430_GP11TIMER_PHYS_BASE,
+ SYS_OMAP3430_GPTIMER_SIZE);
+ if (!psSysSpecData->gpt_base)
+ goto err3;
+
+ clk_enable(psSysSpecData->psGPT11_ICK);
+ clk_enable(psSysSpecData->psGPT11_FCK);
+
+ rate = gpt_read_reg(psSysData, SYS_OMAP3430_GPTIMER_TSICR);
+ if (!(rate & 4)) {
+ PVR_TRACE("Setting GPTIMER11 mode to posted "
+ "(currently is non-posted)");
+ gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_TSICR, rate | 4);
+ }
+
+ clk_disable(psSysSpecData->psGPT11_FCK);
+ clk_disable(psSysSpecData->psGPT11_ICK);
+
+ return PVRSRV_OK;
+
+err3:
+ clk_put(psSysSpecData->psGPT11_ICK);
+err2:
+ clk_put(psSysSpecData->psGPT11_FCK);
+err1:
+ clk_put(psSysSpecData->psMPU_CK);
+err0:
+ PVR_DPF(PVR_DBG_ERROR,
+ "%s: couldn't init clocks: mpu %p sys %p fck %p ick %p",
+ __func__, psSysSpecData->psMPU_CK, sys_ck,
+ psSysSpecData->psGPT11_FCK, psSysSpecData->psGPT11_ICK);
+
+ psSysSpecData->psMPU_CK = NULL;
+ psSysSpecData->psGPT11_FCK = NULL;
+ psSysSpecData->psGPT11_ICK = NULL;
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+static void CleanupDebugClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ if (psSysSpecData->psMPU_CK) {
+ clk_put(psSysSpecData->psMPU_CK);
+ psSysSpecData->psMPU_CK = NULL;
+ }
+ if (psSysSpecData->psGPT11_FCK) {
+ clk_put(psSysSpecData->psGPT11_FCK);
+ psSysSpecData->psGPT11_FCK = NULL;
+ }
+ if (psSysSpecData->psGPT11_ICK) {
+ clk_put(psSysSpecData->psGPT11_ICK);
+ psSysSpecData->psGPT11_ICK = NULL;
+ }
+}
+
+static enum PVRSRV_ERROR EnableDebugClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ if (clk_enable(psSysSpecData->psGPT11_FCK) < 0)
+ goto err0;
+
+ if (clk_enable(psSysSpecData->psGPT11_ICK) < 0)
+ goto err1;
+
+ gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_ENABLE, 3);
+
+ return PVRSRV_OK;
+
+err1:
+ clk_disable(psSysSpecData->psGPT11_FCK);
+err0:
+ PVR_DPF(PVR_DBG_ERROR, "%s: can't enable clocks", __func__);
+
+ return PVRSRV_ERROR_GENERIC;
+}
+
+static inline void DisableDebugClocks(struct SYS_DATA *psSysData)
+{
+ struct SYS_SPECIFIC_DATA *psSysSpecData = psSysData->pvSysSpecificData;
+
+ gpt_write_reg(psSysData, SYS_OMAP3430_GPTIMER_ENABLE, 0);
+
+ clk_disable(psSysSpecData->psGPT11_ICK);
+ clk_disable(psSysSpecData->psGPT11_FCK);
+}
+
+#else
+
+inline enum PVRSRV_ERROR InitDebugClocks(struct SYS_DATA *psSysData)
+{
+ return PVRSRV_OK;
+}
+
+static inline void CleanupDebugClocks(struct SYS_DATA *psSysData)
+{
+}
+
+static inline enum PVRSRV_ERROR EnableDebugClocks(struct SYS_DATA *psSysData)
+{
+ return PVRSRV_OK;
+}
+
+static inline void DisableDebugClocks(struct SYS_DATA *psSysData)
+{
+}
+#endif
+
+enum PVRSRV_ERROR InitSystemClocks(struct SYS_DATA *psSysData)
+{
+ if (InitSgxClocks(psSysData) != PVRSRV_OK)
+ goto err0;
+
+ if (InitDebugClocks(psSysData) != PVRSRV_OK)
+ goto err1;
+
+ return PVRSRV_OK;
+
+err1:
+ CleanupSgxClocks(psSysData);
+err0:
+ return PVRSRV_ERROR_GENERIC;
+}
+
+void CleanupSystemClocks(struct SYS_DATA *psSysData)
+{
+ CleanupDebugClocks(psSysData);
+ CleanupSgxClocks(psSysData);
+}
+
+enum PVRSRV_ERROR EnableSystemClocks(struct SYS_DATA *psSysData)
+{
+ PVR_TRACE("EnableSystemClocks: Enabling System Clocks");
+
+ /*
+ * We force clocks on by increasing their refcount here during
+ * module init time and decreasing it at cleanup time.
+ */
+ if (force_clocks_on())
+ sgx_force_enable_clocks(gpsSysData);
+ if (EnableDebugClocks(psSysData) != PVRSRV_OK)
+ goto err1;
+
+ return PVRSRV_OK;
+
+err1:
+ return PVRSRV_ERROR_GENERIC;
+}
+
+void DisableSystemClocks(struct SYS_DATA *psSysData)
+{
+ PVR_TRACE("DisableSystemClocks: Disabling System Clocks");
+
+ DisableDebugClocks(psSysData);
+ /* Decrease the clocks' refcount that was increased at init time. */
+ if (force_clocks_on())
+ sgx_force_disable_clocks(gpsSysData);
+}
diff --git a/drivers/gpu/pvr/tools/Makefile b/drivers/gpu/pvr/tools/Makefile
new file mode 100644
index 00000000000..27314dabcb3
--- /dev/null
+++ b/drivers/gpu/pvr/tools/Makefile
@@ -0,0 +1,29 @@
+#
+# 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
+
+
+objs-$(CONFIG_PVR_TOOLS) += dbgdrv
+
+dbgdrv-objs := main.c dbgdriv.c ioctl.c hostfunc.c \
+ hotkey.c
+
diff --git a/drivers/gpu/pvr/tools/dbgdriv.c b/drivers/gpu/pvr/tools/dbgdriv.c
new file mode 100644
index 00000000000..1ab5e70e762
--- /dev/null
+++ b/drivers/gpu/pvr/tools/dbgdriv.c
@@ -0,0 +1,1652 @@
+/**********************************************************************
+ *
+ * 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 <linux/string.h>
+
+#include "img_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+#define LAST_FRAME_BUF_SIZE 1024
+
+struct DBG_LASTFRAME_BUFFER {
+ struct DBG_STREAM *psStream;
+ u8 ui8Buffer[LAST_FRAME_BUF_SIZE];
+ u32 ui32BufLen;
+ struct DBG_LASTFRAME_BUFFER *psNext;
+};
+
+static struct DBG_STREAM *g_psStreamList;
+static struct DBG_LASTFRAME_BUFFER *g_psLFBufferList;
+
+static u32 g_ui32LOff;
+static u32 g_ui32Line;
+static u32 g_ui32MonoLines = 25;
+
+static IMG_BOOL g_bHotkeyMiddump = IMG_FALSE;
+static u32 g_ui32HotkeyMiddumpStart = 0xffffffff;
+static u32 g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+void *g_pvAPIMutex;
+
+IMG_BOOL gbDumpThisFrame = IMG_FALSE;
+
+static u32 SpaceInStream(struct DBG_STREAM *psStream);
+static IMG_BOOL ExpandStreamBuffer(struct DBG_STREAM *psStream,
+ u32 ui32NewSize);
+struct DBG_LASTFRAME_BUFFER *FindLFBuf(struct DBG_STREAM *psStream);
+
+struct DBGKM_SERVICE_TABLE g_sDBGKMServices = {
+ sizeof(struct DBGKM_SERVICE_TABLE),
+ ExtDBGDrivCreateStream,
+ ExtDBGDrivDestroyStream,
+ ExtDBGDrivFindStream,
+ ExtDBGDrivWriteString,
+ ExtDBGDrivReadString,
+ ExtDBGDrivWrite,
+ ExtDBGDrivRead,
+ ExtDBGDrivSetCaptureMode,
+ ExtDBGDrivSetOutputMode,
+ ExtDBGDrivSetDebugLevel,
+ ExtDBGDrivSetFrame,
+ ExtDBGDrivGetFrame,
+ ExtDBGDrivOverrideMode,
+ ExtDBGDrivDefaultMode,
+ ExtDBGDrivWrite2,
+ ExtDBGDrivWriteStringCM,
+ ExtDBGDrivWriteCM,
+ ExtDBGDrivSetMarker,
+ ExtDBGDrivGetMarker,
+ ExtDBGDrivStartInitPhase,
+ ExtDBGDrivStopInitPhase,
+ ExtDBGDrivIsCaptureFrame,
+ ExtDBGDrivWriteLF,
+ ExtDBGDrivReadLF,
+ ExtDBGDrivGetStreamOffset,
+ ExtDBGDrivSetStreamOffset,
+ ExtDBGDrivIsLastCaptureFrame,
+ ExtDBGDrivWaitForEvent
+};
+
+void *ExtDBGDrivCreateStream(char *pszName,
+ u32 ui32CapMode,
+ u32 ui32OutMode,
+ u32 ui32Flags,
+ u32 ui32Size)
+{
+ void *pvRet;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet =
+ DBGDrivCreateStream(pszName, ui32CapMode, ui32OutMode, ui32Flags,
+ ui32Size);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+void ExtDBGDrivDestroyStream(struct DBG_STREAM *psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDestroyStream(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void *ExtDBGDrivFindStream(char *pszName,
+ IMG_BOOL bResetStream)
+{
+ void *pvRet;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ pvRet = DBGDrivFindStream(pszName, bResetStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return pvRet;
+}
+
+u32 ExtDBGDrivWriteString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Level)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivWriteString(psStream, pszString, ui32Level);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivReadString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Limit)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivReadString(psStream, pszString, ui32Limit);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivWrite(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivWrite(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivRead(struct DBG_STREAM *psStream,
+ IMG_BOOL bReadInitBuffer,
+ u32 ui32OutBuffSize,
+ u8 *pui8OutBuf)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret =
+ DBGDrivRead(psStream, bReadInitBuffer, ui32OutBuffSize, pui8OutBuf);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void ExtDBGDrivSetCaptureMode(struct DBG_STREAM *psStream,
+ u32 ui32Mode,
+ u32 ui32Start,
+ u32 ui32End,
+ u32 ui32SampleRate)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetCaptureMode(psStream, ui32Mode, ui32Start, ui32End,
+ ui32SampleRate);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void ExtDBGDrivSetOutputMode(struct DBG_STREAM *psStream,
+ u32 ui32OutMode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetOutputMode(psStream, ui32OutMode);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void ExtDBGDrivSetDebugLevel(struct DBG_STREAM *psStream,
+ u32 ui32DebugLevel)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetDebugLevel(psStream, ui32DebugLevel);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void ExtDBGDrivSetFrame(struct DBG_STREAM *psStream, u32 ui32Frame)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetFrame(psStream, ui32Frame);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+u32 ExtDBGDrivGetFrame(struct DBG_STREAM *psStream)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivGetFrame(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivIsLastCaptureFrame(struct DBG_STREAM *psStream)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivIsLastCaptureFrame(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivIsCaptureFrame(struct DBG_STREAM *psStream,
+ IMG_BOOL bCheckPreviousFrame)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivIsCaptureFrame(psStream, bCheckPreviousFrame);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void ExtDBGDrivOverrideMode(struct DBG_STREAM *psStream,
+ u32 ui32Mode)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivOverrideMode(psStream, ui32Mode);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void ExtDBGDrivDefaultMode(struct DBG_STREAM *psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivDefaultMode(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+u32 ExtDBGDrivWrite2(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivWriteStringCM(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Level)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivWriteStringCM(psStream, pszString, ui32Level);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivWriteCM(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret =
+ DBGDrivWriteCM(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void ExtDBGDrivSetMarker(struct DBG_STREAM *psStream,
+ u32 ui32Marker)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetMarker(psStream, ui32Marker);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+u32 ExtDBGDrivGetMarker(struct DBG_STREAM *psStream)
+{
+ u32 ui32Marker;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Marker = DBGDrivGetMarker(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Marker;
+}
+
+u32 ExtDBGDrivWriteLF(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level,
+ u32 ui32Flags)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret =
+ DBGDrivWriteLF(psStream, pui8InBuf, ui32InBuffSize, ui32Level,
+ ui32Flags);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+u32 ExtDBGDrivReadLF(struct DBG_STREAM *psStream,
+ u32 ui32OutBuffSize,
+ u8 *pui8OutBuf)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivReadLF(psStream, ui32OutBuffSize, pui8OutBuf);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void ExtDBGDrivStartInitPhase(struct DBG_STREAM *psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStartInitPhase(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+void ExtDBGDrivStopInitPhase(struct DBG_STREAM *psStream)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivStopInitPhase(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return;
+}
+
+u32 ExtDBGDrivGetStreamOffset(struct DBG_STREAM *psStream)
+{
+ u32 ui32Ret;
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ ui32Ret = DBGDrivGetStreamOffset(psStream);
+
+ HostReleaseMutex(g_pvAPIMutex);
+
+ return ui32Ret;
+}
+
+void ExtDBGDrivSetStreamOffset(struct DBG_STREAM *psStream,
+ u32 ui32StreamOffset)
+{
+
+ HostAquireMutex(g_pvAPIMutex);
+
+ DBGDrivSetStreamOffset(psStream, ui32StreamOffset);
+
+ HostReleaseMutex(g_pvAPIMutex);
+}
+
+void ExtDBGDrivWaitForEvent(enum DBG_EVENT eEvent)
+{
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ DBGDrivWaitForEvent(eEvent);
+#else
+ PVR_UNREFERENCED_PARAMETER(eEvent);
+#endif
+}
+
+u32 AtoI(char *szIn)
+{
+ u32 ui32Len = 0;
+ u32 ui32Value = 0;
+ u32 ui32Digit = 1;
+ u32 ui32Base = 10;
+ int iPos;
+ char bc;
+
+ while (szIn[ui32Len] > 0)
+ ui32Len++;
+
+ if (ui32Len == 0)
+ return 0;
+
+ iPos = 0;
+ while (szIn[iPos] == '0')
+ iPos++;
+ if (szIn[iPos] == '\0')
+ return 0;
+ if (szIn[iPos] == 'x' || szIn[iPos] == 'X') {
+ ui32Base = 16;
+ szIn[iPos] = '0';
+ }
+
+ for (iPos = ui32Len - 1; iPos >= 0; iPos--) {
+ bc = szIn[iPos];
+
+ if ((bc >= 'a') && (bc <= 'f') && ui32Base == 16)
+ bc -= 'a' - 0xa;
+ else if ((bc >= 'A') && (bc <= 'F') && ui32Base == 16)
+ bc -= 'A' - 0xa;
+ else if ((bc >= '0') && (bc <= '9'))
+ bc -= '0';
+ else
+ return 0;
+
+ ui32Value += bc * ui32Digit;
+
+ ui32Digit = ui32Digit * ui32Base;
+ }
+ return ui32Value;
+}
+
+IMG_BOOL StreamValid(struct DBG_STREAM *psStream)
+{
+ struct DBG_STREAM *psThis;
+
+ psThis = g_psStreamList;
+
+ while (psThis)
+ if (psStream && (psThis == psStream))
+ return IMG_TRUE;
+ else
+ psThis = psThis->psNext;
+
+ return IMG_FALSE;
+}
+
+void Write(struct DBG_STREAM *psStream, u8 *pui8Data,
+ u32 ui32InBuffSize)
+{
+
+ if ((psStream->ui32WPtr + ui32InBuffSize) > psStream->ui32Size) {
+ u32 ui32B1 = psStream->ui32Size - psStream->ui32WPtr;
+ u32 ui32B2 = ui32InBuffSize - ui32B1;
+
+ HostMemCopy((void *) (psStream->ui32Base +
+ psStream->ui32WPtr),
+ (void *) pui8Data, ui32B1);
+
+ HostMemCopy((void *) psStream->ui32Base,
+ (void *) ((u32) pui8Data + ui32B1),
+ ui32B2);
+
+ psStream->ui32WPtr = ui32B2;
+ } else {
+ HostMemCopy((void *) (psStream->ui32Base +
+ psStream->ui32WPtr),
+ (void *) pui8Data, ui32InBuffSize);
+
+ psStream->ui32WPtr += ui32InBuffSize;
+
+ if (psStream->ui32WPtr == psStream->ui32Size)
+ psStream->ui32WPtr = 0;
+ }
+ psStream->ui32DataWritten += ui32InBuffSize;
+}
+
+void MonoOut(char *pszString, IMG_BOOL bNewLine)
+{
+ u32 i;
+ char *pScreen;
+
+ pScreen = (char *)DBGDRIV_MONOBASE;
+
+ pScreen += g_ui32Line * 160;
+
+ i = 0;
+ do {
+ pScreen[g_ui32LOff + (i * 2)] = pszString[i];
+ pScreen[g_ui32LOff + (i * 2) + 1] = 127;
+ i++;
+ } while ((pszString[i] != 0) && (i < 4096));
+
+ g_ui32LOff += i * 2;
+
+ if (bNewLine) {
+ g_ui32LOff = 0;
+ g_ui32Line++;
+ }
+
+ if (g_ui32Line == g_ui32MonoLines) {
+ g_ui32Line = g_ui32MonoLines - 1;
+
+ HostMemCopy((void *) DBGDRIV_MONOBASE,
+ (void *) (DBGDRIV_MONOBASE + 160),
+ 160 * (g_ui32MonoLines - 1));
+
+ HostMemSet((void *) (DBGDRIV_MONOBASE +
+ (160 * (g_ui32MonoLines - 1))), 0,
+ 160);
+ }
+}
+
+void AppendName(char *pszOut, char *pszBase, char *pszName)
+{
+ u32 i;
+ u32 ui32Off;
+
+ i = 0;
+
+ while (pszBase[i] != 0) {
+ pszOut[i] = pszBase[i];
+ i++;
+ }
+
+ ui32Off = i;
+ i = 0;
+
+ while (pszName[i] != 0) {
+ pszOut[ui32Off + i] = pszName[i];
+ i++;
+ }
+
+ pszOut[ui32Off + i] = pszName[i];
+}
+
+void *DBGDrivCreateStream(char *pszName,
+ u32 ui32CapMode,
+ u32 ui32OutMode,
+ u32 ui32Flags,
+ u32 ui32Size)
+{
+ struct DBG_STREAM *psStream;
+ struct DBG_STREAM *psInitStream;
+ struct DBG_LASTFRAME_BUFFER *psLFBuffer;
+ u32 ui32Off;
+ void *pvBase;
+
+ psStream = (struct DBG_STREAM *)DBGDrivFindStream(pszName, IMG_FALSE);
+
+ if (psStream)
+ return (void *)psStream;
+
+ psStream = HostNonPageablePageAlloc(1);
+ psInitStream = HostNonPageablePageAlloc(1);
+ psLFBuffer = HostNonPageablePageAlloc(1);
+ if ((!psStream) || (!psInitStream) || (!psLFBuffer)
+ ) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DBGDriv: Couldn't create buffer !!!!!\n\r");
+ return NULL;
+ }
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ else
+ pvBase = HostPageablePageAlloc(ui32Size);
+
+ if (!pvBase) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DBGDriv: Couldn't create buffer !!!!!\n\r");
+ HostNonPageablePageFree(psStream);
+ return NULL;
+ }
+
+ psStream->psNext = 0;
+ psStream->ui32Flags = ui32Flags;
+ psStream->ui32Base = (u32) pvBase;
+ psStream->ui32Size = ui32Size * 4096;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten = 0;
+ psStream->ui32CapMode = ui32CapMode;
+ psStream->ui32OutMode = ui32OutMode;
+ psStream->ui32DebugLevel = DEBUG_LEVEL_0;
+ psStream->ui32DefaultMode = ui32CapMode;
+ psStream->ui32Start = 0;
+ psStream->ui32End = 0;
+ psStream->ui32Current = 0;
+ psStream->ui32SampleRate = 1;
+ psStream->ui32Access = 0;
+ psStream->ui32Timeout = 0;
+ psStream->ui32Marker = 0;
+ psStream->bInitPhaseComplete = IMG_FALSE;
+
+ if ((ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ pvBase = HostNonPageablePageAlloc(ui32Size);
+ else
+ pvBase = HostPageablePageAlloc(ui32Size);
+
+ if (!pvBase) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "DBGDriv: Couldn't create buffer !!!!!\n\r");
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ HostNonPageablePageFree((void *) psStream->
+ ui32Base);
+ else
+ HostPageablePageFree((void *) psStream->ui32Base);
+ HostNonPageablePageFree(psStream);
+ return NULL;
+ }
+
+ psInitStream->psNext = 0;
+ psInitStream->ui32Flags = ui32Flags;
+ psInitStream->ui32Base = (u32) pvBase;
+ psInitStream->ui32Size = ui32Size * 4096;
+ psInitStream->ui32RPtr = 0;
+ psInitStream->ui32WPtr = 0;
+ psInitStream->ui32DataWritten = 0;
+ psInitStream->ui32CapMode = ui32CapMode;
+ psInitStream->ui32OutMode = ui32OutMode;
+ psInitStream->ui32DebugLevel = DEBUG_LEVEL_0;
+ psInitStream->ui32DefaultMode = ui32CapMode;
+ psInitStream->ui32Start = 0;
+ psInitStream->ui32End = 0;
+ psInitStream->ui32Current = 0;
+ psInitStream->ui32SampleRate = 1;
+ psInitStream->ui32Access = 0;
+ psInitStream->ui32Timeout = 0;
+ psInitStream->ui32Marker = 0;
+ psInitStream->bInitPhaseComplete = IMG_FALSE;
+
+ psStream->psInitStream = psInitStream;
+
+ psLFBuffer->psStream = psStream;
+ psLFBuffer->ui32BufLen = 0;
+
+ g_bHotkeyMiddump = IMG_FALSE;
+ g_ui32HotkeyMiddumpStart = 0xffffffff;
+ g_ui32HotkeyMiddumpEnd = 0xffffffff;
+
+ ui32Off = 0;
+
+ do {
+ psStream->szName[ui32Off] = pszName[ui32Off];
+
+ ui32Off++;
+ } while ((pszName[ui32Off] != 0)
+ && (ui32Off < (4096 - sizeof(struct DBG_STREAM))));
+
+ psStream->szName[ui32Off] = pszName[ui32Off];
+
+ psStream->psNext = g_psStreamList;
+ g_psStreamList = psStream;
+
+ psLFBuffer->psNext = g_psLFBufferList;
+ g_psLFBufferList = psLFBuffer;
+
+ return (void *)psStream;
+}
+
+void DBGDrivDestroyStream(struct DBG_STREAM *psStream)
+{
+ struct DBG_STREAM *psStreamThis;
+ struct DBG_STREAM *psStreamPrev;
+ struct DBG_LASTFRAME_BUFFER *psLFBuffer;
+ struct DBG_LASTFRAME_BUFFER *psLFThis;
+ struct DBG_LASTFRAME_BUFFER *psLFPrev;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "DBGDriv: Destroying stream %s\r\n",
+ psStream->szName);
+
+ if (!StreamValid(psStream))
+ return;
+
+ psLFBuffer = FindLFBuf(psStream);
+
+ psStreamThis = g_psStreamList;
+ psStreamPrev = 0;
+
+ while (psStreamThis)
+ if (psStreamThis == psStream) {
+ if (psStreamPrev)
+ psStreamPrev->psNext = psStreamThis->psNext;
+ else
+ g_psStreamList = psStreamThis->psNext;
+
+ psStreamThis = 0;
+ } else {
+ psStreamPrev = psStreamThis;
+ psStreamThis = psStreamThis->psNext;
+ }
+
+ psLFThis = g_psLFBufferList;
+ psLFPrev = 0;
+
+ while (psLFThis)
+ if (psLFThis == psLFBuffer) {
+ if (psLFPrev)
+ psLFPrev->psNext = psLFThis->psNext;
+ else
+ g_psLFBufferList = psLFThis->psNext;
+
+ psLFThis = 0;
+ } else {
+ psLFPrev = psLFThis;
+ psLFThis = psLFThis->psNext;
+ }
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ DeactivateHotKeys();
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0) {
+ HostNonPageablePageFree((void *) psStream->ui32Base);
+ HostNonPageablePageFree((void *) psStream->psInitStream->
+ ui32Base);
+ } else {
+ HostPageablePageFree((void *) psStream->ui32Base);
+ HostPageablePageFree((void *) psStream->psInitStream->
+ ui32Base);
+ }
+
+ HostNonPageablePageFree(psStream->psInitStream);
+ HostNonPageablePageFree(psStream);
+ HostNonPageablePageFree(psLFBuffer);
+
+ if (g_psStreamList == 0)
+ PVR_DPF(PVR_DBG_MESSAGE, "DBGDriv: Stream list now empty");
+
+ return;
+}
+
+void *DBGDrivFindStream(char *pszName,
+ IMG_BOOL bResetStream)
+{
+ struct DBG_STREAM *psStream;
+ struct DBG_STREAM *psThis;
+ u32 ui32Off;
+ IMG_BOOL bAreSame;
+
+ psStream = 0;
+
+ for (psThis = g_psStreamList; psThis != NULL;
+ psThis = psThis->psNext) {
+ bAreSame = IMG_TRUE;
+ ui32Off = 0;
+
+ if (strlen(psThis->szName) == strlen(pszName)) {
+ while ((psThis->szName[ui32Off] != 0)
+ && (pszName[ui32Off] != 0) && (ui32Off < 128)
+ && bAreSame) {
+ if (psThis->szName[ui32Off] != pszName[ui32Off])
+ bAreSame = IMG_FALSE;
+
+ ui32Off++;
+ }
+ } else {
+ bAreSame = IMG_FALSE;
+ }
+
+ if (bAreSame) {
+ psStream = psThis;
+ break;
+ }
+ }
+
+ if (bResetStream && psStream) {
+ static char szComment[] = "-- Init phase terminated\r\n";
+ psStream->psInitStream->ui32RPtr = 0;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = 0;
+ psStream->ui32DataWritten =
+ psStream->psInitStream->ui32DataWritten;
+ if (psStream->bInitPhaseComplete == IMG_FALSE) {
+ if (psStream->ui32Flags & DEBUG_FLAGS_TEXTSTREAM)
+ DBGDrivWrite2(psStream, (u8 *) szComment,
+ sizeof(szComment) - 1, 0x01);
+ psStream->bInitPhaseComplete = IMG_TRUE;
+ }
+ }
+
+ return (void *)psStream;
+}
+
+u32 DBGDrivWriteStringCM(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Level)
+{
+
+ if (!StreamValid(psStream))
+ return 0xFFFFFFFF;
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+ if (!(psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE))
+ return 0;
+ } else {
+ if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ if ((psStream->ui32Current != g_ui32HotKeyFrame)
+ || (g_bHotKeyPressed == IMG_FALSE))
+ return 0;
+ }
+
+ return DBGDrivWriteString(psStream, pszString, ui32Level);
+
+}
+
+u32 DBGDrivWriteString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Level)
+{
+ u32 ui32Len;
+ u32 ui32Space;
+ u32 ui32WPtr;
+ u8 *pui8Buffer;
+
+ if (!StreamValid(psStream))
+ return 0xFFFFFFFF;
+
+ if (!(psStream->ui32DebugLevel & ui32Level))
+ return 0xFFFFFFFF;
+
+ if (!(psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC)) {
+ if (psStream->ui32OutMode & DEBUG_OUTMODE_STANDARDDBG)
+ PVR_DPF(PVR_DBG_MESSAGE, "%s: %s\r\n",
+ psStream->szName, pszString);
+
+ if (psStream->ui32OutMode & DEBUG_OUTMODE_MONO) {
+ MonoOut(psStream->szName, IMG_FALSE);
+ MonoOut(": ", IMG_FALSE);
+ MonoOut(pszString, IMG_TRUE);
+ }
+ }
+
+ if (!((psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE) ||
+ (psStream->ui32OutMode & DEBUG_OUTMODE_ASYNC)
+ )
+ )
+ return 0xFFFFFFFF;
+
+ ui32Space = SpaceInStream(psStream);
+
+ if (ui32Space > 0)
+ ui32Space--;
+
+ ui32Len = 0;
+ ui32WPtr = psStream->ui32WPtr;
+ pui8Buffer = (u8 *) psStream->ui32Base;
+
+ while ((pszString[ui32Len] != 0) && (ui32Len < ui32Space)) {
+ pui8Buffer[ui32WPtr] = pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ ui32WPtr = 0;
+ }
+
+ if (ui32Len < ui32Space) {
+
+ pui8Buffer[ui32WPtr] = pszString[ui32Len];
+ ui32Len++;
+ ui32WPtr++;
+ if (ui32WPtr == psStream->ui32Size)
+ ui32WPtr = 0;
+
+ psStream->ui32WPtr = ui32WPtr;
+ psStream->ui32DataWritten += ui32Len;
+ } else {
+ ui32Len = 0;
+ }
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32Len)
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+#endif
+
+ return ui32Len;
+}
+
+u32 DBGDrivReadString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Limit)
+{
+ u32 ui32OutLen;
+ u32 ui32Len;
+ u32 ui32Offset;
+ u8 *pui8Buff;
+
+ if (!StreamValid(psStream))
+ return 0;
+
+ pui8Buff = (u8 *) psStream->ui32Base;
+ ui32Offset = psStream->ui32RPtr;
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr)
+ return 0;
+
+ ui32Len = 0;
+ while ((pui8Buff[ui32Offset] != 0)
+ && (ui32Offset != psStream->ui32WPtr)) {
+ ui32Offset++;
+ ui32Len++;
+
+ if (ui32Offset == psStream->ui32Size)
+ ui32Offset = 0;
+ }
+
+ ui32OutLen = ui32Len + 1;
+
+ if (ui32Len > ui32Limit)
+ return 0;
+
+ ui32Offset = psStream->ui32RPtr;
+ ui32Len = 0;
+
+ while ((pui8Buff[ui32Offset] != 0) && (ui32Len < ui32Limit)) {
+ pszString[ui32Len] = pui8Buff[ui32Offset];
+ ui32Offset++;
+ ui32Len++;
+
+ if (ui32Offset == psStream->ui32Size)
+ ui32Offset = 0;
+ }
+
+ pszString[ui32Len] = pui8Buff[ui32Offset];
+
+ psStream->ui32RPtr = ui32Offset + 1;
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ psStream->ui32RPtr = 0;
+
+ return ui32OutLen;
+}
+
+u32 DBGDrivWrite(struct DBG_STREAM *psMainStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level)
+{
+ u32 ui32Space;
+ struct DBG_STREAM *psStream;
+
+ if (!StreamValid(psMainStream))
+ return 0xFFFFFFFF;
+
+ if (!(psMainStream->ui32DebugLevel & ui32Level))
+ return 0xFFFFFFFF;
+
+ if (psMainStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+ if (!(psMainStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE))
+ return 0xFFFFFFFF;
+ } else {
+ if (psMainStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ if ((psMainStream->ui32Current != g_ui32HotKeyFrame)
+ || (g_bHotKeyPressed == IMG_FALSE))
+ return 0xFFFFFFFF;
+
+ }
+
+ if (psMainStream->bInitPhaseComplete)
+ psStream = psMainStream;
+ else
+ psStream = psMainStream->psInitStream;
+
+ ui32Space = SpaceInStream(psStream);
+
+ if (!(psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE))
+ return 0;
+
+ if (ui32Space < 8)
+ return 0;
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ ui32InBuffSize = ui32Space - 8;
+
+ Write(psStream, (u8 *) &ui32InBuffSize, 4);
+ Write(psStream, pui8InBuf, ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+#endif
+ return ui32InBuffSize;
+}
+
+u32 DBGDrivWriteCM(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level)
+{
+
+ if (!StreamValid(psStream))
+ return 0xFFFFFFFF;
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+ if (!(psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE))
+ return 0xFFFFFFFF;
+ } else {
+ if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY)
+ if ((psStream->ui32Current != g_ui32HotKeyFrame)
+ || (g_bHotKeyPressed == IMG_FALSE))
+ return 0xFFFFFFFF;
+ }
+
+ return DBGDrivWrite2(psStream, pui8InBuf, ui32InBuffSize, ui32Level);
+}
+
+u32 DBGDrivWrite2(struct DBG_STREAM *psMainStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level)
+{
+ u32 ui32Space;
+ struct DBG_STREAM *psStream;
+
+ if (!StreamValid(psMainStream))
+ return 0xFFFFFFFF;
+
+ if (!(psMainStream->ui32DebugLevel & ui32Level))
+ return 0xFFFFFFFF;
+
+ if (psMainStream->bInitPhaseComplete)
+ psStream = psMainStream;
+ else
+ psStream = psMainStream->psInitStream;
+
+ ui32Space = SpaceInStream(psStream);
+
+ if (!(psStream->ui32OutMode & DEBUG_OUTMODE_STREAMENABLE))
+ return 0;
+
+ if (psStream->ui32Flags & DEBUG_FLAGS_NO_BUF_EXPANDSION) {
+
+ if (ui32Space < 32)
+ return 0;
+ } else {
+ if ((ui32Space < 32) || (ui32Space <= (ui32InBuffSize + 4))) {
+ u32 ui32NewBufSize;
+
+ ui32NewBufSize = 2 * psStream->ui32Size;
+
+ if (ui32InBuffSize > psStream->ui32Size)
+ ui32NewBufSize += ui32InBuffSize;
+
+ if (!ExpandStreamBuffer(psStream, ui32NewBufSize))
+ if (ui32Space < 32)
+ return 0;
+
+ ui32Space = SpaceInStream(psStream);
+ }
+ }
+
+ if (ui32Space <= (ui32InBuffSize + 4))
+ ui32InBuffSize = ui32Space - 4;
+
+ Write(psStream, pui8InBuf, ui32InBuffSize);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ if (ui32InBuffSize)
+ HostSignalEvent(DBG_EVENT_STREAM_DATA);
+#endif
+ return ui32InBuffSize;
+}
+
+u32 DBGDrivRead(struct DBG_STREAM *psMainStream,
+ IMG_BOOL bReadInitBuffer,
+ u32 ui32OutBuffSize,
+ u8 *pui8OutBuf)
+{
+ u32 ui32Data;
+ struct DBG_STREAM *psStream;
+
+ if (!StreamValid(psMainStream))
+ return 0;
+
+ if (bReadInitBuffer)
+ psStream = psMainStream->psInitStream;
+ else
+ psStream = psMainStream;
+
+ if (psStream->ui32RPtr == psStream->ui32WPtr)
+ return 0;
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr) {
+ ui32Data = psStream->ui32WPtr - psStream->ui32RPtr;
+ } else {
+ ui32Data =
+ psStream->ui32WPtr + (psStream->ui32Size -
+ psStream->ui32RPtr);
+ }
+
+ if (ui32Data > ui32OutBuffSize)
+ ui32Data = ui32OutBuffSize;
+
+ if ((psStream->ui32RPtr + ui32Data) > psStream->ui32Size) {
+ u32 ui32B1 = psStream->ui32Size - psStream->ui32RPtr;
+ u32 ui32B2 = ui32Data - ui32B1;
+
+ HostMemCopy((void *) pui8OutBuf,
+ (void *) (psStream->ui32Base +
+ psStream->ui32RPtr), ui32B1);
+
+ HostMemCopy((void *) ((u32) pui8OutBuf + ui32B1),
+ (void *) psStream->ui32Base, ui32B2);
+
+ psStream->ui32RPtr = ui32B2;
+ } else {
+ HostMemCopy((void *) pui8OutBuf,
+ (void *) (psStream->ui32Base +
+ psStream->ui32RPtr), ui32Data);
+
+ psStream->ui32RPtr += ui32Data;
+
+ if (psStream->ui32RPtr == psStream->ui32Size)
+ psStream->ui32RPtr = 0;
+ }
+
+ return ui32Data;
+}
+
+void DBGDrivSetCaptureMode(struct DBG_STREAM *psStream,
+ u32 ui32Mode,
+ u32 ui32Start,
+ u32 ui32End,
+ u32 ui32SampleRate)
+{
+
+ if (!StreamValid(psStream))
+ return;
+
+ psStream->ui32CapMode = ui32Mode;
+ psStream->ui32DefaultMode = ui32Mode;
+ psStream->ui32Start = ui32Start;
+ psStream->ui32End = ui32End;
+ psStream->ui32SampleRate = ui32SampleRate;
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)
+ ActivateHotKeys(psStream);
+}
+
+void DBGDrivSetOutputMode(struct DBG_STREAM *psStream,
+ u32 ui32OutMode)
+{
+
+ if (!StreamValid(psStream))
+ return;
+
+ psStream->ui32OutMode = ui32OutMode;
+}
+
+void DBGDrivSetDebugLevel(struct DBG_STREAM *psStream,
+ u32 ui32DebugLevel)
+{
+
+ if (!StreamValid(psStream))
+ return;
+
+ psStream->ui32DebugLevel = ui32DebugLevel;
+}
+
+void DBGDrivSetFrame(struct DBG_STREAM *psStream, u32 ui32Frame)
+{
+
+ if (!StreamValid(psStream))
+ return;
+
+ psStream->ui32Current = ui32Frame;
+
+ if ((ui32Frame >= psStream->ui32Start) &&
+ (ui32Frame <= psStream->ui32End) &&
+ (((ui32Frame - psStream->ui32Start) % psStream->ui32SampleRate) ==
+ 0))
+ psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ else
+ psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+
+ if (g_bHotkeyMiddump) {
+ if ((ui32Frame >= g_ui32HotkeyMiddumpStart) &&
+ (ui32Frame <= g_ui32HotkeyMiddumpEnd) &&
+ (((ui32Frame -
+ g_ui32HotkeyMiddumpStart) % psStream->ui32SampleRate) ==
+ 0)) {
+ psStream->ui32Flags |= DEBUG_FLAGS_ENABLESAMPLE;
+ } else {
+ psStream->ui32Flags &= ~DEBUG_FLAGS_ENABLESAMPLE;
+ if (psStream->ui32Current > g_ui32HotkeyMiddumpEnd)
+ g_bHotkeyMiddump = IMG_FALSE;
+ }
+ }
+
+ if (g_bHotKeyRegistered) {
+ g_bHotKeyRegistered = IMG_FALSE;
+
+ PVR_DPF(PVR_DBG_MESSAGE, "Hotkey pressed (%08x)!\n",
+ psStream);
+
+ if (!g_bHotKeyPressed) {
+
+ g_ui32HotKeyFrame = psStream->ui32Current + 2;
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+
+ if ((psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED)
+ && (psStream->ui32CapMode & DEBUG_CAPMODE_HOTKEY)) {
+ if (!g_bHotkeyMiddump) {
+
+ g_ui32HotkeyMiddumpStart =
+ g_ui32HotKeyFrame + 1;
+ g_ui32HotkeyMiddumpEnd = 0xffffffff;
+ g_bHotkeyMiddump = IMG_TRUE;
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "Sampling every %d frame(s)\n",
+ psStream->ui32SampleRate);
+ } else {
+
+ g_ui32HotkeyMiddumpEnd = g_ui32HotKeyFrame;
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "Turning off sampling\n");
+ }
+ }
+
+ }
+
+ if (psStream->ui32Current > g_ui32HotKeyFrame)
+ g_bHotKeyPressed = IMG_FALSE;
+}
+
+u32 DBGDrivGetFrame(struct DBG_STREAM *psStream)
+{
+
+ if (!StreamValid(psStream))
+ return 0;
+
+ return psStream->ui32Current;
+}
+
+u32 DBGDrivIsLastCaptureFrame(struct DBG_STREAM *psStream)
+{
+ u32 ui32NextFrame;
+
+ if (!StreamValid(psStream))
+ return IMG_FALSE;
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+ ui32NextFrame =
+ psStream->ui32Current + psStream->ui32SampleRate;
+ if (ui32NextFrame > psStream->ui32End)
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+u32 DBGDrivIsCaptureFrame(struct DBG_STREAM *psStream,
+ IMG_BOOL bCheckPreviousFrame)
+{
+ u32 ui32FrameShift = bCheckPreviousFrame ? 1 : 0;
+
+ if (!StreamValid(psStream))
+ return IMG_FALSE;
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+
+ if (g_bHotkeyMiddump) {
+ if ((psStream->ui32Current >=
+ (g_ui32HotkeyMiddumpStart - ui32FrameShift))
+ && (psStream->ui32Current <=
+ (g_ui32HotkeyMiddumpEnd - ui32FrameShift))
+ &&
+ ((((psStream->ui32Current + ui32FrameShift) -
+ g_ui32HotkeyMiddumpStart) %
+ psStream->ui32SampleRate) == 0))
+ return IMG_TRUE;
+ } else {
+ if ((psStream->ui32Current >=
+ (psStream->ui32Start - ui32FrameShift))
+ && (psStream->ui32Current <=
+ (psStream->ui32End - ui32FrameShift))
+ &&
+ ((((psStream->ui32Current + ui32FrameShift) -
+ psStream->ui32Start) %
+ psStream->ui32SampleRate) == 0))
+ return IMG_TRUE;
+ }
+ } else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY) {
+ if ((psStream->ui32Current ==
+ (g_ui32HotKeyFrame - ui32FrameShift))
+ && (g_bHotKeyPressed))
+ return IMG_TRUE;
+ }
+
+
+ return IMG_FALSE;
+}
+
+void DBGDrivOverrideMode(struct DBG_STREAM *psStream, u32 ui32Mode)
+{
+
+ if (!StreamValid(psStream))
+ return;
+
+ psStream->ui32CapMode = ui32Mode;
+}
+
+void DBGDrivDefaultMode(struct DBG_STREAM *psStream)
+{
+
+ if (!StreamValid(psStream))
+ return;
+
+ psStream->ui32CapMode = psStream->ui32DefaultMode;
+}
+
+void DBGDrivSetMarker(struct DBG_STREAM *psStream, u32 ui32Marker)
+{
+
+ if (!StreamValid(psStream))
+ return;
+
+ psStream->ui32Marker = ui32Marker;
+}
+
+u32 DBGDrivGetMarker(struct DBG_STREAM *psStream)
+{
+
+ if (!StreamValid(psStream))
+ return 0;
+
+ return psStream->ui32Marker;
+}
+
+u32 DBGDrivGetStreamOffset(struct DBG_STREAM *psMainStream)
+{
+ struct DBG_STREAM *psStream;
+
+ if (!StreamValid(psMainStream))
+ return 0;
+
+ if (psMainStream->bInitPhaseComplete)
+ psStream = psMainStream;
+ else
+ psStream = psMainStream->psInitStream;
+
+ return psStream->ui32DataWritten;
+}
+
+void DBGDrivSetStreamOffset(struct DBG_STREAM *psMainStream,
+ u32 ui32StreamOffset)
+{
+ struct DBG_STREAM *psStream;
+
+ if (!StreamValid(psMainStream))
+ return;
+
+ if (psMainStream->bInitPhaseComplete)
+ psStream = psMainStream;
+ else
+ psStream = psMainStream->psInitStream;
+
+ psStream->ui32DataWritten = ui32StreamOffset;
+}
+
+u32 DBGDrivGetServiceTable(void)
+{
+ return (u32)&g_sDBGKMServices;
+}
+
+u32 DBGDrivWriteLF(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level,
+ u32 ui32Flags)
+{
+ struct DBG_LASTFRAME_BUFFER *psLFBuffer;
+
+ if (!StreamValid(psStream))
+ return 0xFFFFFFFF;
+
+ if (!(psStream->ui32DebugLevel & ui32Level))
+ return 0xFFFFFFFF;
+
+ if (psStream->ui32CapMode & DEBUG_CAPMODE_FRAMED) {
+ if (!(psStream->ui32Flags & DEBUG_FLAGS_ENABLESAMPLE))
+ return 0xFFFFFFFF;
+ } else if (psStream->ui32CapMode == DEBUG_CAPMODE_HOTKEY) {
+ if ((psStream->ui32Current != g_ui32HotKeyFrame)
+ || (g_bHotKeyPressed == IMG_FALSE))
+ return 0xFFFFFFFF;
+ }
+
+ psLFBuffer = FindLFBuf(psStream);
+
+ if (ui32Flags & WRITELF_FLAGS_RESETBUF) {
+
+ ui32InBuffSize =
+ (ui32InBuffSize >
+ LAST_FRAME_BUF_SIZE) ? LAST_FRAME_BUF_SIZE :
+ ui32InBuffSize;
+ HostMemCopy((void *) psLFBuffer->ui8Buffer,
+ (void *) pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen = ui32InBuffSize;
+ } else {
+
+ ui32InBuffSize =
+ ((psLFBuffer->ui32BufLen + ui32InBuffSize) >
+ LAST_FRAME_BUF_SIZE) ? (LAST_FRAME_BUF_SIZE -
+ psLFBuffer->
+ ui32BufLen) : ui32InBuffSize;
+ HostMemCopy((void *) (&psLFBuffer->
+ ui8Buffer[psLFBuffer->ui32BufLen]),
+ (void *) pui8InBuf, ui32InBuffSize);
+ psLFBuffer->ui32BufLen += ui32InBuffSize;
+ }
+
+ return ui32InBuffSize;
+}
+
+u32 DBGDrivReadLF(struct DBG_STREAM *psStream,
+ u32 ui32OutBuffSize,
+ u8 *pui8OutBuf)
+{
+ struct DBG_LASTFRAME_BUFFER *psLFBuffer;
+ u32 ui32Data;
+
+ if (!StreamValid(psStream))
+ return 0;
+
+ psLFBuffer = FindLFBuf(psStream);
+
+ ui32Data =
+ (ui32OutBuffSize <
+ psLFBuffer->ui32BufLen) ? ui32OutBuffSize : psLFBuffer->ui32BufLen;
+
+ HostMemCopy((void *) pui8OutBuf, (void *) psLFBuffer->ui8Buffer,
+ ui32Data);
+
+ return ui32Data;
+}
+
+void DBGDrivStartInitPhase(struct DBG_STREAM *psStream)
+{
+ psStream->bInitPhaseComplete = IMG_FALSE;
+}
+
+void DBGDrivStopInitPhase(struct DBG_STREAM *psStream)
+{
+ psStream->bInitPhaseComplete = IMG_TRUE;
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+void DBGDrivWaitForEvent(enum DBG_EVENT eEvent)
+{
+ HostWaitForEvent(eEvent);
+}
+#endif
+
+static IMG_BOOL ExpandStreamBuffer(struct DBG_STREAM *psStream, u32 ui32NewSize)
+{
+ void *pvNewBuf;
+ u32 ui32NewSizeInPages;
+ u32 ui32NewWOffset;
+ u32 ui32SpaceInOldBuf;
+
+ if (psStream->ui32Size >= ui32NewSize)
+ return IMG_FALSE;
+
+ ui32SpaceInOldBuf = SpaceInStream(psStream);
+
+ ui32NewSizeInPages = ((ui32NewSize + 0xfff) & ~0xfff) / 4096;
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ pvNewBuf = HostNonPageablePageAlloc(ui32NewSizeInPages);
+ else
+ pvNewBuf = HostPageablePageAlloc(ui32NewSizeInPages);
+
+ if (pvNewBuf == NULL)
+ return IMG_FALSE;
+
+ if (psStream->ui32RPtr <= psStream->ui32WPtr) {
+
+ HostMemCopy((void *) pvNewBuf,
+ (void *) (psStream->ui32Base +
+ psStream->ui32RPtr),
+ psStream->ui32WPtr - psStream->ui32RPtr);
+ } else {
+ u32 ui32FirstCopySize;
+
+ ui32FirstCopySize = psStream->ui32Size - psStream->ui32RPtr;
+
+ HostMemCopy((void *) pvNewBuf,
+ (void *) (psStream->ui32Base +
+ psStream->ui32RPtr),
+ ui32FirstCopySize);
+
+ HostMemCopy((void *) ((u32) pvNewBuf +
+ ui32FirstCopySize),
+ (void *) psStream->ui32Base,
+ psStream->ui32WPtr);
+ }
+
+ ui32NewWOffset = psStream->ui32Size - ui32SpaceInOldBuf;
+
+ if ((psStream->ui32Flags & DEBUG_FLAGS_USE_NONPAGED_MEM) != 0)
+ HostNonPageablePageFree((void *) psStream->ui32Base);
+ else
+ HostPageablePageFree((void *) psStream->ui32Base);
+
+ psStream->ui32Base = (u32) pvNewBuf;
+ psStream->ui32RPtr = 0;
+ psStream->ui32WPtr = ui32NewWOffset;
+ psStream->ui32Size = ui32NewSizeInPages * 4096;
+
+ return IMG_TRUE;
+}
+
+static u32 SpaceInStream(struct DBG_STREAM *psStream)
+{
+ u32 ui32Space;
+
+ if (psStream->ui32RPtr > psStream->ui32WPtr)
+ ui32Space = psStream->ui32RPtr - psStream->ui32WPtr;
+ else
+ ui32Space =
+ psStream->ui32RPtr + (psStream->ui32Size -
+ psStream->ui32WPtr);
+
+ return ui32Space;
+}
+
+void DestroyAllStreams(void)
+{
+ while (g_psStreamList != NULL)
+ DBGDrivDestroyStream(g_psStreamList);
+ return;
+}
+
+struct DBG_LASTFRAME_BUFFER *FindLFBuf(struct DBG_STREAM *psStream)
+{
+ struct DBG_LASTFRAME_BUFFER *psLFBuffer;
+
+ psLFBuffer = g_psLFBufferList;
+
+ while (psLFBuffer) {
+ if (psLFBuffer->psStream == psStream)
+ break;
+
+ psLFBuffer = psLFBuffer->psNext;
+ }
+
+ return psLFBuffer;
+}
diff --git a/drivers/gpu/pvr/tools/dbgdriv.h b/drivers/gpu/pvr/tools/dbgdriv.h
new file mode 100644
index 00000000000..4e2ebc30ded
--- /dev/null
+++ b/drivers/gpu/pvr/tools/dbgdriv.h
@@ -0,0 +1,183 @@
+/**********************************************************************
+ *
+ * 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 _DBGDRIV_
+#define _DBGDRIV_
+
+#define BUFFER_SIZE (64 * PAGESIZE)
+
+#define DBGDRIV_VERSION 0x100
+#define MAX_PROCESSES 2
+#define BLOCK_USED 0x01
+#define BLOCK_LOCKED 0x02
+#define DBGDRIV_MONOBASE 0x000B0000
+
+extern void *g_pvAPIMutex;
+
+void *DBGDrivCreateStream(char *pszName,
+ u32 ui32CapMode,
+ u32 ui32OutMode,
+ u32 ui32Flags,
+ u32 ui32Pages);
+void DBGDrivDestroyStream(struct DBG_STREAM *psStream);
+void *DBGDrivFindStream(char *pszName,
+ IMG_BOOL bResetStream);
+u32 DBGDrivWriteString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Level);
+u32 DBGDrivReadString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Limit);
+u32 DBGDrivWrite(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level);
+u32 DBGDrivWrite2(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level);
+u32 DBGDrivRead(struct DBG_STREAM *psStream,
+ IMG_BOOL bReadInitBuffer,
+ u32 ui32OutBufferSize,
+ u8 *pui8OutBuf);
+void DBGDrivSetCaptureMode(struct DBG_STREAM *psStream,
+ u32 ui32Mode,
+ u32 ui32Start,
+ u32 ui32Stop,
+ u32 ui32SampleRate);
+void DBGDrivSetOutputMode(struct DBG_STREAM *psStream,
+ u32 ui32OutMode);
+void DBGDrivSetDebugLevel(struct DBG_STREAM *psStream,
+ u32 ui32DebugLevel);
+void DBGDrivSetFrame(struct DBG_STREAM *psStream,
+ u32 ui32Frame);
+u32 DBGDrivGetFrame(struct DBG_STREAM *psStream);
+void DBGDrivOverrideMode(struct DBG_STREAM *psStream,
+ u32 ui32Mode);
+void DBGDrivDefaultMode(struct DBG_STREAM *psStream);
+u32 DBGDrivGetServiceTable(void);
+u32 DBGDrivWriteStringCM(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Level);
+u32 DBGDrivWriteCM(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level);
+void DBGDrivSetMarker(struct DBG_STREAM *psStream,
+ u32 ui32Marker);
+u32 DBGDrivGetMarker(struct DBG_STREAM *psStream);
+u32 DBGDrivIsLastCaptureFrame(struct DBG_STREAM *psStream);
+u32 DBGDrivIsCaptureFrame(struct DBG_STREAM *psStream,
+ IMG_BOOL bCheckPreviousFrame);
+u32 DBGDrivWriteLF(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level,
+ u32 ui32Flags);
+u32 DBGDrivReadLF(struct DBG_STREAM *psStream,
+ u32 ui32OutBuffSize,
+ u8 *pui8OutBuf);
+void DBGDrivStartInitPhase(struct DBG_STREAM *psStream);
+void DBGDrivStopInitPhase(struct DBG_STREAM *psStream);
+u32 DBGDrivGetStreamOffset(struct DBG_STREAM *psStream);
+void DBGDrivSetStreamOffset(struct DBG_STREAM *psStream, u32 ui32StreamOffset);
+void DBGDrivWaitForEvent(enum DBG_EVENT eEvent);
+
+void DestroyAllStreams(void);
+
+u32 AtoI(char *szIn);
+
+void HostMemSet(void *pvDest, u8 ui8Value, u32 ui32Size);
+void HostMemCopy(void *pvDest, void *pvSrc, u32 ui32Size);
+IMG_BOOL StreamValid(struct DBG_STREAM *psStream);
+void Write(struct DBG_STREAM *psStream, u8 *pui8Data,
+ u32 ui32InBuffSize);
+void MonoOut(char *pszString, IMG_BOOL bNewLine);
+
+void *ExtDBGDrivCreateStream(char *pszName,
+ u32 ui32CapMode,
+ u32 ui32OutMode,
+ u32 ui32Flags,
+ u32 ui32Size);
+void ExtDBGDrivDestroyStream(struct DBG_STREAM *psStream);
+void *ExtDBGDrivFindStream(char *pszName,
+ IMG_BOOL bResetStream);
+u32 ExtDBGDrivWriteString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Level);
+u32 ExtDBGDrivReadString(struct DBG_STREAM *psStream,
+ char *pszString,
+ u32 ui32Limit);
+u32 ExtDBGDrivWrite(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level);
+u32 ExtDBGDrivRead(struct DBG_STREAM *psStream,
+ IMG_BOOL bReadInitBuffer,
+ u32 ui32OutBuffSize,
+ u8 *pui8OutBuf);
+void ExtDBGDrivSetCaptureMode(struct DBG_STREAM *psStream,
+ u32 ui32Mode,
+ u32 ui32Start,
+ u32 ui32End,
+ u32 ui32SampleRate);
+void ExtDBGDrivSetOutputMode(struct DBG_STREAM *psStream,
+ u32 ui32OutMode);
+void ExtDBGDrivSetDebugLevel(struct DBG_STREAM *psStream,
+ u32 ui32DebugLevel);
+void ExtDBGDrivSetFrame(struct DBG_STREAM *psStream,
+ u32 ui32Frame);
+u32 ExtDBGDrivGetFrame(struct DBG_STREAM *psStream);
+void ExtDBGDrivOverrideMode(struct DBG_STREAM *psStream,
+ u32 ui32Mode);
+void ExtDBGDrivDefaultMode(struct DBG_STREAM *psStream);
+u32 ExtDBGDrivWrite2(struct DBG_STREAM *psStream, u8 *pui8InBuf,
+ u32 ui32InBuffSize, u32 ui32Level);
+u32 ExtDBGDrivWriteStringCM(struct DBG_STREAM *psStream, char *pszString,
+ u32 ui32Level);
+u32 ExtDBGDrivWriteCM(struct DBG_STREAM *psStream, u8 *pui8InBuf,
+ u32 ui32InBuffSize, u32 ui32Level);
+void ExtDBGDrivSetMarker(struct DBG_STREAM *psStream, u32 ui32Marker);
+u32 ExtDBGDrivGetMarker(struct DBG_STREAM *psStream);
+void ExtDBGDrivStartInitPhase(struct DBG_STREAM *psStream);
+void ExtDBGDrivStopInitPhase(struct DBG_STREAM *psStream);
+u32 ExtDBGDrivIsLastCaptureFrame(struct DBG_STREAM *psStream);
+u32 ExtDBGDrivIsCaptureFrame(struct DBG_STREAM *psStream,
+ IMG_BOOL bCheckPreviousFrame);
+u32 ExtDBGDrivWriteLF(struct DBG_STREAM *psStream,
+ u8 *pui8InBuf,
+ u32 ui32InBuffSize,
+ u32 ui32Level,
+ u32 ui32Flags);
+u32 ExtDBGDrivReadLF(struct DBG_STREAM *psStream,
+ u32 ui32OutBuffSize,
+ u8 *pui8OutBuf);
+u32 ExtDBGDrivGetStreamOffset(struct DBG_STREAM *psStream);
+void ExtDBGDrivSetStreamOffset(struct DBG_STREAM *psStream,
+ u32 ui32StreamOffset);
+void ExtDBGDrivWaitForEvent(enum DBG_EVENT eEvent);
+
+#endif
diff --git a/drivers/gpu/pvr/tools/hostfunc.c b/drivers/gpu/pvr/tools/hostfunc.c
new file mode 100644
index 00000000000..efc9f687ae4
--- /dev/null
+++ b/drivers/gpu/pvr/tools/hostfunc.c
@@ -0,0 +1,267 @@
+/**********************************************************************
+ *
+ * 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 <linux/version.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#include <linux/mutex.h>
+#include <linux/hardirq.h>
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+#endif
+
+#include "img_types.h"
+#include "pvr_debug.h"
+
+#include "dbgdrvif.h"
+#include "hostfunc.h"
+
+#define PVR_STRING_TERMINATOR '\0'
+#define PVR_IS_FILE_SEPARATOR(character) \
+ (((character) == '\\') || ((character) == '/'))
+
+static u32 gPVRDebugLevel = DBGPRIV_WARNING;
+
+void PVRSRVDebugPrintf(u32 ui32DebugLevel,
+ const char *pszFileName,
+ u32 ui32Line, const char *pszFormat, ...
+ )
+{
+ IMG_BOOL bTrace, bDebug;
+ char *pszLeafName;
+
+ pszLeafName = (char *)strrchr(pszFileName, '\\');
+
+ if (pszLeafName)
+ pszFileName = pszLeafName;
+
+ bTrace = gPVRDebugLevel & ui32DebugLevel & DBGPRIV_CALLTRACE;
+ bDebug = ((gPVRDebugLevel & DBGPRIV_ALLLEVELS) >= ui32DebugLevel);
+
+ if (bTrace || bDebug) {
+ va_list vaArgs;
+ static char szBuffer[256];
+
+ va_start(vaArgs, pszFormat);
+
+ if (bDebug) {
+ switch (ui32DebugLevel) {
+ case DBGPRIV_FATAL:
+ {
+ strcpy(szBuffer, "PVR_K:(Fatal): ");
+ break;
+ }
+ case DBGPRIV_ERROR:
+ {
+ strcpy(szBuffer, "PVR_K:(Error): ");
+ break;
+ }
+ case DBGPRIV_WARNING:
+ {
+ strcpy(szBuffer, "PVR_K:(Warning): ");
+ break;
+ }
+ case DBGPRIV_MESSAGE:
+ {
+ strcpy(szBuffer, "PVR_K:(Message): ");
+ break;
+ }
+ case DBGPRIV_VERBOSE:
+ {
+ strcpy(szBuffer, "PVR_K:(Verbose): ");
+ break;
+ }
+ default:
+ {
+ strcpy(szBuffer,
+ "PVR_K:(Unknown message level)");
+ break;
+ }
+ }
+ } else {
+ strcpy(szBuffer, "PVR_K: ");
+ }
+
+ vsprintf(&szBuffer[strlen(szBuffer)], pszFormat, vaArgs);
+
+ if (!bTrace)
+ sprintf(&szBuffer[strlen(szBuffer)], " [%d, %s]",
+ (int)ui32Line, pszFileName);
+
+ printk(KERN_INFO "%s\r\n", szBuffer);
+
+ va_end(vaArgs);
+ }
+}
+
+void HostMemSet(void *pvDest, u8 ui8Value, u32 ui32Size)
+{
+ memset(pvDest, (int)ui8Value, (size_t) ui32Size);
+}
+
+void HostMemCopy(void *pvDst, void *pvSrc, u32 ui32Size)
+{
+ memcpy(pvDst, pvSrc, ui32Size);
+}
+
+u32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName,
+ u32 *pui32Data)
+{
+
+ return 0;
+}
+
+void *HostPageablePageAlloc(u32 ui32Pages)
+{
+ return (void *)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+void HostPageablePageFree(void *pvBase)
+{
+ vfree(pvBase);
+}
+
+void *HostNonPageablePageAlloc(u32 ui32Pages)
+{
+ return (void *)vmalloc(ui32Pages * PAGE_SIZE);
+}
+
+void HostNonPageablePageFree(void *pvBase)
+{
+ vfree(pvBase);
+}
+
+void *HostMapKrnBufIntoUser(void *pvKrnAddr, u32 ui32Size,
+ void **ppvMdl)
+{
+
+ return NULL;
+}
+
+void HostUnMapKrnBufFromUser(void *pvUserAddr, void *pvMdl,
+ void *pvProcess)
+{
+
+}
+
+void HostCreateRegDeclStreams(void)
+{
+
+}
+
+void *HostCreateMutex(void)
+{
+ struct mutex *psSem;
+
+ psSem = kmalloc(sizeof(*psSem), GFP_KERNEL);
+ if (psSem)
+ mutex_init(psSem);
+
+ return psSem;
+}
+
+void HostAquireMutex(void *pvMutex)
+{
+ BUG_ON(in_interrupt());
+
+#if defined(PVR_DEBUG_DBGDRV_DETECT_HOST_MUTEX_COLLISIONS)
+ if (mutex_trylock((struct mutex *)pvMutex)) {
+ printk(KERN_INFO "HostAquireMutex: Waiting for mutex\n");
+ mutex_lock((struct mutex *)pvMutex);
+ }
+#else
+ mutex_lock((struct mutex *)pvMutex);
+#endif
+}
+
+void HostReleaseMutex(void *pvMutex)
+{
+ mutex_unlock((struct mutex *)pvMutex);
+}
+
+void HostDestroyMutex(void *pvMutex)
+{
+ kfree(pvMutex);
+}
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+#define EVENT_WAIT_TIMEOUT_MS 500
+#define EVENT_WAIT_TIMEOUT_JIFFIES (EVENT_WAIT_TIMEOUT_MS * HZ / 1000)
+
+static int iStreamData;
+static wait_queue_head_t sStreamDataEvent;
+
+s32 HostCreateEventObjects(void)
+{
+ init_waitqueue_head(&sStreamDataEvent);
+
+ return 0;
+}
+
+void HostWaitForEvent(enum DBG_EVENT eEvent)
+{
+ switch (eEvent) {
+ case DBG_EVENT_STREAM_DATA:
+
+ wait_event_interruptible_timeout(sStreamDataEvent,
+ iStreamData != 0,
+ EVENT_WAIT_TIMEOUT_JIFFIES);
+ iStreamData = 0;
+ break;
+ default:
+
+ msleep_interruptible(EVENT_WAIT_TIMEOUT_MS);
+ break;
+ }
+}
+
+void HostSignalEvent(enum DBG_EVENT eEvent)
+{
+ switch (eEvent) {
+ case DBG_EVENT_STREAM_DATA:
+ iStreamData = 1;
+ wake_up_interruptible(&sStreamDataEvent);
+ break;
+ default:
+ break;
+ }
+}
+
+void HostDestroyEventObjects(void)
+{
+}
+#endif
diff --git a/drivers/gpu/pvr/tools/hostfunc.h b/drivers/gpu/pvr/tools/hostfunc.h
new file mode 100644
index 00000000000..64f88230e63
--- /dev/null
+++ b/drivers/gpu/pvr/tools/hostfunc.h
@@ -0,0 +1,58 @@
+/**********************************************************************
+ *
+ * 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 _HOSTFUNC_
+#define _HOSTFUNC_
+
+#define HOST_PAGESIZE (4096)
+#define DBG_MEMORY_INITIALIZER (0xe2)
+
+u32 HostReadRegistryDWORDFromString(char *pcKey, char *pcValueName,
+ u32 *pui32Data);
+
+void *HostPageablePageAlloc(u32 ui32Pages);
+void HostPageablePageFree(void *pvBase);
+void *HostNonPageablePageAlloc(u32 ui32Pages);
+void HostNonPageablePageFree(void *pvBase);
+
+void *HostMapKrnBufIntoUser(void *pvKrnAddr, u32 ui32Size, void **ppvMdl);
+void HostUnMapKrnBufFromUser(void *pvUserAddr, void *pvMdl, void *pvProcess);
+
+void HostCreateRegDeclStreams(void);
+
+void *HostCreateMutex(void);
+void HostAquireMutex(void *pvMutex);
+void HostReleaseMutex(void *pvMutex);
+void HostDestroyMutex(void *pvMutex);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+s32 HostCreateEventObjects(void);
+void HostWaitForEvent(enum DBG_EVENT eEvent);
+void HostSignalEvent(enum DBG_EVENT eEvent);
+void HostDestroyEventObjects(void);
+#endif
+
+#endif
diff --git a/drivers/gpu/pvr/tools/hotkey.c b/drivers/gpu/pvr/tools/hotkey.c
new file mode 100644
index 00000000000..b5a2eb86909
--- /dev/null
+++ b/drivers/gpu/pvr/tools/hotkey.c
@@ -0,0 +1,101 @@
+/**********************************************************************
+ *
+ * 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_types.h"
+#include "pvr_debug.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+#include "hostfunc.h"
+
+u32 g_ui32HotKeyFrame = 0xFFFFFFFF;
+IMG_BOOL g_bHotKeyPressed = IMG_FALSE;
+IMG_BOOL g_bHotKeyRegistered = IMG_FALSE;
+
+struct PRIVATEHOTKEYDATA g_PrivateHotKeyData;
+
+void ReadInHotKeys(void)
+{
+ g_PrivateHotKeyData.ui32ScanCode = 0x58;
+ g_PrivateHotKeyData.ui32ShiftState = 0x0;
+
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ScanCode",
+ &g_PrivateHotKeyData.ui32ScanCode);
+ HostReadRegistryDWORDFromString("DEBUG\\Streams", "ui32ShiftState",
+ &g_PrivateHotKeyData.ui32ShiftState);
+}
+
+void RegisterKeyPressed(u32 dwui32ScanCode, struct HOTKEYINFO *pInfo)
+{
+ struct DBG_STREAM *psStream;
+
+ PVR_UNREFERENCED_PARAMETER(pInfo);
+
+ if (dwui32ScanCode == g_PrivateHotKeyData.ui32ScanCode) {
+ PVR_DPF(PVR_DBG_MESSAGE, "PDUMP Hotkey pressed !\n");
+
+ psStream = (struct DBG_STREAM *)
+ g_PrivateHotKeyData.sHotKeyInfo.pvStream;
+
+ if (!g_bHotKeyPressed) {
+
+ g_ui32HotKeyFrame = psStream->ui32Current + 2;
+
+ g_bHotKeyPressed = IMG_TRUE;
+ }
+ }
+}
+
+void ActivateHotKeys(struct DBG_STREAM *psStream)
+{
+
+ ReadInHotKeys();
+
+ if (!g_PrivateHotKeyData.sHotKeyInfo.hHotKey) {
+ if (g_PrivateHotKeyData.ui32ScanCode != 0) {
+ PVR_DPF(PVR_DBG_MESSAGE,
+ "Activate HotKey for PDUMP.\n");
+
+ g_PrivateHotKeyData.sHotKeyInfo.pvStream = psStream;
+
+ DefineHotKey(g_PrivateHotKeyData.ui32ScanCode,
+ g_PrivateHotKeyData.ui32ShiftState,
+ &g_PrivateHotKeyData.sHotKeyInfo);
+ } else {
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+ }
+}
+
+void DeactivateHotKeys(void)
+{
+ if (g_PrivateHotKeyData.sHotKeyInfo.hHotKey != 0) {
+ PVR_DPF(PVR_DBG_MESSAGE, "Deactivate HotKey.\n");
+
+ RemoveHotKey(g_PrivateHotKeyData.sHotKeyInfo.hHotKey);
+ g_PrivateHotKeyData.sHotKeyInfo.hHotKey = 0;
+ }
+}
diff --git a/drivers/gpu/pvr/tools/hotkey.h b/drivers/gpu/pvr/tools/hotkey.h
new file mode 100644
index 00000000000..56c559fe3d4
--- /dev/null
+++ b/drivers/gpu/pvr/tools/hotkey.h
@@ -0,0 +1,60 @@
+/**********************************************************************
+ *
+ * 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 _HOTKEY_
+#define _HOTKEY_
+
+struct HOTKEYINFO {
+ u8 ui8ScanCode;
+ u8 ui8Type;
+ u8 ui8Flag;
+ u8 ui8Filler1;
+ u32 ui32ShiftState;
+ u32 ui32HotKeyProc;
+ void *pvStream;
+ u32 hHotKey;
+};
+
+struct PRIVATEHOTKEYDATA {
+ u32 ui32ScanCode;
+ u32 ui32ShiftState;
+ struct HOTKEYINFO sHotKeyInfo;
+};
+
+extern u32 g_ui32HotKeyFrame;
+extern IMG_BOOL g_bHotKeyPressed;
+extern IMG_BOOL g_bHotKeyRegistered;
+
+void ReadInHotKeys(void);
+void ActivateHotKeys(struct DBG_STREAM *psStream);
+void DeactivateHotKeys(void);
+
+void RemoveHotKey(u32 hHotKey);
+void DefineHotKey(u32 ui32ScanCode, u32 ui32ShiftState,
+ struct HOTKEYINFO *psInfo);
+void RegisterKeyPressed(u32 ui32ScanCode, struct HOTKEYINFO *psInfo);
+
+#endif
diff --git a/drivers/gpu/pvr/tools/ioctl.c b/drivers/gpu/pvr/tools/ioctl.c
new file mode 100644
index 00000000000..ddba5278b67
--- /dev/null
+++ b/drivers/gpu/pvr/tools/ioctl.c
@@ -0,0 +1,399 @@
+/**********************************************************************
+ *
+ * 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 <linux/uaccess.h>
+
+#include "img_types.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hotkey.h"
+
+u32 DBGDIOCDrivCreateStream(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ struct DBG_IN_CREATESTREAM *psIn;
+ void **ppvOut;
+ static char name[32];
+
+ psIn = (struct DBG_IN_CREATESTREAM *)pvInBuffer;
+ ppvOut = (void **)pvOutBuffer;
+
+
+ if (copy_from_user(name, psIn->pszName, 32) != 0)
+ return IMG_FALSE;
+ *ppvOut =
+ ExtDBGDrivCreateStream(name, psIn->ui32CapMode, psIn->ui32OutMode,
+ 0, psIn->ui32Pages);
+
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivDestroyStream(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ u32 *pStream;
+ struct DBG_STREAM *psStream;
+
+ pStream = (u32 *) pvInBuffer;
+ psStream = (struct DBG_STREAM *)*pStream;
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivDestroyStream(psStream);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivGetStream(void *pvInBuffer, void *pvOutBuffer)
+{
+ struct DBG_IN_FINDSTREAM *psParams;
+ u32 *pui32Stream;
+
+ psParams = (struct DBG_IN_FINDSTREAM *)pvInBuffer;
+ pui32Stream = (u32 *) pvOutBuffer;
+
+ *pui32Stream =
+ (u32) ExtDBGDrivFindStream(psParams->pszName,
+ psParams->bResetStream);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivWriteString(void *pvInBuffer, void *pvOutBuffer)
+{
+ struct DBG_IN_WRITESTRING *psParams;
+ u32 *pui32OutLen;
+
+ psParams = (struct DBG_IN_WRITESTRING *)pvInBuffer;
+ pui32OutLen = (u32 *) pvOutBuffer;
+
+ *pui32OutLen =
+ ExtDBGDrivWriteString((struct DBG_STREAM *)psParams->pvStream,
+ psParams->pszString, psParams->ui32Level);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivWriteStringCM(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ struct DBG_IN_WRITESTRING *psParams;
+ u32 *pui32OutLen;
+
+ psParams = (struct DBG_IN_WRITESTRING *)pvInBuffer;
+ pui32OutLen = (u32 *) pvOutBuffer;
+
+ *pui32OutLen =
+ ExtDBGDrivWriteStringCM((struct DBG_STREAM *)psParams->pvStream,
+ psParams->pszString, psParams->ui32Level);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivReadString(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pui32OutLen;
+ struct DBG_IN_READSTRING *psParams;
+
+ psParams = (struct DBG_IN_READSTRING *)pvInBuffer;
+ pui32OutLen = (u32 *) pvOutBuffer;
+
+ *pui32OutLen =
+ ExtDBGDrivReadString(psParams->pvStream, psParams->pszString,
+ psParams->ui32StringLen);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivWrite(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pui32BytesCopied;
+ struct DBG_IN_WRITE *psInParams;
+
+ psInParams = (struct DBG_IN_WRITE *)pvInBuffer;
+ pui32BytesCopied = (u32 *) pvOutBuffer;
+
+ *pui32BytesCopied =
+ ExtDBGDrivWrite((struct DBG_STREAM *)psInParams->pvStream,
+ psInParams->pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivWrite2(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pui32BytesCopied;
+ struct DBG_IN_WRITE *psInParams;
+
+ psInParams = (struct DBG_IN_WRITE *)pvInBuffer;
+ pui32BytesCopied = (u32 *) pvOutBuffer;
+
+ *pui32BytesCopied =
+ ExtDBGDrivWrite2((struct DBG_STREAM *)psInParams->pvStream,
+ psInParams->pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivWriteCM(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pui32BytesCopied;
+ struct DBG_IN_WRITE *psInParams;
+
+ psInParams = (struct DBG_IN_WRITE *)pvInBuffer;
+ pui32BytesCopied = (u32 *) pvOutBuffer;
+
+ *pui32BytesCopied =
+ ExtDBGDrivWriteCM((struct DBG_STREAM *)psInParams->pvStream,
+ psInParams->pui8InBuffer,
+ psInParams->ui32TransferSize,
+ psInParams->ui32Level);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivRead(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pui32BytesCopied;
+ struct DBG_IN_READ *psInParams;
+
+ psInParams = (struct DBG_IN_READ *)pvInBuffer;
+ pui32BytesCopied = (u32 *) pvOutBuffer;
+
+ *pui32BytesCopied =
+ ExtDBGDrivRead((struct DBG_STREAM *)psInParams->pvStream,
+ psInParams->bReadInitBuffer,
+ psInParams->ui32OutBufferSize,
+ psInParams->pui8OutBuffer);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivSetCaptureMode(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ struct DBG_IN_SETDEBUGMODE *psParams;
+
+ psParams = (struct DBG_IN_SETDEBUGMODE *)pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetCaptureMode((struct DBG_STREAM *)psParams->pvStream,
+ psParams->ui32Mode,
+ psParams->ui32Start,
+ psParams->ui32End, psParams->ui32SampleRate);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivSetOutMode(void *pvInBuffer, void *pvOutBuffer)
+{
+ struct DBG_IN_SETDEBUGOUTMODE *psParams;
+
+ psParams = (struct DBG_IN_SETDEBUGOUTMODE *)pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetOutputMode((struct DBG_STREAM *)psParams->pvStream,
+ psParams->ui32Mode);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivSetDebugLevel(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ struct DBG_IN_SETDEBUGLEVEL *psParams;
+
+ psParams = (struct DBG_IN_SETDEBUGLEVEL *)pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetDebugLevel((struct DBG_STREAM *)psParams->pvStream,
+ psParams->ui32Level);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivSetFrame(void *pvInBuffer, void *pvOutBuffer)
+{
+ struct DBG_IN_SETFRAME *psParams;
+
+ psParams = (struct DBG_IN_SETFRAME *)pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetFrame((struct DBG_STREAM *)psParams->pvStream,
+ psParams->ui32Frame);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivGetFrame(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pStream;
+ struct DBG_STREAM *psStream;
+ u32 *pui32Current;
+
+ pStream = (u32 *) pvInBuffer;
+ psStream = (struct DBG_STREAM *)*pStream;
+ pui32Current = (u32 *) pvOutBuffer;
+
+ *pui32Current = ExtDBGDrivGetFrame(psStream);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivIsCaptureFrame(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ struct DBG_IN_ISCAPTUREFRAME *psParams;
+ u32 *pui32Current;
+
+ psParams = (struct DBG_IN_ISCAPTUREFRAME *)pvInBuffer;
+ pui32Current = (u32 *) pvOutBuffer;
+
+ *pui32Current =
+ ExtDBGDrivIsCaptureFrame((struct DBG_STREAM *)psParams->pvStream,
+ psParams->bCheckPreviousFrame);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivOverrideMode(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ struct DBG_IN_OVERRIDEMODE *psParams;
+
+ psParams = (struct DBG_IN_OVERRIDEMODE *)pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivOverrideMode((struct DBG_STREAM *)psParams->pvStream,
+ psParams->ui32Mode);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivDefaultMode(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pStream;
+ struct DBG_STREAM *psStream;
+
+ pStream = (u32 *) pvInBuffer;
+ psStream = (struct DBG_STREAM *)*pStream;
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivDefaultMode(psStream);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivSetMarker(void *pvInBuffer, void *pvOutBuffer)
+{
+ struct DBG_IN_SETMARKER *psParams;
+
+ psParams = (struct DBG_IN_SETMARKER *)pvInBuffer;
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivSetMarker((struct DBG_STREAM *)psParams->pvStream,
+ psParams->ui32Marker);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivGetMarker(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pStream;
+ struct DBG_STREAM *psStream;
+ u32 *pui32Current;
+
+ pStream = (u32 *) pvInBuffer;
+ psStream = (struct DBG_STREAM *)*pStream;
+ pui32Current = (u32 *) pvOutBuffer;
+
+ *pui32Current = ExtDBGDrivGetMarker(psStream);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivGetServiceTable(void *pvInBuffer,
+ void *pvOutBuffer)
+{
+ u32 *pui32Out;
+
+ PVR_UNREFERENCED_PARAMETER(pvInBuffer);
+ pui32Out = (u32 *) pvOutBuffer;
+
+ *pui32Out = DBGDrivGetServiceTable();
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivWriteLF(void *pvInBuffer, void *pvOutBuffer)
+{
+ struct DBG_IN_WRITE_LF *psInParams;
+ u32 *pui32BytesCopied;
+
+ psInParams = (struct DBG_IN_WRITE_LF *)pvInBuffer;
+ pui32BytesCopied = (u32 *) pvOutBuffer;
+
+ *pui32BytesCopied = ExtDBGDrivWriteLF(psInParams->pvStream,
+ psInParams->pui8InBuffer,
+ psInParams->ui32BufferSize,
+ psInParams->ui32Level,
+ psInParams->ui32Flags);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivReadLF(void *pvInBuffer, void *pvOutBuffer)
+{
+ u32 *pui32BytesCopied;
+ struct DBG_IN_READ *psInParams;
+
+ psInParams = (struct DBG_IN_READ *)pvInBuffer;
+ pui32BytesCopied = (u32 *) pvOutBuffer;
+
+ *pui32BytesCopied =
+ ExtDBGDrivReadLF((struct DBG_STREAM *)psInParams->pvStream,
+ psInParams->ui32OutBufferSize,
+ psInParams->pui8OutBuffer);
+
+ return IMG_TRUE;
+}
+
+u32 DBGDIOCDrivWaitForEvent(void *pvInBuffer, void *pvOutBuffer)
+{
+ enum DBG_EVENT eEvent = (enum DBG_EVENT)(*(u32 *) pvInBuffer);
+
+ PVR_UNREFERENCED_PARAMETER(pvOutBuffer);
+
+ ExtDBGDrivWaitForEvent(eEvent);
+
+ return IMG_TRUE;
+}
diff --git a/drivers/gpu/pvr/tools/ioctl.h b/drivers/gpu/pvr/tools/ioctl.h
new file mode 100644
index 00000000000..fcb1ff156eb
--- /dev/null
+++ b/drivers/gpu/pvr/tools/ioctl.h
@@ -0,0 +1,81 @@
+/**********************************************************************
+ *
+ * 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 _IOCTL_
+#define _IOCTL_
+
+u32 DBGDIOCDrivCreateStream(void *, void *);
+u32 DBGDIOCDrivDestroyStream(void *, void *);
+u32 DBGDIOCDrivGetStream(void *, void *);
+u32 DBGDIOCDrivWriteString(void *, void *);
+u32 DBGDIOCDrivReadString(void *, void *);
+u32 DBGDIOCDrivWrite(void *, void *);
+u32 DBGDIOCDrivWrite2(void *, void *);
+u32 DBGDIOCDrivRead(void *, void *);
+u32 DBGDIOCDrivSetCaptureMode(void *, void *);
+u32 DBGDIOCDrivSetOutMode(void *, void *);
+u32 DBGDIOCDrivSetDebugLevel(void *, void *);
+u32 DBGDIOCDrivSetFrame(void *, void *);
+u32 DBGDIOCDrivGetFrame(void *, void *);
+u32 DBGDIOCDrivOverrideMode(void *, void *);
+u32 DBGDIOCDrivDefaultMode(void *, void *);
+u32 DBGDIOCDrivGetServiceTable(void *, void *);
+u32 DBGDIOCDrivWriteStringCM(void *, void *);
+u32 DBGDIOCDrivWriteCM(void *, void *);
+u32 DBGDIOCDrivSetMarker(void *, void *);
+u32 DBGDIOCDrivGetMarker(void *, void *);
+u32 DBGDIOCDrivIsCaptureFrame(void *, void *);
+u32 DBGDIOCDrivWriteLF(void *, void *);
+u32 DBGDIOCDrivReadLF(void *, void *);
+u32 DBGDIOCDrivWaitForEvent(void *, void *);
+
+u32(*g_DBGDrivProc[])(void *, void *) = {
+DBGDIOCDrivCreateStream,
+ DBGDIOCDrivDestroyStream,
+ DBGDIOCDrivGetStream,
+ DBGDIOCDrivWriteString,
+ DBGDIOCDrivReadString,
+ DBGDIOCDrivWrite,
+ DBGDIOCDrivRead,
+ DBGDIOCDrivSetCaptureMode,
+ DBGDIOCDrivSetOutMode,
+ DBGDIOCDrivSetDebugLevel,
+ DBGDIOCDrivSetFrame,
+ DBGDIOCDrivGetFrame,
+ DBGDIOCDrivOverrideMode,
+ DBGDIOCDrivDefaultMode,
+ DBGDIOCDrivGetServiceTable,
+ DBGDIOCDrivWrite2,
+ DBGDIOCDrivWriteStringCM,
+ DBGDIOCDrivWriteCM,
+ DBGDIOCDrivSetMarker,
+ DBGDIOCDrivGetMarker,
+ DBGDIOCDrivIsCaptureFrame,
+ DBGDIOCDrivWriteLF, DBGDIOCDrivReadLF, DBGDIOCDrivWaitForEvent};
+
+#define MAX_DBGVXD_W32_API (sizeof(g_DBGDrivProc)/sizeof(u32))
+
+#endif
diff --git a/drivers/gpu/pvr/tools/linuxsrv.h b/drivers/gpu/pvr/tools/linuxsrv.h
new file mode 100644
index 00000000000..822ba4e3027
--- /dev/null
+++ b/drivers/gpu/pvr/tools/linuxsrv.h
@@ -0,0 +1,47 @@
+/**********************************************************************
+ *
+ * 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 _LINUXSRV_H__
+#define _LINUXSRV_H__
+
+struct IOCTL_PACKAGE {
+ u32 ui32Cmd;
+ u32 ui32Size;
+ void *pInBuffer;
+ u32 ui32InBufferSize;
+ void *pOutBuffer;
+ u32 ui32OutBufferSize;
+};
+
+u32 DeviceIoControl(u32 hDevice,
+ u32 ui32ControlCode,
+ void *pInBuffer,
+ u32 ui32InBufferSize,
+ void *pOutBuffer,
+ u32 ui32OutBufferSize,
+ u32 *pui32BytesReturned);
+
+#endif
diff --git a/drivers/gpu/pvr/tools/main.c b/drivers/gpu/pvr/tools/main.c
new file mode 100644
index 00000000000..5de15cc944b
--- /dev/null
+++ b/drivers/gpu/pvr/tools/main.c
@@ -0,0 +1,197 @@
+/**********************************************************************
+ *
+ * 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 <linux/errno.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/uaccess.h>
+
+#include "img_types.h"
+#include "linuxsrv.h"
+#include "ioctl.h"
+#include "dbgdrvif.h"
+#include "dbgdriv.h"
+#include "hostfunc.h"
+#include "pvr_debug.h"
+
+#define DRVNAME "dbgdrv"
+
+MODULE_AUTHOR("Imagination Technologies Ltd. <gpl-support@imgtec.com>");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE(DRVNAME);
+
+static int AssignedMajorNumber;
+
+static long dbgdrv_ioctl(struct file *, unsigned int, unsigned long);
+
+static int dbgdrv_open(struct inode unref__ * pInode,
+ struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_release(struct inode unref__ * pInode,
+ struct file unref__ * pFile)
+{
+ return 0;
+}
+
+static int dbgdrv_mmap(struct file *pFile, struct vm_area_struct *ps_vma)
+{
+ return 0;
+}
+
+static const struct file_operations dbgdrv_fops = {
+owner: THIS_MODULE,
+unlocked_ioctl : dbgdrv_ioctl,
+open : dbgdrv_open,
+release : dbgdrv_release,
+mmap : dbgdrv_mmap,
+};
+
+void DBGDrvGetServiceTable(void **fn_table)
+{
+ *fn_table = &g_sDBGKMServices;
+
+}
+EXPORT_SYMBOL(DBGDrvGetServiceTable);
+
+void cleanup_module(void)
+{
+ if (AssignedMajorNumber > 0)
+ unregister_chrdev(AssignedMajorNumber, DRVNAME);
+
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+ HostDestroyEventObjects();
+#endif
+
+ if (g_pvAPIMutex != NULL)
+ HostDestroyMutex(g_pvAPIMutex);
+
+ return;
+}
+
+int init_module(void)
+{
+ g_pvAPIMutex = HostCreateMutex();
+ if (g_pvAPIMutex == NULL) {
+ cleanup_module();
+ return -ENOMEM;
+ }
+#if defined(SUPPORT_DBGDRV_EVENT_OBJECTS)
+
+ (void)HostCreateEventObjects();
+#endif
+
+ AssignedMajorNumber =
+ register_chrdev(AssignedMajorNumber, DRVNAME, &dbgdrv_fops);
+
+ if (AssignedMajorNumber <= 0) {
+ PVR_DPF(PVR_DBG_ERROR, " unable to get major\n");
+ cleanup_module();
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static long dbgdrv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct IOCTL_PACKAGE *pIP = (struct IOCTL_PACKAGE *)arg;
+
+ char *buffer, *in, *out;
+
+ if ((pIP->ui32InBufferSize > (PAGE_SIZE >> 1))
+ || (pIP->ui32OutBufferSize > (PAGE_SIZE >> 1))) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "Sizes of the buffers are too large, cannot do ioctl\n");
+ return -1;
+ }
+
+ buffer = (char *)HostPageablePageAlloc(1);
+ if (!buffer) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "Failed to allocate buffer, cannot do ioctl\n");
+ return -EFAULT;
+ }
+
+ in = buffer;
+ out = buffer + (PAGE_SIZE >> 1);
+
+ if (copy_from_user(in, pIP->pInBuffer, pIP->ui32InBufferSize) != 0)
+ goto init_failed;
+
+ cmd = ((pIP->ui32Cmd >> 2) & 0xFFF) - 0x801;
+
+ if (pIP->ui32Cmd == DEBUG_SERVICE_READ) {
+ char *ui8Tmp;
+ u32 *pui32BytesCopied = (u32 *) out;
+ struct DBG_IN_READ *psReadInParams = (struct DBG_IN_READ *)in;
+
+ ui8Tmp = vmalloc(psReadInParams->ui32OutBufferSize);
+ if (!ui8Tmp)
+ goto init_failed;
+ *pui32BytesCopied = ExtDBGDrivRead((struct DBG_STREAM *)
+ psReadInParams->pvStream,
+ psReadInParams->bReadInitBuffer,
+ psReadInParams->ui32OutBufferSize, ui8Tmp);
+ if (copy_to_user(psReadInParams->pui8OutBuffer, ui8Tmp,
+ *pui32BytesCopied) != 0) {
+ vfree(ui8Tmp);
+ goto init_failed;
+ }
+ vfree(ui8Tmp);
+ } else {
+ (g_DBGDrivProc[cmd]) (in, out);
+ }
+
+ if (copy_to_user(pIP->pOutBuffer, out, pIP->ui32OutBufferSize) != 0)
+ goto init_failed;
+
+ HostPageablePageFree((void *) buffer);
+ return 0;
+
+init_failed:
+ HostPageablePageFree((void *) buffer);
+ return -EFAULT;
+}
+
+void RemoveHotKey(unsigned hHotKey)
+{
+
+}
+
+void DefineHotKey(unsigned ScanCode, unsigned ShiftState, void *pInfo)
+{
+
+}
+
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 175f8f6ff88..1e02feb8463 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -23,6 +23,8 @@ source "drivers/gpu/drm/Kconfig"
source "drivers/gpu/stub/Kconfig"
+source "drivers/gpu/pvr/Kconfig"
+
config VGASTATE
tristate
default n
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 8ab6d43329b..d3eecdd00b3 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -201,6 +201,8 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
int dss_init_overlay_managers(struct platform_device *pdev);
void dss_uninit_overlay_managers(struct platform_device *pdev);
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
+int dss_mgr_notify_ovl(struct omap_overlay *ovl,
+ enum omap_dss_notify_event events);
void dss_setup_partial_planes(struct omap_dss_device *dssdev,
u16 *x, u16 *y, u16 *w, u16 *h,
bool enlarge_update_area);
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 9aeea50e33f..7908b032e6d 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
@@ -418,6 +419,8 @@ struct overlay_cache_data {
u32 fifo_high;
bool manual_update;
+
+ enum omap_dss_notify_event requested_events;
};
struct manager_cache_data {
@@ -429,6 +432,8 @@ struct manager_cache_data {
* VSYNC/EVSYNC */
bool shadow_dirty;
+ bool enabled;
+
u32 default_color;
enum omap_dss_trans_key_type trans_key_type;
@@ -447,8 +452,14 @@ struct manager_cache_data {
/* enlarge the update area if the update area contains scaled
* overlays */
bool enlarge_update_area;
+
+ bool in_use;
+
+ enum omap_dss_notify_event requested_events;
};
+static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
+
static struct {
spinlock_t lock;
struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
@@ -457,7 +468,156 @@ static struct {
bool irq_enabled;
} dss_cache;
+static ATOMIC_NOTIFIER_HEAD(dss_notifier_list);
+
+static int dss_notifier_call_chain(unsigned long val, void *v)
+{
+ return atomic_notifier_call_chain(&dss_notifier_list, val, v);
+}
+
+/**
+ * Check from events which should be fired now.
+ *
+ * @return: list of events that should fire now.
+ */
+static enum omap_dss_notify_event dss_mgr_notify_check(
+ struct omap_overlay_manager *mgr,
+ struct manager_cache_data *mc,
+ enum omap_dss_notify_event events)
+{
+ if (mc->manual_update) {
+ if (mc->enabled && mc->in_use && mgr->info_dirty)
+ events &= ~OMAP_DSS_NOTIFY_GO_MGR;
+
+ if (mc->enabled && mc->in_use)
+ events &= ~OMAP_DSS_NOTIFY_UPDATE_MGR;
+ } else {
+ if (mc->enabled && (mc->dirty || mc->shadow_dirty))
+ events = OMAP_DSS_NOTIFY_NONE;
+ }
+
+ return events;
+}
+
+static enum omap_dss_notify_event dss_mgr_notify_check_ovl(
+ struct omap_overlay *ovl,
+ struct overlay_cache_data *oc,
+ struct manager_cache_data *mc,
+ enum omap_dss_notify_event events)
+{
+ if (mc->manual_update) {
+ if (mc->enabled && oc->enabled
+ && mc->in_use && ovl->info_dirty)
+ events &= ~OMAP_DSS_NOTIFY_GO_OVL;
+
+ if (mc->enabled && oc->enabled && mc->in_use)
+ events &= ~OMAP_DSS_NOTIFY_UPDATE_OVL;
+ } else {
+ if (mc->enabled && oc->enabled
+ && (oc->dirty || oc->shadow_dirty))
+ events = OMAP_DSS_NOTIFY_NONE;
+ }
+
+ return events;
+}
+
+static enum omap_dss_notify_event check_mgr_notify(
+ struct omap_overlay_manager *mgr)
+{
+ struct manager_cache_data *mc;
+
+ if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
+ return OMAP_DSS_NOTIFY_NONE;
+
+ mc = &dss_cache.manager_cache[mgr->id];
+
+ if (mc->requested_events == OMAP_DSS_NOTIFY_NONE)
+ return OMAP_DSS_NOTIFY_NONE;
+ return dss_mgr_notify_check(mgr, mc, mc->requested_events);
+}
+
+static enum omap_dss_notify_event check_ovl_notify(
+ struct omap_overlay *ovl)
+{
+ struct overlay_cache_data *oc;
+ struct manager_cache_data *mc;
+
+ if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
+ return OMAP_DSS_NOTIFY_NONE;
+
+ oc = &dss_cache.overlay_cache[ovl->id];
+
+ if (!ovl->manager)
+ return oc->requested_events;
+
+ mc = &dss_cache.manager_cache[ovl->manager->id];
+
+ if (oc->requested_events == OMAP_DSS_NOTIFY_NONE)
+ return OMAP_DSS_NOTIFY_NONE;
+
+ return dss_mgr_notify_check_ovl(ovl, oc, mc, oc->requested_events);
+}
+
+static void dss_run_notifiers(void)
+{
+ struct overlay_cache_data *oc;
+ struct manager_cache_data *mc;
+ int i;
+ struct omap_overlay_manager *mgr;
+ struct omap_overlay *ovl;
+ enum omap_dss_notify_event events;
+
+ list_for_each_entry(mgr, &manager_list, list) {
+ events = check_mgr_notify(mgr);
+ if (events == OMAP_DSS_NOTIFY_NONE)
+ continue;
+
+ mc = &dss_cache.manager_cache[mgr->id];
+
+ mc->requested_events &= ~events;
+
+ dss_notifier_call_chain(events,
+ (void *)(long)mgr->id);
+ }
+
+ for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
+ ovl = omap_dss_get_overlay(i);
+
+ events = check_ovl_notify(ovl);
+ if (events == OMAP_DSS_NOTIFY_NONE)
+ continue;
+
+ oc = &dss_cache.overlay_cache[ovl->id];
+
+ oc->requested_events &= ~events;
+
+ dss_notifier_call_chain(events,
+ (void *)(long)ovl->id);
+ }
+}
+
+void omap_dss_lock_cache(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dss_cache.lock, flags);
+ BUG_ON(dss_cache.manager_cache[0].in_use);
+ dss_cache.manager_cache[0].in_use = true;
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+}
+EXPORT_SYMBOL(omap_dss_lock_cache);
+
+void omap_dss_unlock_cache(void)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&dss_cache.lock, flags);
+ BUG_ON(!dss_cache.manager_cache[0].in_use);
+ dss_cache.manager_cache[0].in_use = false;
+ dss_run_notifiers();
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+ omap_dss_mgr_apply(omap_dss_get_overlay_manager(0));
+}
+EXPORT_SYMBOL(omap_dss_unlock_cache);
static int omap_dss_set_device(struct omap_overlay_manager *mgr,
struct omap_dss_device *dssdev)
@@ -527,153 +687,89 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
}
-static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
-{
- unsigned long timeout = msecs_to_jiffies(500);
- struct manager_cache_data *mc;
- u32 irq;
- int r;
- int i;
- struct omap_dss_device *dssdev = mgr->device;
-
- if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
- return 0;
-
- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
- || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
- irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
- } else {
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
- enum omap_dss_update_mode mode;
- mode = dssdev->driver->get_update_mode(dssdev);
- if (mode != OMAP_DSS_UPDATE_AUTO)
- return 0;
-
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_FRAMEDONE
- : DISPC_IRQ_FRAMEDONE2;
- } else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC
- : DISPC_IRQ_VSYNC2;
- }
- }
+struct dss_wait_notify_event {
+ enum omap_dss_notify_event event;
+ int id;
+ struct completion compl;
+ struct list_head list;
+};
- mc = &dss_cache.manager_cache[mgr->id];
- i = 0;
- while (1) {
- unsigned long flags;
- bool shadow_dirty, dirty;
-
- spin_lock_irqsave(&dss_cache.lock, flags);
- dirty = mc->dirty;
- shadow_dirty = mc->shadow_dirty;
- spin_unlock_irqrestore(&dss_cache.lock, flags);
-
- if (!dirty && !shadow_dirty) {
- r = 0;
- break;
- }
+static struct {
+ struct notifier_block nb;
+ spinlock_t lock;
+ struct list_head list;
+} dss_wait_notify;
- /* 4 iterations is the worst case:
- * 1 - initial iteration, dirty = true (between VFP and VSYNC)
- * 2 - first VSYNC, dirty = true
- * 3 - dirty = false, shadow_dirty = true
- * 4 - shadow_dirty = false */
- if (i++ == 3) {
- DSSERR("mgr(%d)->wait_for_go() not finishing\n",
- mgr->id);
- r = 0;
- break;
- }
+static int dss_wait_notify_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct dss_wait_notify_event *e;
+ unsigned long flags;
- r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
- if (r == -ERESTARTSYS)
- break;
+ spin_lock_irqsave(&dss_wait_notify.lock, flags);
- if (r) {
- DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
- break;
- }
+ list_for_each_entry(e, &dss_wait_notify.list, list) {
+ if (!(event & e->event))
+ continue;
+ if ((long)data != e->id)
+ continue;
+ complete(&e->compl);
}
- return r;
+ spin_unlock_irqrestore(&dss_wait_notify.lock, flags);
+
+ return 0;
}
-int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+static int dss_wait_notify_event(enum omap_dss_notify_event event,
+ int id)
{
unsigned long timeout = msecs_to_jiffies(500);
- struct overlay_cache_data *oc;
- struct omap_dss_device *dssdev;
- u32 irq;
+ struct dss_wait_notify_event e = {
+ .event = event,
+ .id = id,
+ };
+ unsigned long flags;
int r;
- int i;
- if (!ovl->manager)
- return 0;
+ init_completion(&e.compl);
- dssdev = ovl->manager->device;
+ spin_lock_irqsave(&dss_wait_notify.lock, flags);
+ list_add_tail(&e.list, &dss_wait_notify.list);
+ spin_unlock_irqrestore(&dss_wait_notify.lock, flags);
- if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
- return 0;
+ r = omap_dss_request_notify(event, id);
+ if (r)
+ goto list_remove;
- if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
- || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
- irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
- } else {
- if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
- enum omap_dss_update_mode mode;
- mode = dssdev->driver->get_update_mode(dssdev);
- if (mode != OMAP_DSS_UPDATE_AUTO)
- return 0;
-
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_FRAMEDONE
- : DISPC_IRQ_FRAMEDONE2;
- } else {
- irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
- DISPC_IRQ_VSYNC
- : DISPC_IRQ_VSYNC2;
- }
- }
+ r = wait_for_completion_interruptible_timeout(&e.compl, timeout);
+ if (!r)
+ r = -ETIMEDOUT;
- oc = &dss_cache.overlay_cache[ovl->id];
- i = 0;
- while (1) {
- unsigned long flags;
- bool shadow_dirty, dirty;
-
- spin_lock_irqsave(&dss_cache.lock, flags);
- dirty = oc->dirty;
- shadow_dirty = oc->shadow_dirty;
- spin_unlock_irqrestore(&dss_cache.lock, flags);
-
- if (!dirty && !shadow_dirty) {
- r = 0;
- break;
- }
+ list_remove:
+ spin_lock_irqsave(&dss_wait_notify.lock, flags);
+ list_del(&e.list);
+ spin_unlock_irqrestore(&dss_wait_notify.lock, flags);
- /* 4 iterations is the worst case:
- * 1 - initial iteration, dirty = true (between VFP and VSYNC)
- * 2 - first VSYNC, dirty = true
- * 3 - dirty = false, shadow_dirty = true
- * 4 - shadow_dirty = false */
- if (i++ == 3) {
- DSSERR("ovl(%d)->wait_for_go() not finishing\n",
- ovl->id);
- r = 0;
- break;
- }
+ return r < 0 ? r : 0;
+}
- r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
- if (r == -ERESTARTSYS)
- break;
+static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
+{
+ int r = dss_wait_notify_event(OMAP_DSS_NOTIFY_GO_MGR, mgr->id);
- if (r) {
- DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
- break;
- }
- }
+ if (r == -ETIMEDOUT)
+ DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
+
+ return r;
+}
+
+int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
+{
+ int r = dss_wait_notify_event(OMAP_DSS_NOTIFY_GO_OVL, ovl->id);
+
+ if (r == -ETIMEDOUT)
+ DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
return r;
}
@@ -1004,6 +1100,146 @@ static void make_even(u16 *x, u16 *w)
*w = x2 - x1;
}
+static int dss_mgr_notify(struct omap_overlay_manager *mgr,
+ enum omap_dss_notify_event events)
+{
+ struct manager_cache_data *mc;
+ const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+ unsigned long flags;
+ enum omap_dss_notify_event fire_events = OMAP_DSS_NOTIFY_NONE;
+ struct omap_dss_device *dssdev = mgr->device;
+ int r = 0;
+
+ if (mgr->id >= num_mgrs)
+ return -EINVAL;
+
+ if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ dss_notifier_call_chain(events,
+ (void *)(long)mgr->id);
+ return 0;
+ }
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+
+ mc = &dss_cache.manager_cache[mgr->id];
+
+ if (!mc->manual_update && (events & OMAP_DSS_NOTIFY_UPDATE_MGR)) {
+ r = -EINVAL;
+ goto err_out;
+ }
+
+ fire_events = dss_mgr_notify_check(mgr, mc, events);
+
+ mc->requested_events |= events & ~fire_events;
+
+err_out:
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
+ if (fire_events != OMAP_DSS_NOTIFY_NONE)
+ dss_notifier_call_chain(fire_events,
+ (void *)(long)mgr->id);
+
+ return r;
+}
+
+int dss_mgr_notify_ovl(struct omap_overlay *ovl,
+ enum omap_dss_notify_event events)
+{
+ struct overlay_cache_data *oc;
+ struct manager_cache_data *mc;
+ const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
+ unsigned long flags;
+ enum omap_dss_notify_event fire_events = OMAP_DSS_NOTIFY_NONE;
+ struct omap_dss_device *dssdev;
+ int r = 0;
+
+ if (ovl->id >= num_ovls)
+ return -EINVAL;
+
+ if (!ovl->manager) {
+ dss_notifier_call_chain(events,
+ (void *)(long)ovl->id);
+ return 0;
+ }
+
+ dssdev = ovl->manager->device;
+
+ if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
+ dss_notifier_call_chain(events,
+ (void *)(long)ovl->id);
+ return 0;
+ }
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+
+ oc = &dss_cache.overlay_cache[ovl->id];
+ mc = &dss_cache.manager_cache[ovl->manager->id];
+
+ if (!mc->manual_update && (events & OMAP_DSS_NOTIFY_UPDATE_OVL)) {
+ r = -EINVAL;
+ goto err_out;
+ }
+
+ fire_events = dss_mgr_notify_check_ovl(ovl, oc, mc, events);
+
+ oc->requested_events |= events & ~fire_events;
+
+err_out:
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
+ if (fire_events != OMAP_DSS_NOTIFY_NONE)
+ dss_notifier_call_chain(fire_events,
+ (void *)(long)ovl->id);
+
+ return r;
+}
+
+int omap_dss_request_notify(enum omap_dss_notify_event events,
+ long value)
+{
+ int r;
+ struct omap_overlay_manager *mgr;
+ struct omap_overlay *ovl;
+
+ if (events & ~(OMAP_DSS_NOTIFY_MASK_MGR | OMAP_DSS_NOTIFY_MASK_OVL))
+ return -EINVAL;
+
+ if (events & OMAP_DSS_NOTIFY_MASK_MGR) {
+ mgr = omap_dss_get_overlay_manager(value);
+ if (!mgr)
+ return -EINVAL;
+ if (!mgr->notify)
+ return -ENOSYS;
+ r = mgr->notify(mgr, events & OMAP_DSS_NOTIFY_MASK_MGR);
+ if (r)
+ return r;
+ }
+ if (events & OMAP_DSS_NOTIFY_MASK_OVL) {
+ ovl = omap_dss_get_overlay(value);
+ if (!ovl)
+ return -EINVAL;
+ if (!ovl->notify)
+ return -ENOSYS;
+ r = ovl->notify(ovl, events & OMAP_DSS_NOTIFY_MASK_OVL);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(omap_dss_request_notify);
+
+int omap_dss_register_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&dss_notifier_list, nb);
+}
+EXPORT_SYMBOL(omap_dss_register_notifier);
+
+int omap_dss_unregister_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&dss_notifier_list, nb);
+}
+EXPORT_SYMBOL(omap_dss_unregister_notifier);
+
/* Configure dispc for partial update. Return possibly modified update
* area */
void dss_setup_partial_planes(struct omap_dss_device *dssdev,
@@ -1178,11 +1414,12 @@ static void dss_apply_irq_handler(void *data, u32 mask)
int i, r;
bool mgr_busy[MAX_DSS_MANAGERS];
u32 irq_mask;
+ unsigned long flags;
for (i = 0; i < num_mgrs; i++)
mgr_busy[i] = dispc_go_busy(i);
- spin_lock(&dss_cache.lock);
+ spin_lock_irqsave(&dss_cache.lock, flags);
for (i = 0; i < num_ovls; ++i) {
oc = &dss_cache.overlay_cache[i];
@@ -1220,7 +1457,8 @@ static void dss_apply_irq_handler(void *data, u32 mask)
dss_cache.irq_enabled = false;
end:
- spin_unlock(&dss_cache.lock);
+ dss_run_notifiers();
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
}
static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
@@ -1248,6 +1486,12 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
continue;
oc = &dss_cache.overlay_cache[ovl->id];
+ if (ovl->manager) {
+ mc = &dss_cache.manager_cache[ovl->manager->id];
+
+ if (mc->in_use)
+ continue;
+ }
if (!overlay_enabled(ovl)) {
if (oc->enabled) {
@@ -1319,6 +1563,9 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
mc = &dss_cache.manager_cache[mgr->id];
+ if (mc->in_use)
+ continue;
+
if (mgr->device_changed) {
mgr->device_changed = false;
mgr->info_dirty = true;
@@ -1377,6 +1624,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
oc = &dss_cache.overlay_cache[ovl->id];
+ if (ovl->manager) {
+ mc = &dss_cache.manager_cache[ovl->manager->id];
+
+ if (mc->in_use)
+ continue;
+ }
+
if (!oc->enabled)
continue;
@@ -1469,13 +1723,29 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
static int dss_mgr_enable(struct omap_overlay_manager *mgr)
{
+ struct manager_cache_data *mc = &dss_cache.manager_cache[mgr->id];
+ unsigned long flags;
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+ mc->enabled = true;
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
dispc_enable_channel(mgr->id, 1);
return 0;
}
static int dss_mgr_disable(struct omap_overlay_manager *mgr)
{
+ struct manager_cache_data *mc = &dss_cache.manager_cache[mgr->id];
+ unsigned long flags;
+
dispc_enable_channel(mgr->id, 0);
+
+ spin_lock_irqsave(&dss_cache.lock, flags);
+ mc->enabled = false;
+ dss_run_notifiers();
+ spin_unlock_irqrestore(&dss_cache.lock, flags);
+
return 0;
}
@@ -1491,6 +1761,11 @@ int dss_init_overlay_managers(struct platform_device *pdev)
spin_lock_init(&dss_cache.lock);
+ spin_lock_init(&dss_wait_notify.lock);
+ INIT_LIST_HEAD(&dss_wait_notify.list);
+ dss_wait_notify.nb.notifier_call = dss_wait_notify_callback;
+ omap_dss_register_notifier(&dss_wait_notify.nb);
+
INIT_LIST_HEAD(&manager_list);
num_managers = 0;
@@ -1522,6 +1797,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
mgr->set_manager_info = &omap_dss_mgr_set_info;
mgr->get_manager_info = &omap_dss_mgr_get_info;
mgr->wait_for_go = &dss_mgr_wait_for_go;
+ mgr->notify = &dss_mgr_notify;
mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
mgr->enable = &dss_mgr_enable;
@@ -1596,6 +1872,8 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)
kfree(mgr);
}
+ omap_dss_unregister_notifier(&dss_wait_notify.nb);
+
num_managers = 0;
}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 0f08025b1f0..fe53368019d 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -485,6 +485,12 @@ static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
return dss_mgr_wait_for_go_ovl(ovl);
}
+static int dss_ovl_notify(struct omap_overlay *ovl,
+ enum omap_dss_notify_event events)
+{
+ return dss_mgr_notify_ovl(ovl, events);
+}
+
static int omap_dss_set_manager(struct omap_overlay *ovl,
struct omap_overlay_manager *mgr)
{
@@ -631,6 +637,7 @@ void dss_init_overlays(struct platform_device *pdev)
ovl->set_overlay_info = &dss_ovl_set_overlay_info;
ovl->get_overlay_info = &dss_ovl_get_overlay_info;
ovl->wait_for_go = &dss_ovl_wait_for_go;
+ ovl->notify = &dss_ovl_notify;
ovl->supported_modes =
dss_feat_get_supported_color_modes(ovl->id);
diff --git a/include/linux/pvr.h b/include/linux/pvr.h
new file mode 100644
index 00000000000..49f64e00f84
--- /dev/null
+++ b/include/linux/pvr.h
@@ -0,0 +1,8 @@
+#ifndef __PVR_H
+#define __PVR_H
+
+struct sgx_platform_data {
+ unsigned long fclock_max;
+};
+
+#endif
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 892b97f8e15..26b3b9a1e8b 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -22,6 +22,7 @@
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/notifier.h>
#include <asm/atomic.h>
#define DISPC_IRQ_FRAMEDONE (1 << 0)
@@ -188,6 +189,48 @@ enum omap_dss_clk_source {
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
};
+/**
+ * Go event is triggered when all dss caches are clean (including shadow
+ * registers).
+ *
+ * This is used in xserver xv implementation to block writing to overlay until
+ * dss has completed reading same memory area.
+ *
+ * Example use in xv:
+ * If there is manual update triggered by gfx overlay first wait_for_go()
+ * doesn't block but wait_gfx() would block.
+ ** Frame 5 to first "buffer"
+ * wait_for_go()
+ * fill frame
+ * pan to first "buffer"
+ * update_window() for frame 1
+ * request update notify
+ ** Frame 6 to second "buffer" (wait_gfx() would block here)
+ * wait_for_go()
+ * fill frame
+ * pan to second "buffer"
+ ** Frame 7 to first "buffer"
+ * wait_for_go() blocking
+ * First update completes
+ * wait_for_go() returns
+ * update notify arrives
+ * update_window() for frame 2
+ * fill frame
+ * pan to third frame
+ *
+ * Update event is sent when manual update completes. Update event is not
+ * available for automatic update displays (returns -EINVAL).
+ */
+enum omap_dss_notify_event {
+ OMAP_DSS_NOTIFY_NONE = 0 << 0,
+ OMAP_DSS_NOTIFY_GO_MGR = 1 << 0,
+ OMAP_DSS_NOTIFY_UPDATE_MGR = 2 << 0,
+ OMAP_DSS_NOTIFY_MASK_MGR = 3 << 0,
+ OMAP_DSS_NOTIFY_GO_OVL = 1 << 2,
+ OMAP_DSS_NOTIFY_UPDATE_OVL = 2 << 2,
+ OMAP_DSS_NOTIFY_MASK_OVL = 3 << 2,
+};
+
/* RFBI */
struct rfbi_timings {
@@ -349,6 +392,8 @@ struct omap_overlay {
struct omap_overlay_info *info);
int (*wait_for_go)(struct omap_overlay *ovl);
+ int (*notify)(struct omap_overlay *ovl,
+ enum omap_dss_notify_event events);
};
struct omap_overlay_manager_info {
@@ -392,6 +437,8 @@ struct omap_overlay_manager {
int (*apply)(struct omap_overlay_manager *mgr);
int (*wait_for_go)(struct omap_overlay_manager *mgr);
+ int (*notify)(struct omap_overlay_manager *mgr,
+ enum omap_dss_notify_event events);
int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
int (*enable)(struct omap_overlay_manager *mgr);
@@ -584,10 +631,18 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
int omap_dss_get_num_overlays(void);
struct omap_overlay *omap_dss_get_overlay(int num);
+void omap_dss_lock_cache(void);
+void omap_dss_unlock_cache(void);
+
void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres);
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
+int omap_dss_register_notifier(struct notifier_block *nb);
+int omap_dss_unregister_notifier(struct notifier_block *nb);
+
+int omap_dss_request_notify(enum omap_dss_notify_event event, long value);
+
typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
diff --git a/include/video/sgx-util.h b/include/video/sgx-util.h
new file mode 100644
index 00000000000..4a5bd7ff50a
--- /dev/null
+++ b/include/video/sgx-util.h
@@ -0,0 +1,64 @@
+/*
+ * SGX utility functions
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SGX_UTIL_H
+#define __SGX_UTIL_H
+
+#include <linux/kernel.h>
+
+#define OMAPLFB_PAGE_SIZE 4096
+
+/* Greatest common divisor */
+static unsigned long gcd(unsigned long a, unsigned long b)
+{
+ unsigned long r;
+
+ if (a < b) {
+ r = a;
+ a = b;
+ b = r;
+ }
+
+ while ((r = a % b) != 0) {
+ a = b;
+ b = r;
+ }
+
+ return b;
+}
+
+/*
+ * Workout the smallest size that is aligned to both 4K (for the SGX)
+ * and line length (for the fbdev driver).
+ */
+static unsigned int sgx_buffer_align(unsigned stride, unsigned size)
+{
+ unsigned lcm;
+
+ if (!stride || !size)
+ return 0;
+
+ lcm = stride * OMAPLFB_PAGE_SIZE / gcd(stride,
+ OMAPLFB_PAGE_SIZE);
+
+ return roundup(size, lcm);
+}
+
+#endif /* __SGX_UTIL_H */